Search code examples
linuxlinux-kernelserial-portlinux-device-driveruart

Device node at /dev/tty* not getting created for uart serial driver


I have written a simple UART serial driver in embedded Linux running busybox with mdev rules. I have provided .dev_name as "ttyC2C" in my driver code.

static struct uart_driver serial_omap_reg = {
   .owner      = THIS_MODULE,
   .driver_name   = "Omap-C2C-Serial",
   .dev_name   = "ttyC2C",
   .nr      = OMAP_MAX_HSUART_PORTS,
   .cons    = NULL,
};

However the node is getting created in

./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
./sys/class/tty/ttyC2C0

/ # ls -l ./sys/class/tty/ttyC2C0
lrwxrwxrwx    1 root     0                0 Jan  1 00:14 ./sys/class/tty/ttyC2C0 -> ../../devices/platform/omap_c2c_uart.0/tty/ttyC2C0

/ # ls -l ./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
-r--r--r--    1 root     0             4096 Jan  1 00:14 dev
lrwxrwxrwx    1 root     0                0 Jan  1 00:14 device -> ../../../omap_c2c_uart.0
drwxr-xr-x    2 root     0                0 Jan  1 00:14 power
lrwxrwxrwx    1 root     0                0 Jan  1 00:14 subsystem -> ../../../../../class/tty
-rw-r--r--    1 root     0             4096 Jan  1 00:14 uevent
/ #

The mdev rules for tty are:

tty 0:5 0666
tty.* 0:0 0620

How to get device node as /dev/ttyC2C ?


Solution

  • You are confusing two things. The sysfs nodes you are seeing are indeed maintained by the kernel based on the kobject hierarchy. However device nodes are entirely a user space problem and can exist anywhere (although by convention are under /dev).

    So by hand you would first find the major:minor numbers:

    cat /sys/class/tty/ttyC2C0/dev
    

    And then:

    mknod /dev/ttyC2C0 c ${MAJOR} ${MINOR}
    

    However as you have already indicated you are using the fork of udev, mdev to handle the user space creation of device nodes. However the matching rules look odd to me. I assume mdev has the equivalent of udevadm which should help you write the matching rules. For example my USB tty driver can be queried like this:

    udevadm info -a -p /sys/class/tty/ttyUSB0
    

    And looking at the tree produced I can see a list of udev attributes which I could use to match. So in my case:

    KERNEL=="ttyUSB0", DRIVERS=="ftdi_sio", NAME="ttyUSB0"
    

    Would be enough to match (although my distro has a lot more complex matching rules to deal with dynamic setups).

    I'm guessing but I suspect the mapping rule you want would look more like:

    KERNEL=="ttyC2C", NAME="ttyC2C"
    

    Although you might need a bit more to ensure you get device nodes created for each port (minor number?).