Hatred's Log Place

DON'T PANIC!

Dec 5, 2023 - 5 minute read - Programming

Проброс последовательного порта по сети

Сетап:

  • Удалённое устройство, подключенное к серверу на Linux
  • Управление через COM порт
  • Управление тулом под Windows
  • Есть SSH доступ
  • Само устройство успешно удалённо программируется и отлаживается по JTAG

Нужно:

  • Запустить тул локально под Virtual Box (локальная машина тоже Linux)
  • Пробросить удалённый последовательный порт локально
  • Пробросить его в Virtual Box

Поиск в интернете даёт сходу два результата:

Оба пакета имеются в наличии в Manjaro/ArchLinux и поставить просто:

pacman -S socat ser2net

socat, к слову, уже был поставлен как зависимость kwallet-pam.

ser2net реализует RFC2217.

Предподготовка

Будем пытаться максимально делать всё от обычного пользователя (кроме, пожалуй, установки пакетов).

Создадим каталог $HOME/dev для наших устройств:

mkdir -p $HOME/dev

Попытка номер раз: только socat

В его man’е есть заманчивая строчка:

       socat PTY,link=$HOME/dev/vmodem0,rawer,wait-slave \
       EXEC:"ssh modemserver.us.org socat - /dev/ttyS0,nonblock,rawer"

Пробуем (эксперимент показываю на localhost, сейчас удалёнка вне доступа, но смысл тот же, просто где-то придётся пробросить порты через тот же SSH):

socat PTY,link=$HOME/dev/serial-local,rawer,wait-slave EXEC:"ssh localhost socat - /dev/ttyUSB0,nonblock,rawer"

А далее picocom:

$ picocom -b 115200  ~/dev/serial-local  
picocom v3.1  
  
port is        : /home/hatred/dev/serial-local  
flowcontrol    : none  
baudrate is    : 115200  
parity is      : none  
databits are   : 8  
stopbits are   : 1  
escape is      : C-a  
local echo is  : no  
noinit is      : no  
noreset is     : no  
hangup is      : no  
nolock is      : no  
send_cmd is    : sz -vv  
receive_cmd is : rz -vv -E  
imap is        :    
omap is        :    
emap is        : crcrlf,delbs,  
logfile is     : none  
initstring     : none  
exit_after is  : not set  
exit is        : no  
  
Type [C-a] [C-h] to see available commands  
Terminal ready  
  
FATAL: read zero bytes from port  
term_exitfunc: reset failed for dev UNKNOWN: Input/output error

При этом со стороны socat:

2023/12/05 11:00:37 socat[1555557] E tcgetattr(7, 0x56489e9255a0): Inappropriate ioctl for device

Это фиаско. Но двигаемся дальше.

Попытка номер два: ser2net и socat

Со стороны “сервера” пробуем запустить ser2net, а уже локально создать “файл устройства” через socat.

Сервер:

ser2net -C "7000:telnet:0:/dev/ttyUSB1:remctl" -d -u

Локально (если нужно, пробрасываем порт через ssh):

socat PTY,link=$HOME/dev/serial-local,rawer TCP:localhost:7000

Локально, picocom:

$ picocom -b 115200  ~/dev/serial-local  
picocom v3.1  
  
port is        : /home/hatred/dev/serial-local  
flowcontrol    : none  
baudrate is    : 115200  
parity is      : none  
databits are   : 8  
stopbits are   : 1  
escape is      : C-a  
local echo is  : no  
noinit is      : no  
noreset is     : no  
hangup is      : no  
nolock is      : no  
send_cmd is    : sz -vv  
receive_cmd is : rz -vv -E  
imap is        :    
omap is        :    
emap is        : crcrlf,delbs,  
logfile is     : none  
initstring     : none  
exit_after is  : not set  
exit is        : no  
  
Type [C-a] [C-h] to see available commands  
Terminal ready  
weeeerrrrrttttyyyyqqqqaaassszzxxcvfdsfdsfdsrwrew

со стороны UART Rx и Tx соединены, поэтому наблюдаем Echo.

Это успех!

UPD: успех, но не полный. Петля на Rx-Tx скрыла тот факт, что не было настройки Boudrate. Если бодрейт сильно отличается, то может посыпать мусор и параметр remctl тут не сильно помогает. Если по простому: то в самом конце цепочки, на уровне picocom может уже не сработать установка baudrate. Нужно править или на уровне socat или команды ser2net. Самое простое, изменить команду ser2net так:

ser2net -C "7000:telnet:0:/dev/ttyUSB1:921600 remctl" -d -u

И однострочник, который пробросит с хоста и порты сразу и запустит команду:

ssh -L '*:7000:localhost:7000' zcu208 'ser2net -C "7000:telnet:0:/dev/ttyUSB1:921600 remctl" -d -u'

А теперь горбатый VirtualBox

Идём в настройки виртуальной машины на вкладку “Serial Ports” и включаем, для примера, COM1.

И, внезапно, обнаруживаем в параметре “Port Mode:” режим “TCP”… А ну ка, указываем там “localhost:7000” (именно на этом порту у нас уже висит ser2net из предыдущего пункта) и загружаемся.

В Windows в диспетчере видим единственный COM1 и подключаемся к нему через Putty и наблюдаем echo.

Снова успех! Даже запуска socat не нужно. Но успех частичный, читаем дальше.

Есть, правда, нюанс: до запуска виртуалки к ser2net не должно быть никакого подключения. Иначе порт появится, а работать не будет.

Второй нюанс: не работают “нестандартные” Baud Rate. К примеру, я не смог поставить 921600. Но они же работают в связке socat+picocom.

Если настраивать через PIPE, то результат ровно такой же. Настройка через PIPE

  • Сначала запускаем socat: socat UNIX-LISTEN:$HOME/dev/serial-pipe TCP:localhost:7000
  • В настройках порта указываем:
    • “Port Mode:” → “Host Pipe”
    • “Path/Address:” → “~/dev/serial-pipe”
      • лучше указать полный путь, который обслуживает socat.

Сдаётся мне, что это особенности стандартного драйвера для стандартных последовательных портов (COM1-4). Поэтому, идём дальше.

Убираем промежуточное звено

На Windows вполне можно себе использовать RFC2217. Поэтому попытаемся создать подключение к ser2net непосредственно, миную функционал Virtual Box.

Для начала запускаем Telnet или Putty, выбираем протокол telnet, устанавливаем хост в адрес на котором крутится ser2net и соответствующий порт. Смотрим, что работает. Если не работает - разбираемся с сетью.

Дальше скачиваем необходимые пакеты проекта Null-modem emulator:

  • com2com
    • лучше версию 2.2.2.0 дабы не иметь проблем с подписью на новых Windows
    • или отключаем проверку подписи, либо курим DSEO
    • я скачивал и пробовал (Windows 10 64bit) com0com-2.2.2.0-x64-fre-signed.zip
  • hub2com

Первый распаковываем и устанавливаем. После чего запускаем от имени Администратора конфигуратор setupc.exe и вводим туда:

install PortName=COM19 PortName=COM20

что создаст нам пару виртуальных портов и роутинг между ними. В приложении нужно будет использовать порт COM20, а для сети - COM19. Можно добавить параметр EmuBR=yes к COM19 для эмуляции скорости, но у меня всё заработало без него.

Далее распаковываем hub4com, там никаких установщиков нет. И запускаем:

.\com2tcp-rfc2217 \\.\COM19 192.168.0.104 7000

здесь:

  • COM19 - первый из пары виртуальных адресов
  • 192.168.0.104 - адрес, где крутится ser2net на Linux
  • 7000 - соответственно порт, который слушает ser2net

В Putty пробуем открыть COM20 с нестандартным рейтом, например - 921600. И вот тут оно начинает работать.

Терминал с запущенным com2tcp-rfc2217.bat закрывать не нужно, иначе связь разорвётся.

Теперь точно успех!

Дополнительная информация