Virtual Serial Ports, com0com, RFC2217, and Radio

Tunneling com ports over tcp, and in particular over low bandwidth radio links can be a tricky business. Even more so if you are on windows and want to use free or preferably open source software. Recent work I've been involved in has required that many devices with different and proprietary protocols (all serial in nature) be tunneled over a udp radio connection from a Windows server to the client device.  The image below demonstrates the conecpt.

com0com1

Each radio has two IP addresses: one for the RF side, and one for the Ethernet side. The serial ports listen on ports 8881 and 8882 respectively on the Ethernet interface.  The serial ports can be configured to send received serial data to a udp/ip:port combination (our Windows server 172.10.10.10), and similarly transmit received udp packets out the serial port.  We will omit details such as IP routing for simplicity.

com0com was the only virtual serial port driver that I could find that would do *mostly* everything that I wanted:

  • RFC2217
  • Raw Serial to Ethernet
  • Create arbitrary numbers of com ports
  • Easy to interface with

Because Windows x64 requires signed drivers and com0com only supplies unsigned drivers, I used the drivers from here to save me the hassle of either disabling driver signing in windows (never a good option for a production environment) or purchasing my own code signing certificate and compiling my own.  However once installed I realised that the com2tcp program (which does the COM<>TCP translation) doesn't support bidirectional udp connections.  Luckily for me, someone wrote a patch for the software back in 2010 to provide exactly this feature.  All I had to do was download the latest source, apply the patch, create new visual studio project files (com0com used to use the old make tools which are no longer supported), and compile!  It took me a few goes to get the correct compile options (why does compiling C on windows have to be so complicated?) but I got there in the end.

I created a new serial port pair COM5<>CNCB0, then ran the command com2tcp.exe --udp \\.\CNCB0 172.20.10.10 8882 8882.  This connects serial port CNCB0 (which is connected to COM5) to our device with IP address 172.20.10.10 on port 8882.  It also listens for incoming traffic on port 8882 (which we have already configured our radios to send data to).  Then we fire up the devices configuration software, and get it to connect to COM5.  At first everything seemed to work, but I soon started getting the error GetOverlappedResult(EVENT_RECEIVED) ERROR Unknown error (234) show up in com2tcp.  Looking up error 234 on the Microsoft website shows More data is available.  Perhaps the buffers are too small?  I took a look at com2tcp.cpp and noticed that all the buffers were only 64 bytes each.  This seemed quite small to me so I set them all to 4096 and voila!  Everything came together nicely.

Now that's all pretty cool, but on my network I might have hundreds of devices to connect to, and having to constantly faff around with batch files is going to get frustrating, and I certainly don't want to create one virtual serial port per endpoint.  So, I made a GUI that lists all the serial ports, and provides with a few clicks a way to start and stop com2tcp/hub4com.  It currently has preset options for TCPClient, UDP and RFC2217 but it would be straightforward to add other options as well.  Preset destinations are read from a portsdb.txt file located in the same directory as the executable allowing for easy configuration.com0comredirector

Currently this program is pretty rough, and doesn't persist settings between sessions (kind of by design as I don't normally connect to the same devices all the time) but it has worked well so far.  All the source for com0com including the parts I have modified and the Redirector program can be found at https://github.com/Raggles/com0com.

| April 17th, 2015 | Posted in Networking, SCADA, Software |

Leave a Reply