Иногда возникает желание работать с устройством, подключенным по USB, не держа его на столе рядом с ноутбуком. У меня таким устройством является китайский гравёр с лазером на 500 мВт, штука довольно неприятная при близком контакте. Помимо непосредственной опасности для глаз, в процессе работы лазера выделяются токсичные продукты горения, поэтому устройство должно находится в хорошо проветриваемом помещении, и желательно изолированно от людей. А как же таким устройством управлять? Ответ на данный вопрос я случайно нашел, просматривая репозиторий OpenWRT в надежде найти достойное применение старенькому роутеру D-Link DIR-320 A2. Для подключения решил использовать описываемый на Хабре ранее USB over IP tunnel, однако все инструкции по его установке успели потерять актуальность, поэтому пишу свою.

OpenWRT — операционная система, не нуждающаяся в представлении, поэтому её установку расписывать не буду. Для своего роутера взял последний стабильный релиз OpenWrt 19.07.3, и подключил его к основной точке доступа по Wi-Fi в качестве клиента, выбрав режим lan, чтобы не мучать файрвол.

Серверная часть


Действуем согласно официальной инструкции. После подключения по ssh устанавливаем необходимые пакеты.

root@OpenWrt:~# opkg update
root@OpenWrt:~# opkg install kmod-usb-ohci usbip-server usbip-client

Далее подключаем к USB-порту роутера наше устройство (в моём случае устройства: USB-хаб, флешку, на которую смонтирована файловая система роутера (ввиду нехватки места на внутреннем накопителе), и, непосредственно, гравёр).

Пробуем вывести список подключенных устройств:

root@OpenWrt:~# usbip list -l

Пусто.

Путём гугления был найден виновник, им оказалась библиотека libudev-fbsd.
Вытаскиваем руками из репозитория последнюю рабочую версию libudev_3.2-1 из релиза OpenWRT 17.01.7 под свою архитектуру, в моём случае это libudev_3.2-1_mipsel_mips32.ipk. С помощью wget/scp загружаем её в память роутера и переустанавливаем

root@OpenWrt:~# opkg remove --force-depends libudev-fbsd
root@OpenWrt:~# opkg install libudev_3.2-1_mipsel_mips32.ipk

Проверяем:

root@OpenWrt:~# usbip list -l
 - busid 1-1.1 (090c:1000)
   Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) : Flash Drive (090c:1000)

 - busid 1-1.4 (1a86:7523)
   QinHeng Electronics : HL-340 USB-Serial adapter (1a86:7523)

Китаец, подключенный в USB-хаб, получил bsuid 1-1.4. Запомнили.

Теперь запускаем демон:

root@OpenWrt:~# usbipd -D

и биндим китайца

root@OpenWrt:~# usbip bind -b 1-1.4
usbip: info: bind device on busid 1-1.4: complete

Проверяем, что всё работает:

root@OpenWrt:/home# netstat -alpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:3240            0.0.0.0:*               LISTEN      1884/usbipd

Чтобы далее биндить девайс автоматически, подредактируем /etc/rc.local, добавив перед exit 0 следующее:

usbipd -D &
sleep 1
usbip bind -b 1-1.4

Клиентская часть


Попробуем поключить устройство к Windows 10, используя вышеупомянутую инструкцию с openwrt.org. Сразу скажу: затея обречена на провал. Во-первых, рассматривается только Windows 7 x64. Во-вторых, дана ссылка на тред на sourceforge.net, в котором предлагается скачать с дропбокса патченый в 2014 году драйвер. При попытке запустить его под Windows 10 и подключиться к нашему устройству получаем ошибку:

c:\Utils\usbip>usbip -a 192.168.31.203 1-1.4
usbip for windows ($Id$)

*** ERROR: cannot find device

Связано это с тем, что клиент не работает с сервером, собранным под ядро старше версии 3.14.
Сервер usbip под OpenWRT 19.07.3 собран на ядре 4.14.180.

Продолжая поиски, натыкаюсь на актуальную разработку виндового клиента на github. Ок, заявлена поддержка Windows 10 x64, но клиент исключительно тестовый, поэтому присутствует ряд ограничений.

Итак, сначала просят установить сертификат, притом дважды. Ок, помещаем его в Trusted Root Certification Authority и Trusted Publishers.

Далее необходимо перевести операционную систему в тестовый режим. Делается это командой

bcdedit.exe /set TESTSIGNING ON

С первого раза у меня не получилось, помешал secure boot. Для его отключения необходимо перезагрузиться в UEFI, и выставить secure boot — disable. На некоторых моделях ноутбуков может потребоваться установка supervisor password.

После этого загружаемся в Windows и делаем bcdedit.exe /set TESTSIGNING ON
Винда говорит, что всё ок. Снова перезагружаемся, и видим в правом нижнем углу надпись Test Mode, версию и номер билда ОС.

Для чего же все эти манипуляции? Для установки неподписанного драйвера USB/IP VHCI. Сделать это предлагается, скачав файлы usbip.exe, usbip_vhci.sys, usbip_vhci.inf, usbip_vhci.cer, usbip_vhci.cat, и выполнив с правами администратора

usbip.exe install

либо второй способ, установка Legacy Hardware в ручном режиме. Я выбрал второй вариант, получил предупреждение об установке неподписанного драйвера и согласился с ним.

Далее проверяем, что у нас есть возможность подключиться к удаленному USB-устройству, выполняя команду:

usbip.exe list -r <ip вашего роутера>

получаем список устройств:

c:\Utils\usbip>usbip.exe list -r 192.168.31.203
usbip: error: failed to open usb id database
Exportable USB devices
======================
 - 192.168.31.203
      1-1.4: unknown vendor : unknown product (1a86:7523)
           : /sys/devices/ssb0:1/ehci-platform.0/usb1/1-1/1-1.4
           : unknown class / unknown subclass / unknown protocol (ff/00/00)

на ошибку usbip: error: failed to open usb id database не обращаем внимания, на работу не влияет.

Теперь биндим устройство:

c:\Utils\usbip>usbip.exe attach -r 192.168.31.203 -b 1-1.4

Всё, винда обнаружила новое устройство, теперь с ним можно работать так, как будто оно физически подключено к ноутбуку.

С китайским гравёром пришлось немного помучаться, так как при попытке установить его драйвер CH341SER через прилагавшийся к гравёру инсталлятор (да, гравёр на Ардуино), USB/IP VHCI ронял винду в BSOD. Однако установка драйвера CH341SER до подключения устройства через usbip.exe решала проблему.

Итог: гравёр шумит и дымит на кухне при открытом окне и закрытой двери, я наблюдаю за процессом выжигания из другой комнаты через родную софтину, которая не чувствует подвоха.

Использованные источники:

https://openwrt.org/docs/guide-user/services/usb.iptunnel
https://github.com/cezanne/usbip-win