9
votes

We are making a device and it has 8 serial ports. It runs on the Monta Vista Pro5 kernel. And we are working in C.

Suppose: A device gets attached to ttyUSB0, ttyUSB1 and ttyUSB2. The next device gets connected to ttyUSB3 and another to ttyUSB4. How can I know which device gets attached to which port ?? ie ttyUSB0 or ttyUSB1 or so on. Is there a way to directly query the device and find which port it is attached to. Or, in C, open ttyUSB0, query it somehow and get some reply as to which device it is ??

A rather complicated way: do a stat of, say /dev/ttyUSB0. Get the device number. And search for this in /proc/bus/usb/devices and find the vendor id or something to identify the device.

Or: Is there some way to reserve ttyUSB0,ttyUSB1 and ttyUSB2 for one device, ttyUSB3 for another and so on when they are plugged in ? This way I will know which device is connected to which port.

Help please..... :)

Thanks in advance. Nubin Stanley

4
Let me see if I got this right. What you are trying to do is match the /dev/ttyUSBx nodes to the /proc/bus/usb device on the host system? Or are you trying to identify a serial device that is conencted to a usbserial adapter?thkala
stat'ing /dev/<whatever> will only get you the major and minor versions of the device. Those are not by any means connected to vendor/product/device ids.thkala
So you have a device with some usbserial IC (e.g. from FTDI) and you need to identify it ? Have you set vendor/product ids and serial number in the usbserial chip ?thkala

4 Answers

9
votes

You can use udev rules to create symbolic links just to your device:

(these rules go in /etc/udev/rules.d/-name.rules -- look at your udev documentation

KERNEL=="ttyUSB*", ATTRS{idVendor}=="<vendorid>", MODE="0666", SYMLINK+="mydev"

You have to specify your vendor id and/or product id for your device. Then those devices will be available at /dev/mydev in the above example.

You can also use various other parameters to create appropriate unique symbolic links for your use. Check udev man page.

3
votes

Here's my code, based on Alex Robinson's, but without global "except":

import os
from os.path import join

def find_tty_usb(idVendor, idProduct):
    """find_tty_usb('067b', '2302') -> '/dev/ttyUSB0'"""
    # Note: if searching for a lot of pairs, it would be much faster to search
    # for the enitre lot at once instead of going over all the usb devices
    # each time.
    for dnbase in os.listdir('/sys/bus/usb/devices'):
        dn = join('/sys/bus/usb/devices', dnbase)
        if not os.path.exists(join(dn, 'idVendor')):
            continue
        idv = open(join(dn, 'idVendor')).read().strip()
        if idv != idVendor:
            continue
        idp = open(join(dn, 'idProduct')).read().strip()
        if idp != idProduct:
            continue
        for subdir in os.listdir(dn):
            if subdir.startswith(dnbase+':'):
                for subsubdir in os.listdir(join(dn, subdir)):
                    if subsubdir.startswith('ttyUSB'):
                        return join('/dev', subsubdir)
1
votes

This Python code seems to find the /dev/ttyUSB number for the given vendor ID and product ID. Not hard to translate it to C. Parsing the output from hwinfo --usb can do the trick, too. The regx is:

"\s\sVendor:\susb\s0x([0-9a-f]{4}).*?\s\sDevice:\susb\s0x([0-9a-f]{4}).*?\s\sDevice\sFile:\s/dev/ttyUSB([0-9]+)"
import  glob
import  os
import  re

def find_usb_tty(vendor_id = None, product_id = None) :
    tty_devs    = []

    for dn in glob.glob('/sys/bus/usb/devices/*') :
        try     :
            vid = int(open(os.path.join(dn, "idVendor" )).read().strip(), 16)
            pid = int(open(os.path.join(dn, "idProduct")).read().strip(), 16)
            if  ((vendor_id is None) or (vid == vendor_id)) and ((product_id is None) or (pid == product_id)) :
                dns = glob.glob(os.path.join(dn, os.path.basename(dn) + "*"))
                for sdn in dns :
                    for fn in glob.glob(os.path.join(sdn, "*")) :
                        if  re.search(r"\/ttyUSB[0-9]+$", fn) :
                            #tty_devs.append("/dev" + os.path.basename(fn))
                            tty_devs.append(os.path.join("/dev", os.path.basename(fn)))
                        pass
                    pass
                pass
            pass
        except ( ValueError, TypeError, AttributeError, OSError, IOError ) :
            pass
        pass

    return tty_devs

print find_usb_tty()
0
votes

The best way to do this is would be to use libusb, but if that doesn't give you enough information about your devices (which it may not), then you'll have to use the /proc filesystem which the kernel makes available, specifically /proc/bus/usb/.

Have a read of this information on /proc/bus/usb: in particular on /proc/bus/usb/devices. But as you say, this is all a bit hacky!