Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have USB cellular modem attached to an ALIX 3d2 board running voyage linux (which is based on Debian Squeeze). The modem registers itself as a TTY device, and so by default, udev will create TTY devices named "ttyUSB0" through "ttyUSB3" in /dev. However, there may be other USB-to-Serial devices attached and I'd like to have a known reference to the modem. So, I wrote a simple udev rule to make a link from the modem to /dev/ttyModem{0-3} however, the only way I could find to automatically handle the numbering was through the %n variable in udev, which has the problem of creating /dev/ttyModem{4-7} if a four port USB-to-Serial adapter is enumerated before the modem. I found some references to a %e variable in old udev documentation that would do just what I need, but it appears to have been removed some time ago.

Luckily, there is a port number that can be referenced from the device for each tty device, so I should be able to handle the numbering manually. I can create a link based on the port number, but whenever I attempt to use both the port number and the USB vendorID+productID, the rule is no longer applied. I suspect that I might be violating the "one single parent device" rule somewhere, as these attributes are recognized in different devices according to udevadm info, but as far as I can tell, all attributes should be coming from one device and its parent.

Here are the rules I've applied:

This rule works, and is what I started with, but the number it generates may not start at 0.

SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="1199", ATTRS{idProduct}=="0028", SYMLINK+="ttyUSBID%n"

So I attempted to specify the port number using four rules like this one, however, this fails, I think because it violates the "one single parent device" rule.

SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{port_number}=="0", ATTRS{idVendor}=="1199", ATTRS{idProduct}=="0028", SYMLINK+="ttyFailingPort0"

Every condition on this rule should come from the same node, so this rule (which works as you'd expect) should be able to reference a parent node.

SUBSYSTEMS=="usb-serial", KERNELS=="ttyUSB*", ATTRS{port_number}=="0", SYMLINK+="ttyPortNumberChild0"

However, this rule fails, and I have no idea why.

SUBSYSTEMS=="usb-serial", KERNELS=="ttyUSB*", ATTRS{idVendor}=="1199" ATTRS{port_number}=="0", SYMLINK+="ttyFailingPortNumber0

And here is the output of udevadm info --attribute-walk for port0, port1, port2, port3. The second device from the top contains the port number, and the fourth device contains the identifying USB information.

I realize this is a bit of an XY problem, so if you know of a better way to give the modem a constant name, feel free to post that as your answer.

share|improve this question

2 Answers 2

The modem rules should match ACTION=="add", SUBSYSTEM=="tty" combined with idVendor, idProduct and port_number attributes:

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1199", ATTRS{idProduct}=="0028", ATTRS{port_number}=="0", SYMLINK+="ttyPort0"
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1199", ATTRS{idProduct}=="0028", ATTRS{port_number}=="1", SYMLINK+="ttyPort1"
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1199", ATTRS{idProduct}=="0028", ATTRS{port_number}=="2", SYMLINK+="ttyPort2"
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1199", ATTRS{idProduct}=="0028", ATTRS{port_number}=="3", SYMLINK+="ttyPort3"

Also check if any of the existing symlinks in /dev/serial/by-id (helps if your modem has a unique serial number) or /dev/serial/by-path (works if you always plug in your modem in to the same USB port) would work for your purpose.

share|improve this answer
    
Unfortunately, that didn't work. I also tried the simplest form of that method I could think of ENV{ID_VENDOR_ID}=="1199" SYMLINK+="ttyPortNumber0", but even that didn't get triggered. I confirmed with udevadem info --query=all that the environment variable should be added, but I'm at a loss as to why it doesn't seem to recognize it in the rule. As for the other symlinks, This rule needs to work for any modem of the same model, and when it's plugged in to any USB port, so the only thing I would do with those is copy them and rename them, which is the whole point of using udev. –  isidor3 Jun 12 '13 at 16:10
    
could you try just ACTION=="add", SUBSYSTEM=="tty", ATTRS{port_number}=="0", SYMLINK+="ttyPort0"? –  Alex P. Jun 12 '13 at 17:40
    
That rule works as you'd expect, it doesn't solve my problem, but it correctly recognized the modem's port0 device. –  isidor3 Jun 12 '13 at 18:04
up vote 0 down vote accepted

I ended up working around the "only one parent" limitation by splitting up the configuration between multiple rules. For those interested, here is the code I ended up with:

ACTION!="add", GOTO="modem_rules_end"
SUBSYSTEM!="tty" GOTO="modem_rules_end"

#ModemType1
ATTRS{idVendor}=="1199", ATTRS{idProduct}=="0028", GOTO="type1_rules_begin"
GOTO="type1_rules_end"
LABEL="type1_rules_begin"

ATTRS{port_number}=="0", SYMLINK:="ttyType1_0"
ATTRS{port_number}=="1", SYMLINK:="ttyType1_1"
ATTRS{port_number}=="2", SYMLINK:="ttyType1_2"
ATTRS{port_number}=="3", SYMLINK:="ttyType1_3"

LABEL="type1_rules_end"
LABEL="modem_rules_end"
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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