Serial port redirection from Windows to Linux with socat

My work computer is a Windows machine running several virtual machines with Linux and FreeBSD via VirtualBox. A part of my work requires developing software that interacts with hardware. Most of the time I have successfully used VirtualBox USB filtering to redirect USB devices to the virtual machines, but recently I got a USB device (CDC-ACM class) that refused to be forwarded to the VM.

Windows was always hijacking the device, no matter how I set up VirtualBox filters, and made a new COM serial port. I did not have enough time to setup a bare-metal Linux computer, so I had to figure a way to test my application running in a Linux VM with the hardware attached to Windows.

I found out a very elegant solution – socat. Something netcat-like, but with different features (TONS of features!!). Socat allows to redirect serial ports to TCP sockets (and many other “pipes” back and forth).

Windows side

I installed Cygwin64. It has socat in its package repository. Starting the serial port server is as easy as a single command in Cygwin terminal:
socat -d -d -d TCP4-LISTEN:23000,reuseaddr,fork /dev/ttyS5

Windows COM ports appear in Cygwin as /dev/ttySxxx devices, COM1 is /dev/ttyS0 etc. 23000 is the listen port number.

Linux side

socat PTY,link=/tmp/vmodem0,rawer,wail-slave TCP:

/tmp/vmodem0 is the virtual serial port (it is in /tmp rather than in /dev, so that it does not requires root privileges). It is a “real” tty device that can be opened with minicom or picocom. IP belongs to the Windows PC.

In the end the serial device reliably communicated with my Linux pyserial application. It was using only the RX/TX lines (though I am almost sure that any other device would fail, if it had to rely on RTS/CTS/DCD or their specific timings like old chip programmers).