Однозначный tty для USB-устройств в FreeBSD

в 9:51, , рубрики: Без рубрики

Несколько лет назад пришлось решать следующую задачу. К хосту под управлением FreeBSD подключается несколько однотипных USB-устройств. Программное обеспечение хоста работает с ними через файлы символьных устройств. Понятно, что при произвольном переключении шнурков USB или при перезагрузке хоста, файлы символьных устройств нумеруются (в общем случае) совсем не в том порядке, как при первом подключении. В моем случае USB-устройства — конвертеры интерфейсов на которых висят шины RS-485 с приборами. Никаких возможностей автоматически определить по приборам в шине, какие шины повисли на каком порту нет. Таким образом непонятно, какие файлы символьных устройств каким физическим устройствам соответствуют в данный момент. Кому интересно решение, прошу под кат. Несмотря на специфичность задачи, способ универсальный.

Идея. При подключении USB-устройства, определять имя файла символьного устройства, которое выдано системой (типа ttyUx), производителя, тип, s/n устройства и создавать в /dev ссылку с заранее определенным именем для этого s/n, указывающую на уже известный ttyUx. Т.о. наш софт всегда будет работать с известными именами файлов символьных устройств — предопределенными ссылками, которые соответствуют конкретному устройству.

Реализация.

Для того, чтоб узнать подробности про USB-устройство:

usbconfig dump_device_desc
...
ugen1.2: <USB-Serial Controller Prolific Technology Inc.> at usbus1, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON
  bLength = 0x0012 
  bDescriptorType = 0x0001 
  bcdUSB = 0x0110 
  bDeviceClass = 0x0000 
  bDeviceSubClass = 0x0000 
  bDeviceProtocol = 0x0000 
  bMaxPacketSize0 = 0x0040 
  idVendor = 0x067b 
  idProduct = 0x2303 
  bcdDevice = 0xa7d4 
  iManufacturer = 0x0001  <Prolific Technology Inc.>
  iProduct = 0x0002  <USB-Serial Controller>
  iSerialNumber = 0x0003  <0000A7D4>
  bNumConfigurations = 0x0001 
...

Редактируем /etc/devd.conf. Пишем что-то вроде:

# When the ICPCON USB Converter appear...
attach 100 {
        match "device-name" "uplcom[0-9]";
        match "vendor" "0x067b";
        match "product" "0x2303";
        match "release" "0xa7d4";
        action "/usr/local/bin/uplcom2ttyU $device-name /dev/icpcon1";
};
detach 100 {
        match "device-name" "ugen+";
        match "vendor" "0x067b";
        match "product" "0x2303";
        match "release" "0xa7d4";
        action "rm /dev/icpcon1";
};

Думаю, смысл этой записи понятен. Осталось «нарисовать» uplcom2ttyU, который создаст ту самую ссылку, однозначную, в примере — /dev/icpcon1. Для каждого устройства нужно делать в devd.conf соответствующую запись. Не забываем менять имя ссылки (у меня /dev/icpcon1) в двух местах: attach, detach, — мы же хотим, чтоб ссылка исчезала с отключением устройства.

cat /usr/local/bin/uplcom2ttyU
#!/bin/sh
# arg #1 - $device-name from devd.conf - uplcomX; arg #2 - new link to ttyUX - /dev/.....
ln -s $(echo /dev/$1 | sed 's/uplcom/ttyU/g') $2

Видно, что запись uplcom меняется на ttyU, поскольку в /dev система создает именно ttyUx, где x совпадает с номером uplcom.

Вот и все. Однако, до сих пор целостного описания решения подобной проблемы не найти в Интернет. Разве только мои посты на форуме одного известного ресурса.

Автор: jim1406

Источник

Поделиться

* - обязательные к заполнению поля