Несколько лет назад пришлось решать следующую задачу. К хосту под управлением 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