Open xerxes1986 opened 9 years ago
Hi Paul,
On RHEL we use the following udev rule which is working perfectly for us:
SUBSYSTEM == "tty", ATTRS{manufacturer} == "FTDI", ATTRS{product} == "USB <-> Serial", SYMLINK = "ttyJUMO", GROUP = "usb", MODE = "0664" SUBSYSTEM == "usb", ATTRS{manufacturer} == "FTDI", ATTRS{product} == "USB <-> Serial", GROUP = "usb", MODE = "0664"
I think we also managed to get udev rules working on ubuntu, i will look for them in the next days.
Hi Felix,
The way I understand udev is that any device matching the list of rules in a udev file (and the first match) will trigger the event, so your second line there doesn't matter. The first line doesn't work on our computers and I think the reason is the "SUBSYSTEM == "tty"" part. If I run udevadm info -n /dev/ttyUSB0 I get:
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device
'/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/ttyUSB0/tty/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device
'/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/ttyUSB0':
KERNELS=="ttyUSB0"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ftdi_sio"
ATTRS{port_number}=="0"
ATTRS{latency_timer}=="1"
looking at parent device
'/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0':
KERNELS=="3-2:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="ftdi_sio"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceSubClass}=="ff"
ATTRS{bInterfaceProtocol}=="ff"
ATTRS{bNumEndpoints}=="02"
ATTRS{supports_autosuspend}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}=="00"
ATTRS{interface}=="USB <-> Serial"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2':
KERNELS=="3-2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="2"
ATTRS{idVendor}=="0403"
ATTRS{speed}=="12"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{busnum}=="3"
ATTRS{devnum}=="5"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="90mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0400"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="6835546"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="FTDI"
ATTRS{removable}=="removable"
ATTRS{idProduct}=="6001"
ATTRS{bDeviceClass}=="00"
ATTRS{product}=="USB <-> Serial"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3':
KERNELS=="usb3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="01"
ATTRS{devpath}=="0"
ATTRS{idVendor}=="1d6b"
ATTRS{speed}=="480"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{authorized_default}=="1"
ATTRS{busnum}=="3"
ATTRS{devnum}=="1"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="0mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="4"
ATTRS{bcdDevice}=="0313"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{serial}=="0000:00:14.0"
ATTRS{version}==" 2.00"
ATTRS{urbnum}=="70"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 3.13.0-53-generic xhci_hcd"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="0002"
ATTRS{bDeviceClass}=="09"
ATTRS{product}=="xHCI Host Controller"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{irq}=="43"
ATTRS{subsystem_vendor}=="0x1028"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0330"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{dma_mask_bits}=="64"
ATTRS{local_cpus}=="00000000,00000000,00000000,00000000,00000000,00000000,00000000,0000000f"
ATTRS{device}=="0x1e31"
ATTRS{enable}=="1"
ATTRS{msi_bus}==""
ATTRS{local_cpulist}=="0-3"
ATTRS{vendor}=="0x8086"
ATTRS{subsystem_device}=="0x0581"
ATTRS{numa_node}=="-1"
ATTRS{d3cold_allowed}=="1"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
The way the rules are written, you should be able to use a combination of exactly one device and one of that device's parents attributes. However, this doesn't work for whatever reason on Ubuntu so for the rule to work I need to remove the SUBSYSTEM == "tty" part, but I don't see why this would screw up the symlink since this is a matching rule not an action rule.
I did however find a solution by changing "SYMLINK" to "NAME", which creates the virtual serial port with the assigned name. I'm not sure if this will have any issues in the future though.
Paul Turner
On Wed, Jun 10, 2015 at 3:12 AM, Felix Bachmair notifications@github.com wrote:
Hi Paul,
On RHEL we use the following udev rule which is working perfectly for us:
SUBSYSTEM == "tty", ATTRS{manufacturer} == "FTDI", ATTRS{product} == "USB <-> Serial", SYMLINK = "ttyJUMO", GROUP = "usb", MODE = "0664" SUBSYSTEM == "usb", ATTRS{manufacturer} == "FTDI", ATTRS{product} == "USB <-> Serial", GROUP = "usb", MODE = "0664"
— Reply to this email directly or view it on GitHub https://github.com/psi46/elComandante/issues/14#issuecomment-110645584.
Since this issue is still open, I would like to suggest an approach to this problem that sidesteps the udev configuration step by instead handling this in code. This uses the pyudev
package to interact with udev at runtime to identify which connected device is the Keithley, which is the JUMO.
#!/usr/bin/env python2
from __future__ import print_function
import pyudev
context = pyudev.Context()
def device_by_id(id_vendor, id_product):
match_devices = []
for dev in context.list_devices(subsystem='tty'):
try:
ancestor = dev.parent.parent.parent
attribs = ancestor.attributes
except AttributeError:
continue
try:
idVendor = attribs['idVendor']
idProduct = attribs['idProduct']
except KeyError:
continue
if idVendor == id_vendor and idProduct == id_product:
match_devices.append(dev)
return match_devices
def find_single_device(id_vendor, id_product):
devs = device_by_id(id_vendor, id_product)
if len(devs) == 0:
msg = "Unable to find device with idVendor={} and idProduct={}"
raise ValueError(msg.format(id_vendor, id_product))
elif len(devs) > 1:
msg = "Found multiple devices with idVendor={} and idProduct={}"
raise ValueError(msg.format(id_vendor, id_product))
else:
return devs[0].device_node
keithley_dev = find_single_device('06cd', '0121')
print("Found Keithley on port", keithley_dev)
jumo_dev = find_single_device('0403', '6001')
print("Found JUMO on port", jumo_dev)
Which, on our system, gives the output:
Found Keithley on port /dev/ttyUSB2
Found JUMO on port /dev/ttyUSB0
Now, a problem that this doesn't solve is if the devices get mounted with incorrect permissions. For this, a UDEV rule would likely still be required. However, I'm not sure if this is a problem that many people run into.
I also cannot vouch for how platform independent this is. For example, it's possible that different platforms will handle the device nesting differently, so the line dev.parent.parent.parent
would have to be modified.
Found answer @ https://www.indilib.org/forum/mounts/3757-port-failure-error-inappropriate-ioctl-for-device.html Thanks to ADSF. "Just FYI for the people googling this in the future: I had this exact same problem with a CP201x usb-serial adapter. The solution is to change all the "ATTR" references to "ATTRS" in the udev rules. That's it. That's the magic incantation. I hoped this helped someone. In this case changing ATTR{manufacturer}=="Prolific Technology Inc." to ATTRS{manufacturer}=="Prolific Technology Inc." most likely would have fixed OP's issue."
Works for me (py3.8, linux kernel 3.14): ACTION=="add",ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001",SYMLINK+="ttyUSB_ftdi"
Just for future people using cfangmeiers answer. The code they wrote works if you update device_by_id like this:
def device_by_id(id_vendor, id_product):
match_devices = []
for dev in context.list_devices():
try:
if(dev.properties['ID_VENDOR_ID'] == id_vendor and dev.properties['ID_MODEL_ID'] == id_product):
match_devices.append(dev)
except KeyError:
continue
return match_devices
I have finally found a udev rule that assigns a consistent link to the coldbox (instead of the random /dev/ttyUSB#) which is:
The problem is that this symlink creates a link to the wrong thing. For example, the coldbox is /dev/ttyUSB0 but the symlink /dev/ttyUSBColdbox points to bus/usb/003/005 instead of /dev/ttyUSB0. When trying to run the coldbox client, it gives the following error:
The solution I've found for now is to use the automatically created symlinks in
/dev/serial/by-id/
:I think these symlinks will work, but I was hoping the symlink option in udev would work as it seems like it would be more consistent across platforms. Has anyone gotten this to work?