Ранее я уже затрагивал настройку правил udev в статье по настройке принт-сервера для двух принтеров. Но с обновлением OpenWRT до 18 версии, оказалось, что пакета udev в ней уже нет. Видимо, это связано с внедрением в OpenWRT своей собственной системы инициализации и менеджера процессов — Procd, который, так же, заменил и дополнил функционал более старой системы управления устройствами — Hotplug2.
Как это работает
В директории /etc/hotplug.d расположены несколько поддиректорий, таких как: block, iface, net, usb и т.д., со скриптами для обработки событий. Когда срабатывает событие триггера соответствующего типа, Procd выполнит все сценарии в поддиректории этого триггера в алфавитном порядке. Поэтому в именах скриптов обычно используется числовой префикс.
Пишем скрипты для Hotplug
Итак, к примеру, мы имеем те же два принтера, что и в вышеупомянутой статье: Xerox Workcentre 5020 и HP DesignJet 111 Roll.
При подключении принтеров к роутеру, в директории /dev/usb создаются файлы устройств: lp0, lp1, lp2 и т.д., в том порядке, в котором они были подключены. В конфиге нашего принт-сервера (p910nd) мы указываем, с какого порта на какое устройство отправлять данные на печать. Таким образом, если принтер в системе один — проблем не возникает. Но если принтеров — два и более, то нам придётся подключать их строго в определённом порядке, чтобы каждому принтеру каждый раз соответствовало то же самое устройство в системе, а это довольно неудобно.
Чтобы исключить эти неудобства, напишем hotplug-скрипты, которые будут при подключении принтеров создавать символьные ссылки с фиксированными именами для каждого из них. Создаём поддиректорию /etc/hotplug.d/usb (если ещё не создана), и помещаем в неё скрипт, например 22-xerox5020, примерно такого содержания:
XEROX5020_PRODUCT="924/4271/1"
SYMLINK="xerox5020"
if [ "${PRODUCT}" = "${XEROX5020_PRODUCT}" ];
then
if [ "${ACTION}" = "add" ];
then
DEVICE_NAME=$(ls /sys$DEVPATH/usbmisc | grep lp)
if [ -z ${DEVICE_NAME} ];
then
exit
fi
logger -t hotplug Device name of XEROX5020 is $DEVICE_NAME
ln -s /dev/usb/$DEVICE_NAME /dev/${SYMLINK}
logger -t hotplug Symlink from /dev/usb/$DEVICE_NAME to /dev/${SYMLINK} created
fi
if [ "${ACTION}" = "remove" ];
then
if [ -L /dev/${SYMLINK} ];
then
rm /dev/${SYMLINK}
logger -t hotplug Symlink /dev/${SYMLINK} removed
fi
fi
fi
Здесь переменные:
- ACTION — тип события: add — подключение, remove — отключение устройства;
- PRODUCT — идентификатор устройства вида: vendorid/productid/version;
- SYMLINK — имя символьной ссылки, которая будет создана для устройства;
- DEVICE_NAME — имя файла устройства в системе (lp0, lp1 и т.д.);
- DEVPATH — путь к файлам устройства в директории /sys.
Vendorid и productid устройства можно узнать, например, из вывода dmesg:
root@OpenWrt:~# dmesg | grep usb
.....
[74991.411950] usb 1-1.2: new high-speed USB device number 79 using ehci-platform
[74991.569073] usblp 1-1.2:1.1: usblp1: USB Bidirectional printer dev 79 if 1 alt 0 proto 2 vid 0x0924 pid 0x4271
.....
Или с помощью команды lsusb (входит в состав пакета usbutils):
root@OpenWrt:~# lsusb
Bus 001 Device 079: ID 0924:4271 Xerox
Bus 001 Device 003: ID 1058:25a2 Western Digital Technologies, Inc. Elements 25A2
Bus 001 Device 040: ID 03f0:0314 HP, Inc designjet 30/130 series
Bus 001 Device 002: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Видим, что для нашего Xerox: vid — 924, pid — 4271; для HP: vid — 3f0, pid — 314.
А чтобы узнать номер версии устройства, можно посмотреть расширенный вывод lsusb с помощью опции -v :
root@OpenWrt:~# lsusb -v -d 0924:4271
Bus 001 Device 079: ID 0924:4271 Xerox
Device Descriptor:
.....
idVendor 0x0924 Xerox
idProduct 0x4271
bcdDevice 0.01
.....
root@OpenWrt:~# lsusb -v -d 03f0:0314
Bus 001 Device 040: ID 03f0:0314 HP, Inc designjet 30/130 series
Device Descriptor:
.....
idVendor 0x03f0 HP, Inc
idProduct 0x0314 designjet 30/130 series
bcdDevice 1.00
.....
Аналогичный скрипт напишем и для нашего второго принтера (HP):
HPdj111roll_PRODUCT="3f0/314/100"
SYMLINK="hpdj111roll"
if [ "${PRODUCT}" = "${HPdj111roll_PRODUCT}" ];
then
if [ "${ACTION}" = "add" ];
then
DEVICE_NAME=$(ls /sys$DEVPATH/usbmisc | grep lp)
if [ -z ${DEVICE_NAME} ];
then
exit
fi
logger -t hotplug Device name of HP Designjet 111 roll is $DEVICE_NAME
ln -s /dev/usb/$DEVICE_NAME /dev/${SYMLINK}
logger -t hotplug Symlink from /dev/usb/$DEVICE_NAME to /dev/${SYMLINK} created
fi
if [ "${ACTION}" = "remove" ];
then
if [ -L /dev/${SYMLINK} ];
then
rm /dev/${SYMLINK}
logger -t hotplug Symlink /dev/${SYMLINK} removed
fi
fi
fi
Созданные скрипты Procd подхватывает на лету — даже не нужно ничего перезапускать. Давайте убедимся, что всё работает, как надо. Откроем системный лог и переподключим наши принтеры:
root@OpenWrt:~# logread -f
kern.info kernel: [82901.484970] usb 1-1.2: USB disconnect, device number 89
kern.info kernel: [82901.490759] usblp0: removed
user.notice hotplug: Symlink /dev/hpdj111roll removed
kern.info kernel: [82903.276970] usb 1-1.3: USB disconnect, device number 90
kern.info kernel: [82903.283082] usblp1: removed
user.notice hotplug: Symlink /dev/xerox5020 removed
kern.info kernel: [82910.481449] usb 1-1.3: new high-speed USB device number 91 using ehci-platform
kern.info kernel: [82910.638964] usblp 1-1.3:1.1: usblp0: USB Bidirectional printer dev 91 if 1 alt 0 proto 2 vid 0x0924 pid 0x4271
user.notice hotplug: Device name of XEROX5020 is lp0
user.notice hotplug: Symlink from /dev/usb/lp0 to /dev/xerox5020 created
kern.info kernel: [82913.551441] usb 1-1.2: new full-speed USB device number 92 using ehci-platform
kern.info kernel: [82913.714898] usblp 1-1.2:1.0: usblp1: USB Bidirectional printer dev 92 if 0 alt 0 proto 2 vid 0x03F0 pid 0x0314
user.notice hotplug: Device name of HP Designjet 111 roll is lp1
user.notice hotplug: Symlink from /dev/usb/lp1 to /dev/hpdj111roll created
Видим, что всё работает, как и задумано. Причём, обратите внимание, что я специально переподключил принтеры в другой последовательности: Xerox — был lp1, стал lp0; HP — наоборот — был lp0, стал lp1. Но симлинки на принтеры сохранились с фиксированными именами, что нам и требовалось. Теперь можем в конфиге принт-сервера указывать пути к принтерам, как: /dev/xerox5020 и /dev/hpdj111roll.
Подробнее о написании hotplug-скриптов можно почитать на странице документации OpenWRT:
OpenWrt Project » Documentation » User guide » Base system » Hotplug