Как программно получить информацию о поставщике и продукте USB в Linux?

Используя udev, я смог получить эту информацию для определенного USB-устройства:

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

Теперь я хочу получить полные строки, связанные с идентификаторами поставщиков и продуктов. Я обнаружил, что файл /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 будет правильным местоположением?


person StackedCrooked    schedule 19.07.2010    source источник
comment
В моей системе это /usr/share/usb.ids. Не удается найти какой-либо стандарт, определяющий место для этого файла.   -  person P Shved    schedule 19.07.2010
comment
Вот самая последняя версия: linux-usb.org/usb.ids и интерфейс для отправки: linux-usb.org/usb-ids.html   -  person endolith    schedule 22.07.2010
comment
В Android моя программа на C использует libusbhost, который обеспечивает обратные вызовы для вставки/удаления устройства. Все дескрипторы устройств доступны в lib.   -  person m-ric    schedule 11.10.2012


Ответы (5)


Команда 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 гораздо предпочтительнее делать это с помощью команд оболочки (таких как lsusb), чем напрямую анализировать системные файлы, к которым эти команды обращаются.

person P Shved    schedule 19.07.2010
comment
Значит, мне нужно вызывать lsusb с помощью popen? - person StackedCrooked; 19.07.2010
comment
@Stacked, да (для C), но это зависит от языка, на котором вы разрабатываете. Но в любом случае вы будете читать что-то из потока, и вызов lsusb -d ... через popen, похоже, требует меньшего количества нажатий клавиш, чем анализ всего файла с описаниями. - person P Shved; 19.07.2010

Сам не пробовал, но значение udev_device_get_property_value от libudev должно быть таким; он используется в udev-util компании pulseaudio. .c как udev_device_get_property_value(card, "ID_VENDOR_FROM_DATABASE")).

Вот небольшой пример, который я только что собрал на основе udev-util.c — обратите внимание, что я использовал Arduino Duemillanove с чипом FTDI FT232, чей путь udev я нашел с помощью udevadm (см. комментарии в коде ниже), а затем я жестко закодировал его в ниже программа, 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" является правильной записью для VID:PID 0403:6001 в usb.id.

Надеюсь, это поможет,
Ура!

person sdaau    schedule 19.03.2013
comment
как инициализировать структуру udev *udev;? структура udev *udev = NULL? Потому что моя программа проверки кода выдает ошибку для этого. Спасибо. - person sree; 28.01.2015

В моей системе 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
person sarnold    schedule 19.07.2010

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 = 1d6b и product = 0003

person amdan    schedule 28.10.2019

Вашему USB-устройству не нужно сопоставлять идентификаторы производителя и продукта с фактическими правильными именами.

Было бы безопаснее получить эту информацию от самого устройства с помощью чего-то вроде libusb или lsusb.

person leppie    schedule 19.07.2010