【问题标题】:How to get USB vendor and product info programmatically on Linux?如何在 Linux 上以编程方式获取 USB 供应商和产品信息?
【发布时间】:2011-03-17 19:49:48
【问题描述】:

使用 udev 我已经能够获取某个 USB 设备的此信息:

idVendor: 13b1
idProduct: 0018
manufacturer:  
product: USB 2.0 Network Adapter ver.2 
serial: 00FFFF

现在我想获取与供应商和产品 ID 关联的完整字符串。我发现文件/usr/share/misc/usb.ids 包含我要查找的信息:

13b1  Linksys
        000b  WUSB11 v4.0 802.11b Adapter
        000d  WUSB54G Wireless Adapter
        0011  WUSB54GP v4.0 802.11g Adapter
        0018  USB200M 10/100 Ethernet Adapter
        001a  HU200TS Wireless Adapter
        001e  WUSBF54G 802.11bg
        0020  WUSB54GC 802.11g Adapter [ralink rt73]
        0023  WUSB54GR
        0024  WUSBF54G v1.1 802.11bg

但是,我不清楚我应该如何在我的应用程序中检索这些数据。是否有可用的 API 或者我应该只解析文件?如果我选择解析它,那么/usr/share/misc/usb.ids 是否总是正确的位置?

【问题讨论】:

  • 在我的系统上是/usr/share/usb.ids。找不到管理此文件位置的任何标准。
  • 这是最新版本:linux-usb.org/usb.ids 和提交界面:linux-usb.org/usb-ids.html
  • 在 Android 上,我的 C 程序使用 libusbhost,它为设备插入/移除提供回调。所有设备描述符都由 lib 提供。

标签: linux usb udev


【解决方案1】:

lsusb 命令查询有关当前插入的 USB 设备的信息。您可以使用其-d 选项来查询某个供应商/产品(但它似乎仅适用于当前插入的设备):

$ lsusb -d 0e21:0750
Bus 001 Device 005: ID 0e21:0750 Cowon Systems, Inc.

您可以显示所有设备的信息:

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 004: ID 0421:01c7 Nokia Mobile Phones
Bus 001 Device 003: ID 0bda:8187 Realtek Semiconductor Corp. RTL8187 Wireless Adapter
Bus 001 Device 005: ID 0e21:0750 Cowon Systems, Inc.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 002: ID 046d:c01b Logitech, Inc. MX310 Optical Mouse
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

您也可以让它变得冗长 (lsusb -v) 并打印 很多 的东西。

请注意,在 Linux 操作系统中访问有关系统的信息时,最好通过 shell 命令(例如lsusb)进行,而不是直接解析这些命令访问的系统文件。

【讨论】:

  • 那么我需要使用 popen 调用 lsusb 吗?
  • @Stacked,是的(对于 C),但这取决于您开发的语言。但无论哪种方式,您都将从流中读取内容,并通过 popen 调用 lsusb -d ... 似乎与使用描述解析整个文件相比,所需的击键次数更少。
【解决方案2】:

这个我自己没试过,不过libudev's udev_device_get_property_value应该是这样的;它在pulseaudio's udev-util.c 中用作udev_device_get_property_value(card, "ID_VENDOR_FROM_DATABASE"))

这是我刚刚基于udev-util.c 整理的一个小示例 - 请注意,我使用了带有 FTDI FT232 芯片的 Arduino Duemillanove,我使用udevadm 找到了它的 udev 路径(请参阅下面代码中的 cmets),然后我在下面的程序中对其进行了硬编码,udevl.c

// sudo apt-get install libudev-dev
// build with: gcc -o udevl -ludev -Wall -g udevl.c

#include <stdio.h>

#include <libudev.h>

int main( int argc, char **argv )
{
  const char *v;
  char t[256];
  struct udev *udev;
  struct udev_device *card = NULL;

  if (!(udev = udev_new())) {
      fprintf(stderr, "Failed to allocate udev context.\n");
      return -1;
  }

  // $ lsusb | grep FT232
  // Bus 002 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC    
  // $ udevadm info --name=/dev/ttyUSB0 --attribute-walk | grep "looking at device"
  // looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/ttyUSB0/tty/ttyUSB0'
  // (that one is under /sys)
  // hardcode that path below:

  // udev_get_sys_path(udev) for me: '/sys'
  sprintf(t, "%s/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/ttyUSB0/tty/ttyUSB0", udev_get_sys_path(udev));
  fprintf(stdout, " path: %s\n", t);

  card = udev_device_new_from_syspath(udev, t);
  fprintf(stdout, " udev_device: 0x%08X\n", (unsigned int)card);

  if ((v = udev_device_get_property_value(card, "ID_MODEL_FROM_DATABASE")) )
    fprintf(stdout, "got ID_MODEL_FROM_DATABASE: %s\n", v);
  else
    fprintf(stdout, "failed getting ID_MODEL_FROM_DATABASE: %s\n", v);

  fprintf(stdout, "Done.\n");

  if (card)
    udev_device_unref(card);

  if (udev)
    udev_unref(udev);

  return 0;
}

这个程序(附带 Arduino)输出:

$ ./udevl 
 path: /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/ttyUSB0/tty/ttyUSB0
 udev_device: 0x09FBF080
got ID_MODEL_FROM_DATABASE: FT232 USB-Serial (UART) IC
Done.

...“FT232 USB-Serial (UART) IC”是usb.ids 中 VID:PID 0403:6001 的正确条目。

希望这会有所帮助,
干杯!

【讨论】:

  • 如何初始化struct udev *udev;?结构 udev *udev = NULL?因为我的代码检查器为此给出了错误。谢谢。
【解决方案3】:

在我的 Ubuntu 系统上,lsusb(1) 手册页说 /var/lib/usbutils/usb.ids 是 id 文件的位置;实际上,有两个符号链接,其中一个是您的/usr/share/misc/usb.ids。在信任符号链接之前,我会信任实际位置:

$ ls -l /usr/share/misc/usb.ids /var/lib/misc/usb.ids /var/lib/usbutils/usb.ids
lrwxrwxrwx 1 root root     25 2010-04-29 18:08 /usr/share/misc/usb.ids -> /var/lib/usbutils/usb.ids
lrwxrwxrwx 1 root root     19 2010-04-29 18:08 /var/lib/misc/usb.ids -> ../usbutils/usb.ids
-rw-r--r-- 1 root root 368377 2009-11-06 09:26 /var/lib/usbutils/usb.ids

【讨论】:

    【解决方案4】:
    lsusb
    

    你会得到这样的东西

    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 009: ID 138a:0010 Validity Sensors, Inc. VFS Fingerprint sensor
    Bus 001 Device 008: ID 13d3:3491 IMC Networks 
    

    那么:ID 1d6b:0003 可以看作:vendor = 1d6bproduct = 0003

    【讨论】:

      【解决方案5】:

      您的 USB 设备不需要将供应商和产品 ID 与实际正确的名称相匹配。

      使用libusblsusb 之类的方式从设备本身获取此信息会更安全。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多