Protocol Deep Dive¶
The Icom LAN protocol is a proprietary UDP-based protocol used by Icom transceivers for remote control over Ethernet/WiFi. It was reverse-engineered by the wfview project.
Packet Structure¶
Every UDP packet starts with a fixed 16-byte header:
Offset Size Endian Field
0x00 4 LE Packet length (total, including header)
0x04 2 LE Packet type
0x06 2 LE Sequence number
0x08 4 LE Sender ID
0x0C 4 LE Receiver ID
Packet Types¶
| Type | Name | Size | Description |
|---|---|---|---|
0x00 |
DATA | Variable | Carries CI-V commands, audio, etc. |
0x01 |
CONTROL | 0x10+ | Retransmit requests |
0x03 |
ARE_YOU_THERE | 0x10 | Discovery request (broadcast) |
0x04 |
I_AM_HERE | 0x10 | Discovery response |
0x05 |
DISCONNECT | 0x10 | Disconnect notification |
0x06 |
ARE_YOU_READY | 0x10 | Ready handshake |
0x07 |
PING | 0x15 | Keep-alive ping/pong |
Port Architecture¶
| Port | Name | Purpose |
|---|---|---|
| 50001 | Control | Authentication, session management, keep-alive |
| 50002 | CI-V | CI-V serial command exchange |
| 50003 | Audio | Opus audio streaming |
The CI-V and audio port numbers are negotiated — they're reported in the status packet (0x50 bytes) after the conninfo exchange. However, in practice they are almost always control_port+1 and control_port+2.
Discovery¶
Client → Radio: ARE_YOU_THERE (0x03), 16 bytes
Radio → Client: I_AM_HERE (0x04), 16 bytes, includes radio's sender_id
Client → Radio: ARE_YOU_READY (0x06), 16 bytes
Radio → Client: ARE_YOU_READY (0x06), 16 bytes (echo/ack)
This can also be broadcast (UDP broadcast to port 50001) for autodiscovery.
Authentication¶
Login Packet (0x80 bytes)¶
Offset Size Field
0x00 4 Packet length (0x80)
0x04 2 Type (0x00 = DATA)
0x06 2 Sequence
0x08 4 Sender ID
0x0C 4 Receiver ID
0x10 4 Payload size (0x70, big-endian)
0x14 1 Request/reply (0x01)
0x15 1 Request type (0x00 = login)
0x16 2 Inner sequence (big-endian)
0x1A 2 Token request ID
0x40 16 Encoded username
0x50 16 Encoded password
0x60 16 Computer name (ASCII)
Credential Encoding¶
Icom uses a position-dependent substitution cipher:
- For each character at position
i: compute index =ord(char) + i - If index > 126: index =
32 + (index % 127) - Look up in the substitution table (128-byte constant)
This is obfuscation, not encryption. The substitution table is publicly known.
Auth Response (0x60 bytes)¶
Offset Size Field
0x1A 2 Token request ID (echoed)
0x1C 4 Session token
0x30 4 Error code (0 = success, 0xFEFFFFFF/0xFFFFFFFF = failure)
0x40 16 Connection type string
Token Ack (0x40 bytes)¶
Offset Size Endian Field
0x10 4 BE Payload size
0x14 1 Request/reply (0x01)
0x15 1 Request type (0x02 = token ack)
0x16 2 BE Inner sequence
0x1A 2 LE Token request ID
0x1C 4 LE Token
0x24 2 BE Reset capability (0x0798)
Conninfo Exchange¶
Conninfo Packet (0x90 bytes)¶
Sent by both radio and client. Contains:
Offset Size Field
0x15 1 Request type (0x03 = conninfo)
0x1C 4 Token
0x20 16 GUID / MAC area
0x40 32 Device name
0x60 16 Encoded username
0x70 1 RX enable
0x71 1 TX enable
0x72 1 RX codec
0x73 1 TX codec
0x74 4 RX sample rate (BE)
0x78 4 TX sample rate (BE)
0x7C 4 CI-V local port (BE)
0x80 4 Audio local port (BE)
0x84 4 TX buffer latency ms (BE)
Critical: The client must echo the radio's GUID (0x20–0x2F from the radio's conninfo) in its own conninfo. Otherwise, the status packet will report CI-V port = 0.
Status Packet (0x50 bytes)¶
Sent by the radio after receiving the client's conninfo:
Offset Size Endian Field
0x30 4 LE Error code
0x40 1 Disconnect flag
0x42 2 BE CI-V port
0x46 2 BE Audio port
CI-V Over UDP¶
CI-V Data Packet¶
CI-V frames are wrapped in UDP data packets on port 50002:
Offset Size Field
0x00 4 Total packet length
0x04 2 Type (0x00 = DATA)
0x06 2 Sequence
0x08 4 Sender ID
0x0C 4 Receiver ID
0x10 1 Reply marker (0xC1 for CI-V data)
0x11 2 CI-V frame length (LE)
0x13 2 Send sequence (BE)
0x15 ... CI-V frame data
The CI-V header is 0x15 bytes (not 0x10 — there's a 5-byte sub-header after the standard packet header).
OpenClose Packet (0x16 bytes)¶
Sent to start/stop the CI-V data stream:
Offset Size Field
0x10 2 Data (0x01C0)
0x13 2 Send sequence (BE)
0x15 1 Magic (0x04 = open, 0x00 = close)
Keep-Alive¶
Ping Packet (0x15 bytes)¶
Offset Size Field
0x00 4 Length (0x15)
0x04 2 Type (0x07 = PING)
0x06 2 Ping sequence
0x08 4 Sender ID
0x0C 4 Receiver ID
0x10 1 Flag (0x00 = request, 0x01 = reply)
0x11 4 Timestamp (LE, milliseconds)
Pings are sent every 500ms. The radio drops connections that stop pinging.
Retransmit¶
If a sequence gap is detected, the receiver sends a retransmit request:
- Single missing: 0x10-byte control packet with type=0x01 and the missing seq in the seq field
- Multiple missing: 0x10+ byte packet with type=0x01, followed by pairs of (seq, seq) for each missing packet
CI-V Frame Format¶
Standard Icom CI-V serial protocol, encapsulated in UDP:
FE FE— preamble<to>— destination address (radio = 0x98 for IC-7610)<from>— source address (controller = 0xE0)<cmd>— command byte<sub>— sub-command (optional, depends on command)<data>— payload (variable length)FD— terminator
BCD Frequency Encoding¶
Frequencies are encoded as 5-byte little-endian BCD:
14,074,000 Hz → 00 40 07 14 00
Byte 0: 00 → digits 0,0 (1 Hz, 10 Hz)
Byte 1: 40 → digits 4,0 (100 Hz, 1 kHz)
Byte 2: 07 → digits 0,7 (10 kHz, 100 kHz)
Byte 3: 14 → digits 1,4 (1 MHz, 10 MHz)
Byte 4: 00 → digits 0,0 (100 MHz, 1 GHz)
References¶
- wfview — open-source Icom remote control software (GPLv3)
packettypes.h— packet structure definitionsicomudpbase.cpp— base UDP handlingicomudphandler.cpp— authentication and handshakeicomudpcivdata.cpp— CI-V data flowicomcommander.cpp— CI-V command encoding
Legal Note¶
Protocol reverse engineering for interoperability is protected by:
- EU Directive 2009/24/EC (Software Directive, Article 6)
- US DMCA interoperability exception (17 U.S.C. § 1201(f))
This library is a clean-room implementation based on protocol understanding, not a derivative of wfview's GPLv3 code.