Linux Serial Server Now Working with HRD and FT-857

After some additional efforts, I managed to get my Linux remote serial server to work with HRD; now HRD running on Windows can control my FT-857 when it is connected to a Linux box.

Getting there required resolving three issues. One was getting the code that configures the serial port to work correctly. It had some bugs in this code initially, which prevented the code from actually talking to the radio. The second was a new protocol command that I did not see before. HRD uses this command to set the frequency of the radio. I initially treated it like the normal command that sends data to the radio. This did not work. Snooping on the protocol with Wireshark showed that the server should not respond to this message at all; I removed the response, and it started working. The final issue involved the command that writes configuration parameters to the radio’s EEPROM, command BC in the CAT protocol. This is an undocumented CAT command (and a very useful one). For some reason, HRD expects a 5-byte reply from the radio to the command. The radio apparently does not reply, so the serial read attempt times out. I did not initially implement timeouts in my code, so it just got stuck. When I added timeouts (which are also useful in other cases), the code was finally able to fully control the radio.

Here is the code; it’s very preliminary and only tested with the FT-857.

19 Responses to Linux Serial Server Now Working with HRD and FT-857

  1. Steve AD7WY says:

    This looks great. I am using a Mac instead of Linux, but I’d like to play around with this and see whether I can make it work. One question: I see that hrd_serial_server.c #includes endian.c, but that is not supplied in your zip file. Google does not seem to lead me to it either. Where can I find this file?
    Thanks!
    Steve AD7WY

    • Sivan Toledo says:

      Hi Steve.

      Sorry about this. I added the missing file to the zip file that the link points to. I’ll be happy to hear how your efforts are going.

      Regards, Sivan

  2. Steve AD7WY says:

    Thanks! I look forward to giving it a try.

  3. Steve AD7WY says:

    Hi Sivan –

    The code compiles as is on the Mac. But, I wonder if the code you posted is the final version that you got working? For example, in connection_read(), on line 694 of hrd_serial_server.c, persistent_read() is called, and the result is stored in n, which is checked with an assert to ensure it is 12. However, although is declared to return as ssize_t, it doesn’t actually return anything, so the assert always fails.

    Steve AD7WY

  4. Steve AD7WY says:

    Hi Sivan –

    Same problem, but I think see what you have done. You are probably compiling with NDEBUG to turn off the asserts. When I do that, it runs fine (and I can even connect to it from HRD!)
    Thanks!

    Steve AD7WY

  5. Corby K0SKW says:

    Terribly stupid question, but anything special I need to do to compile this?

    $ gcc hrd_serial_server.c
    /tmp/ccIPEYnw.o: In function `connection_create’:
    hrd_serial_server.c:(.text+0x6a7): undefined reference to `pthread_create’
    /tmp/ccIPEYnw.o: In function `main’:
    hrd_serial_server.c:(.text+0x1e51): undefined reference to `configInit’
    hrd_serial_server.c:(.text+0x1e7b): undefined reference to `configGetInt’
    collect2: ld returned 1 exit status

    It’s been a long time since I’ve compiled C code, so I’m probably just doing it wrong haha

    • Sivan Toledo says:

      Corby,

      Try “gcc hrd_serial_server.c config.c -lpthread”

      The zip file should contain a file config.c that should also be compiled with the main program, and pthread_create, which the linker did not find, is from the Linux threading library that -lpthread will include.

      Sivan

  6. Dirk ON4CRM says:

    Sivan,

    I gave your code a try on Linux Mint using the command

    gcc hrd_serial_server.c config.c -lpthread -DNDEBUG

    I get the following warning and no executable :
    config.c: In function ‘read_config_file’:
    config.c:371:3: warning: format ‘%u’ expects type ‘unsigned int’, but argument 3 has type ‘__off_t’

    any ideas?
    Many thx

  7. Dirk ON4CRM says:

    Sivan,

    Used the -o arg and it works. I’m trying to connect to an ICOM IC706MkIIg and I van connect but when setting the ports to use I got an error : the output at the serverside
    size of /etc/hrd_serial_server.conf is 1409 bytes
    size of ./hrd_serial_server.conf is 1409 bytes
    port 7805
    Connection request from 192.168.2.122
    reading command…Command 0 length 1680
    Processing command 0
    Authenticate command user=on4crm password=******** release=2494
    reading command…Command 1 length 4112
    Processing command 1
    Enumerate command ports=
    ports=ttyUSB2,ttyUSB1,ttyUSB0,ttyS0,ttyS31,ttyS30,ttyS29,ttyS28,ttyS27,ttyS26,ttyS25,ttyS24,ttyS23,ttyS22,ttyS21,ttyS20,ttyS19,ttyS18,ttyS17,ttyS16,ttyS15,ttyS14,ttyS13,ttyS12,ttyS11,ttyS10,ttyS9,ttyS8,ttyS7,ttyS6,ttyS5,ttyS4,ttyS3,ttyS2,ttyS1
    reading command…Command 2 length 520
    Processing command 2
    Connect command port=\\.\ttyUSB1
    posix port=/dev/ttyUSB1
    reading command…Command 3 length 520
    Processing command 3
    Misc command, handle=6 (our handle is 6)
    reading command…Command 5 length 520
    Processing command 5
    Purge command, handle=6 (our handle is 6)
    bits=0000000f
    reading command…Command 6 length 520
    Processing command 6
    Set Comm Params command, handle=6 (our handle is 6)
    Set parameters command, handle=6 (our handle is 6)
    speed=19200 nbits=8 parity=0 stop=0
    xonch=11 xoffch=13 err=3f eof=00 evt=00
    bitfields=00000000
    bitfields=00000000
    DTR=disabled (off)
    RTS=disabled (off)
    reading command…Command 7 length 520
    Processing command 7
    Set Timeouts command, handle=6 (our handle is 6)
    Timeouts command, handle=6 (our handle is 6)
    500,500,500,500,500
    reading command…Command 3 length 520
    Processing command 3
    Misc command, handle=6 (our handle is 6)
    reading command…Command 3 length 520
    Processing command 3
    Misc command, handle=6 (our handle is 6)
    reading command…Command 4 length 520
    Processing command 4
    Waitmask command, handle=6 (our handle is 6)
    event mask=0000017d
    reading command…Command 5 length 520
    Processing command 5
    Purge command, handle=6 (our handle is 6)
    bits=0000000f
    reading command…Command 2 length 520
    Processing command 2
    Connect command port=\\.\ttyUSB0
    posix port=/dev/ttyUSB0
    reading command…Command 13 length 520
    Processing command 13
    Unknown command code 13
    08 02 00 00 48 52 44 2a 0d 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 06 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 07 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00

    • Sivan Toledo says:

      Hi Dirk,

      This one is more difficult. I guess that there is some serial-port operation that is required on Icom radios but not on Yaesu radios. My guess is that this is related to setting or clearing RTS and DTR, but I am not sure. From the fact that the argument is 520 byte long I gather that it is a port configuration command, like the preceding ones. It follows the open command, which is command 2.

      There are basically several ways to proceed:
      1. You are using both ttyUSB0 and ttyUSB1. I guess that one of them (perhaps USB1) is for PTT. You can try to avoid using it and to hope that HRD will use CAT commands instead to switch from RX to TX (this is what it does on Yaesu radios). Maybe this will eliminate the need for command 13.
      2. If USB1 is the CAT port, not the PTT port, you can try to configure it without hardware flow control. Perhaps an Icom won’t work without this, but it’s worth a try.
      3. The more systematic thing to do is to connect the radio to a Windows computer and to run portmon to trace what HRD is doing to the serial ports. We will see from this trace the sequence of commands that it sends (the open, set timeouts, set line parameters, etc), and after the second open command (of ttyUSB1) we will see what is the Windows system call that corresponds to command 13. Either this will be enough, or maybe we will also need a matching wireshark trace to see how to respond to command 13.

      If it’s too complicated for you, I can try to do #3 while configuring my radio with DTR and RTS, just to see if setting them generates a command 13.

      Regards, Sivan

      • Dirk says:

        Hi Sivan,…. did the test withouth the PPT only using ttyUSB0. I’ve got a little bit further but now we’re hitting a new command 9 as you can see below

        Processing command 1
        Enumerate command ports=
        ports=ttyUSB2,ttyUSB1,ttyUSB0,ttyS0,ttyS31,ttyS30,ttyS29,ttyS28,ttyS27,ttyS26,ttyS25,ttyS24,ttyS23,ttyS22,ttyS21,ttyS20,ttyS19,ttyS18,ttyS17,ttyS16,ttyS15,ttyS14,ttyS13,ttyS12,ttyS11,ttyS10,ttyS9,ttyS8,ttyS7,ttyS6,ttyS5,ttyS4,ttyS3,ttyS2,ttyS1
        reading command…Command 2 length 520
        Processing command 2
        Connect command port=\\.\ttyUSB0
        posix port=/dev/ttyUSB0
        reading command…Command 3 length 520
        Processing command 3
        Misc command, handle=8 (our handle is 8)
        reading command…Command 5 length 520
        Processing command 5
        Purge command, handle=8 (our handle is 8)
        bits=0000000f
        reading command…Command 6 length 520
        Processing command 6
        Set Comm Params command, handle=8 (our handle is 8)
        Set parameters command, handle=8 (our handle is 8)
        speed=19200 nbits=8 parity=0 stop=0
        xonch=11 xoffch=13 err=3f eof=00 evt=00
        bitfields=00000000
        bitfields=00000000
        DTR=disabled (off)
        RTS=disabled (off)
        reading command…Command 7 length 520
        Processing command 7
        Set Timeouts command, handle=8 (our handle is 8)
        Timeouts command, handle=8 (our handle is 8)
        500,500,500,500,500
        reading command…Command 3 length 520
        Processing command 3
        Misc command, handle=8 (our handle is 8)
        reading command…Command 3 length 520
        Processing command 3
        Misc command, handle=8 (our handle is 8)
        reading command…Command 4 length 520
        Processing command 4
        Waitmask command, handle=8 (our handle is 8)
        event mask=0000017d
        reading command…Command 5 length 520
        Processing command 5
        Purge command, handle=8 (our handle is 8)
        bits=0000000f
        reading command…Command 10 length 55
        Processing command 10
        Send command, handle=8 (our handle is 8)
        7 bytes
        data to radio: fe fe 58 e0 19 00 fd
        this means : Read tranceivers ID Code cfr page 49 of manual IC706
        reading command…Command 9 length 21
        Processing command 9
        Unknown command code 9
        15 00 00 00 48 52 44 2a 09 00 00 00 08 00 00
        00 00 01 00 00 fd

        Strange the radio does not answers directly like FE FE E0 58 19 00 <id-code FD
        We'll have to do a complete trace with portmon/wireshark

  8. Dirk says:

    Hoi Sivan,

    Thx for the clear explanation…I had the same sequence in mind :-). Indeed ttyUSB1 is for PTT -I use a ZLP digipro interface – and as the program stops there, my ideas was not to use it as icom radio listens to the HRD for PTT – I’ll test this this evening.
    For option 3 I’ll do this as well so you can make your program better. I’ll help where I can but my knowledge of C/C++ is certainly not at your level.
    I’ll keep you posted.

  9. dirk says:

    Hello Sivan,

    As I already answered, code 13 has a relation with the use of another comport for the PTT. I omitted it and then the program reveives command 9 – which asks for the identification of the tranceiver. I found out that the receiver replies with is default adress 0x58 in my case (IC706MkIIG).
    To understand the whole sequence I did a ‘portmon’ after the identificationrequest the frequencies are asked (0xFF 0xFF 0x58 0xE0 0x00 0x03 0xFD)
    Is there any way to provide you atext file with the output of portmon?

    Thx… I’m trying to understand the code but I have some problems with it…

  10. dirk says:

    BTW I found a lot of info on ICOM CI-V on the site of DF4OR (http://www.plicht.de/ekki/civ/civ-p0a.html)

  11. Sivan Toledo says:

    Hi Dirk,

    Thanks for the portmon trace that you emailed me. The portion that seems relevant to the “9” command seems to send an Icom command which the radio echos and then responds to. HRD sends FE FE 58 E0 19 00 FD, the radio sends back the same thing, and then the radio sends FE FE 58 E0 19 00 58 FD.

    It seems that the Icom protocol uses 0xFD as a termination symbol. So my guess is that the command “9” that you saw basically says “send the following bytes until you see a byte with value 0xFD”. The “9” command you reported was
    15 00 00 00 48 52 44 2a 09 00 00 00 08 00 00 00 00 01 00 00 fd
    I think that the first 4 bytes are the length, 21. The next 4 are the signature, HRD*. The next 4 are the command (9) and then 4 bytes for the handle (8). I am not sure what the rest is, but I think we have 4 bytes with the value 256, which might be the maximum buffer size required for the command to the radio (or the response), and then the termination byte, 0xFD.

    The best way to verify this is to use HRD in a remote configuration with a Windows remote server and to capture the network traffic using wireshark. That way we’ll see what follows the “9” command (my guess is that it is followed by the Icom command, but it’s just a guess), and how the remote server responds. This is a bit tricky to do, since you need two computers, one to run HRD and the other to run the remote server. I think that this won’t work with a single radio through localhost, since wireshark does not capture packets on the localhost interface in Windows. Perhaps you can do it with one computer if you tell HRD to connect to a “remote” server running on the same machine but using the external IP address of the machine (e.g., the wifi IP address) rather than though localhost.

    I might be able to borrow an Icom for a few days to do this, but it won’t happen soon.

    Regards, Sivan

  12. Dirk says:

    Sivan,
    I’ll do the trace with wireshark…have # pc @home.. About The ICOM commands. The structure is:
    Preamble :FE FE
    From adress : E0 for the PC
    To adress : 58 (depends on icon rig)
    Msg : 19 00 means identify yourself
    End: FD
    The answer to this command is the adress of the rig, 58 in my case… thus FE FE 58 E0 19 00 58 FD. See also my comments between brackets in the trace.

  13. Dirk says:

    Hey Sivan,

    It works now with the IC706Mk IIG !! Thx a lot for your big support!

Leave a reply to dirk Cancel reply