I'm currently working on a serial port library which already uses special frameworks to get information about serial ports on the system. Though serial ports are a fundamental design in Unix—as an answer such as this one proves—I thought that a good way to test whether a file is a serial port is by testing the major mode of the character device and check whether this is actually a TTY or not.

Crawling on Internet, I could not find any documentation talking about the major modes of TTYs across unices. Well, there's only one Linux man page stating that ptmx has major mode 5.

Though I already asked about the implementation details of tty character device based on this Stack Overflow question, I thought I might ask the Unix Stack Exchange community to find out how stable the tty values are across Unix flavors.

So, I'm asking your help to build a knowledge base of the Major mode of all your tty files on your system(s), i.e.: what's the major mode of

  • real serial ports?
  • pseudo terminal (PTS) ports?
  • FTDI USB Serial ports?
  • other USB Serial ports?

To get the values for major mode of a character device, you shall look using:

% stat -f " * %N: %Hr%n" /dev/tty* /dev/pts/*
 * /dev/ttys001: 16
                 ^^- major mode

or using good old ls:

% ls -l /dev/ttys001
crw--w----  1 <user>  tty   16,   1 Apr 30 03:25 /dev/ttys001
                major mode -^^   ^^- minor mode

You can put information in answer of your own, or extend the community wiki answer with additional information.

  • 1
    @slm, asking the device major of all existing Unix variants sounds like a practical specific question with a verifiable answer. Nobody's asking about linux distros here. Apr 30, 2014 at 13:05
  • 1
    well, I'd prefer not to go ask about that in meta, but I've seen other posts (in other Q&A) working in a similar way, and afaict, the main goal of Stack Exchange is to gather a Knowledge Base. Though, I was considering it could be done by modifying my answer into a community edit, but then nobody would get a point reward.
    – zmo
    Apr 30, 2014 at 13:05
  • You could compile the results into a community answer though. (and let the people not too concerned about "votes" edit that one directly). Apr 30, 2014 at 13:07
  • 3
    I've retracted my close vote. There is one still on it from Anthon, I've asked him to retract it as well. NOTE to others It was agreed that this Q as a community wiki post should be kept.
    – slm
    Apr 30, 2014 at 13:26
  • 1
    @slm there's no CW police. Either it should be closed or remain open. CW is not an excuse to leave opened.
    – Braiam
    Apr 30, 2014 at 20:02

2 Answers 2


Unix version 7 (1979):

# ls -l /dev/console /dev/tty?*
crw--w--w- 1 root    0,  0 Sep 22 06:46 /dev/console
crw-rw-r-- 1 root    0,  1 Sep 22 05:47 /dev/tty1
crw-rw-r-- 1 root    0,  2 Sep 22 05:47 /dev/tty2

(no pty there yet)

Linux 3.2.0 (debian wheezy).

Note: you can also find these by searching /dev for owned by group tty and dialout. That's a Debian thing.

  • Virtual consoles
    • /dev/tty[0-9]*: 4
  • Real serial ports:
    • /dev/ttyS[0-9]+: 4
  • Pseudo terminals:
    • /dev/pts/[0-9]+: 136
    • /dev/pts/ptmx: 5
  • FTDI USB serial port:
    • /dev/ttyUSB[0-9]+: 188
  • USB serial port: (AVR embedded USB/Arduino Uno)
    • /dev/ttyACM[0-9]+: 166

Linux 3.4.0 (Android 4.4.2 / Nexus 5)

Note: has all linux ones plus:

  • ttyACM (cell modem control)
    • (no /dev entry, apparently): 166
  • ttyHSL (Bluetooth)
    • /dev/ttyHSL0: 247
  • ttyHS (Bluetooth)
    • /dev/ttyHS99: 248

Darwin 13.1.0 (MacOS 10.9.2):

  • Real serial ports:
    • /dev/ttys[0-9a-f]: 4
  • Pseudo terminals:
    • /dev/ttys[0-9]{3}: 16
  • FTDI USB serial port:
    • /dev/tty.usbserial.*: 18
  • USB serial port: (AVR embedded USB/Arduino Uno)
    • /dev/tty.usbmodem.*: 18

Solaris 10 x86/amd64:

  • Pseudo terminals:

    • /dev/pty[p-r][0-9a-f] (pty master): 25
    • /dev/tty[p-r][0-9a-f] (pty slave): 26
    • /dev/pts/[0-9]+: 24
    • /dev/ptmx: 23
  • Serial devices:

    • /dev/tty[abc...] aka /dev/term/[abc...] or /dev/tty0[012..] (uart serial, also ): 106
    • also as /dev/ttyd[012...] but with different interface (dial, modem) also on 106 but high minors.

OpenBSD 6.0

As documented in the commentary in /dev/MAKEDEV

  • PC/AT UART serial ports:
    • /dev/tty[0-7][0-9a-f]: 8
    • /dev/cua[0-7][0-9a-f]: 8
  • Cyclades serial ports:
    • /dev/ttyc*: 38
    • /dev/cuac*: 38
  • Virtio serial ports:
    • /dev/ttyVI*: 94
  • USB serial ports:
    • /dev/ttyU[0-3]: 66
    • /dev/cuaU[0-3]: 66
  • wscons terminals:
    • /dev/tty[C-J][0-b]: 12
  • Pseudo terminal master and slave (non-UNIX 98)
    • /dev/pty[p-zP-T][0-9a-zA-Z]: 6
    • /dev/tty[p-zP-T][0-9a-zA-Z]: 5

FreeBSD 10.0 and TrueOS

FreeBSD (and its derivatives such as TrueOS) is where your idea shows a fatal flaw. There is no major+minor device number scheme in FreeBSD.

The devfs pseudo-filesystem on FreeBSD, conventionally mounted at /dev, does not use a major+minor system for grouping devices into "major" classes at all. Rather, the rdev for the device is the same as its i-node number in the pseudo-filesystem, with i-nodes simply assigned in ascending order as device nodes are generated, depending from the exact hardware on the machine at hand at the time.

So device number cannot be used as a shortcut for isatty().

  • thank you for the android update, though can you give the kernel version as well? (uname -a). And I find it pretty weird that ttyACM has no /dev entry, where it is, then?
    – zmo
    Apr 30, 2014 at 16:40
  • And also, back in the days we were using /dev/cua*, the call unix device to call out on a modem. I'm not sure where those went, but it's weird they're using a tty for using a modem.
    – zmo
    Apr 30, 2014 at 16:40
  • 1
    note: you can find the kernel version Android was built with by looking under Settings > About. it's probably also worth noting the Android version and which ROM you're running (e.g. AOSP on a Nexus, TouchWiz on a Samsung, CyanogenMod that you flashed youself, etc.) as the Linux kernel is heavily patched in Android.
    – strugee
    May 1, 2014 at 1:52

On a linux 3.8.2 source tree:

$ cscope -dL1 '.*MAJOR' | grep -e TTY -e PTS -e PTY
drivers/s390/char/sclp_vt220.c .*MAJOR 31 #define SCLP_VT220_MAJOR TTY_MAJOR
drivers/staging/net/pc300_tty.c .*MAJOR 62 #define CPC_TTY_MAJOR CYCLADES_MAJOR
drivers/staging/sb105x/sb_pci_mp.h .*MAJOR 42 #define SB_TTY_MP_MAJOR 54
drivers/tty/rocket_int.h .*MAJOR 1168 #define TTY_ROCKET_MAJOR 46
drivers/tty/serial/apbuart.c .*MAJOR 38 #define SERIAL_APBUART_MAJOR TTY_MAJOR
drivers/tty/serial/atmel_serial.c .*MAJOR 79 #define SERIAL_ATMEL_MAJOR TTY_MAJOR
drivers/tty/serial/pmac_zilog.c .*MAJOR 93 #define PMACZILOG_MAJOR TTY_MAJOR
drivers/tty/serial/serial_txx9.c .*MAJOR 45 #define TXX9_TTY_MAJOR 204
drivers/tty/serial/serial_txx9.c .*MAJOR 50 #define TXX9_TTY_MAJOR TTY_MAJOR
drivers/usb/class/cdc-acm.h .*MAJOR 21 #define ACM_TTY_MAJOR 166
drivers/usb/serial/ipw.c .*MAJOR 55 #define IPW_TTY_MAJOR 240
include/linux/isdn.h .*MAJOR 41 #define ISDN_TTY_MAJOR 43
include/linux/isdn.h .*MAJOR 42 #define ISDN_TTYAUX_MAJOR 44
include/linux/usb/serial.h .*MAJOR 21 #define SERIAL_TTY_MAJOR 188
include/net/irda/ircomm_tty.h .*MAJOR 45 #define IRCOMM_TTY_MAJOR 161
include/uapi/linux/major.h .*MAJOR 13 #define PTY_MASTER_MAJOR 2
include/uapi/linux/major.h .*MAJOR 16 #define PTY_SLAVE_MAJOR 3
include/uapi/linux/major.h .*MAJOR 17 #define TTY_MAJOR 4
include/uapi/linux/major.h .*MAJOR 18 #define TTYAUX_MAJOR 5
include/uapi/linux/major.h .*MAJOR 144 #define UNIX98_PTY_MASTER_MAJOR 128
include/uapi/linux/major.h .*MAJOR 146 #define UNIX98_PTY_SLAVE_MAJOR (UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
include/uapi/linux/major.h .*MAJOR 169 #define IBM_TTY3270_MAJOR 227
net/bluetooth/rfcomm/tty.c .*MAJOR 40 #define RFCOMM_TTY_MAJOR 216

UNIX98_PTY_MAJOR_COUNT is 8 which gives your pty-slave = 136, but doesn't seem to be otherwise used.

Another one that comes to mind:

drivers/tty/hvc/hvc_console.c .*MAJOR 48 #define HVC_MAJOR 229

(the XEN serial devices).

Now, there are also a number with a dynamically allocated major number. For instance:

    tty_drv->driver_name = "sdio_uart";
    tty_drv->name =   "ttySDIO";
    tty_drv->major = 0;  /* dynamically allocated */

You can look for all the calls to tty_register_driver where driver->major is 0.

Some you can also supply the major number as a kernel/module parameter. For instance hso.

So on Linux, it sounds that you'd have to look up the major in /proc/devices and decide based on the driver name rather than the major number.

  • It's a great answer, though I'd say it's more a good answer on how this is implemented in the question I asked on SO… Whereas here I'm more asking about the modes on the different flavours of unix.
    – zmo
    Apr 30, 2014 at 15:03
  • @zmo, but that's telling you you can't rely on major numbers on Linux alone as there are a few static ones, but the rest is dynamic and/or chosen by the administrator. Apr 30, 2014 at 15:13
  • 1
    sure, you're definitely making a point, though I still think it's more a fit on the other Q, because here I'm more wondering how stable this is accross flavors of Unix. Like it looks like Darwin and Linux use the major mode 4 for the "real" serial ports. Does that mean this is something defined in UNIX98, or in POSIX? Or is this a convention that's pretty old but that could be changed because some unix kernel developer is phobic of the number 4?
    – zmo
    Apr 30, 2014 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.