【问题标题】:How to find which device is attached to a USB-serial port in Linux using C?如何使用 C 在 Linux 中查找连接到 USB 串行端口的设备?
【发布时间】:2011-05-10 17:29:35
【问题描述】:

我们正在制作一个设备,它有 8 个串行端口。它在 Monta Vista Pro5 内核上运行。我们正在使用 C 语言。

假设: 一个设备连接到 ttyUSB0、ttyUSB1 和 ttyUSB2。下一个设备连接到 ttyUSB3,另一个连接到 ttyUSB4。我怎么知道哪个设备连接到哪个端口?即 ttyUSB0 或 ttyUSB1 等。有没有办法直接查询设备并找到它连接到哪个端口。或者,在 C 语言中,打开 ttyUSB0,以某种方式查询它并得到一些关于它是哪个设备的回复??

一个相当复杂的方法:做一个统计,比如说/dev/ttyUSB0。获取设备号。然后在 /proc/bus/usb/devices 中搜索它并找到供应商 ID 或其他东西来识别设备。

或者: 插入时有什么方法可以为一个设备保留 ttyUSB0、ttyUSB1 和 ttyUSB2,为另一个设备保留 ttyUSB3,依此类推?这样我就知道哪个设备连接到哪个端口了。

请帮忙.....:)

提前致谢。 努宾斯坦利

【问题讨论】:

  • 让我看看我是否做对了。您要做的是将 /dev/ttyUSBx 节点与主机系统上的 /proc/bus/usb 设备相匹配?或者您是否正在尝试识别连接到 USB 串行适配器的串行设备?
  • stat'ing /dev/ 只会为您提供设备的主要和次要版本。这些与供应商/产品/设备 ID 没有任何关联。
  • 所以你有一个带有一些usbserial IC的设备(例如来自FTDI),你需要识别它吗?你有没有在usbserial芯片中设置供应商/产品ID和序列号?

标签: c


【解决方案1】:

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

/proc/bus/usb 上阅读this information:尤其是/proc/bus/usb/devices。但正如你所说,这有点 hacky!

【讨论】:

  • 我目前正在研究 libusb。但是话又说回来,我不知道它是否会给我任何关于设备连接到哪个端口的指示......假设我使用 libusb 查询我的设备,我需要以某种方式找出 / 中的“x” dev/ttyUSB 这样我就可以知道特定设备是 /dev/ttyUSB0 或 ttyUSB1 等等 :)
【解决方案2】:

您可以使用 udev 规则为您的设备创建符号链接:

(这些规则在 /etc/udev/rules.d/-name.rules 中——查看你的 udev 文档

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

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

您还可以使用各种其他参数来创建适合您使用的唯一符号链接。检查 udev 手册页。

【讨论】:

  • 您的建议将帮助我获得指向我设备的唯一链接。但这不是我想要的。
  • 随机连接了3个设备,分别占用ttyUSB0、ttyUSB1和ttyUSB2。现在的问题是,我不知道哪些设备连接到哪个端口。我需要一种方法来找出哪个设备连接到 ttyUSB0 或 ttyUSB1 或 ttyUSB2 :)
  • 我已经回答了您的问题 - “有没有办法为一个设备保留 ttyUSB0、ttyUSB1 和 ttyUSB2,为另一个设备保留 ttyUSB3……”。如果您想为一台设备保留设备条目,您需要了解该设备的详细信息。当然,如果它们是随机设备,这将无济于事。
  • 而且,我的“/etc/udev/rules.d/”中没有“-name.rules”文件。所以我应该只做一个吗?在“name.rules”之前有一个'-'对吗?? :)
  • 很高兴它对您有用。另外,我实际上已经输入了/etc/udev/rules.d/(number)-(yourname).rules,但是输入了'',所以它变成了一个标签并且没有显示出来。对于用户定义的规则,该数字最好在 50 左右。
【解决方案3】:

此 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()

【讨论】:

    【解决方案4】:

    这是我的代码,基于 Alex Robinson 的,但没有全局“例外”:

    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)
    

    【讨论】:

      猜你喜欢
      • 2021-11-07
      • 1970-01-01
      • 1970-01-01
      • 2013-08-06
      • 1970-01-01
      • 1970-01-01
      • 2023-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多