如何使用C语言在Linux中查找连接到USB串口的设备?

9
我们正在制作一个设备,它有8个串口。它运行在Monta Vista Pro5内核上。我们使用C语言进行开发。
假设:一个设备连接到ttyUSB0,ttyUSB1和ttyUSB2。下一个设备连接到ttyUSB3,另一个设备连接到ttyUSB4。我怎么知道哪个设备连接到了哪个端口?例如是ttyUSB0还是ttyUSB1等等。是否有一种直接查询设备并找出其所连接端口的方法?或者在C语言中打开ttyUSB0后,以某种方式查询,获取关于其所连接设备的回复?
以下是两种比较复杂的方法:一种是对/dev/ttyUSB0执行stat操作,获取设备号,然后在/proc/bus/usb/devices中搜索该设备号,以查找厂商ID或其他可用于识别该设备的信息;另一种则是当设备插入时为每个设备保留ttyUSB0、ttyUSB1和ttyUSB2,并为其他设备保留ttyUSB3等端口。通过这种方式,我将知道哪个设备连接到了哪个端口。
希望能得到帮助... :)
提前致谢, Nubin Stanley

让我看看我是否理解正确。你想做的是将/dev/ttyUSBx节点与主机系统上的/proc/bus/usb设备匹配吗?还是你试图识别连接到usb串行适配器的串行设备? - thkala
stat命令查询/dev/<whatever>只会返回设备的主要和次要版本号,这些与供应商/产品/设备ID没有任何关联。 - thkala
所以你有一个带有一些usbserial IC(例如来自FTDI)的设备,你需要识别它吗?你在usbserial芯片中设置了供应商/产品ID和序列号吗? - thkala
4个回答

9
您可以使用udev规则来创建符号链接,仅针对您的设备:
(这些规则位于/etc/udev/rules.d/-name.rules中,请查看您的udev文档)
KERNEL=="ttyUSB*", ATTRS{idVendor}=="<vendorid>", MODE="0666", SYMLINK+="mydev"

您需要为设备指定供应商 ID 和/或产品 ID。然后,在上面的示例中,这些设备将在 /dev/mydev 上可用。

您还可以使用各种其他参数为您的使用创建适当的唯一符号链接。请查看 udev 手册。


你提出的建议可以帮助我获得一个唯一的设备链接。但那不是我想要的。 - stanzlavos
我已经回答了你的问题 -“有没有一种方法可以为一个设备保留ttyUSB0、ttyUSB1和ttyUSB2,为另一个设备保留ttyUSB3”。如果你想要为一个设备保留设备条目,你需要知道该设备的详细信息。当然,如果它们是随机设备,这并没有帮助。 - rsmoorthy
哦,好的,现在我明白了。所以使用udev规则,我基本上可以告诉操作系统将Device0与特定的<VendorId>连接到ttyUSB0等等??? - stanzlavos
1
还有,在 "/etc/udev/rules.d/" 目录下没有 "-name.rules" 文件。所以我应该创建一个吗?而且在 "name.rules" 前面是不是应该加上一个'-'呢? :) - stanzlavos
1
很高兴它对你有用。实际上,我已经放置了 /etc/udev/rules.d/(number)-(yourname).rules,但是我输入了 '<' 和 '>',结果它成为了一个标签而没有被显示。最好把数字设定在 50 左右来定义用户规则。 - rsmoorthy
显示剩余8条评论

3

这是我的代码,基于Alex Robinson的代码,但没有全局的“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)

2
这段 Python 代码似乎可以找到给定供应商 ID 和产品 ID 的 /dev/ttyUSB 号码。将其翻译成 C 并不难。从 hwinfo --usb 中解析输出也可以实现此功能。正则表达式如下:
"\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

最好的方法是使用libusb,但如果它不能提供关于您的设备足够的信息(可能不会),那么您将不得不使用内核提供的/proc文件系统,特别是/proc/bus/usb/

阅读一下这个信息关于/proc/bus/usb:特别是关于/proc/bus/usb/devices。但正如你所说,这都有点hacky!


我目前正在使用libusb进行工作。但是,我不知道它是否会给我任何关于设备连接到哪个端口的指示......假设我使用libusb查询我的设备,我需要找出/dev/ttyUSB<x>中的“x”,以便我可以知道特定设备是/dev/ttyUSB0还是ttyUSB1等等 :) - stanzlavos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接