Line 1:
Line 1:
−
This service was added with [[2.0.0-2]]. It employs a custom packet format with obfuscation and error detection.
+
#REDIRECT [[IR Services#IR Service "ir:USER"]]
−
−
= Command set =
−
When sending data, SendIrnop is used when the size is <=0xFC, otherwise SendIrnopLarge is used.
−
−
{| class="wikitable" border="1"
−
|-
−
! Command Header
−
! Available since system version
−
! Description
−
|-
−
| 0x00010182
−
| [[2.0.0-2]]
−
| InitializeIrnop
−
|-
−
| 0x00020000
−
| [[2.0.0-2]]
−
| FinalizeIrnop
−
|-
−
| 0x00030000
−
| [[2.0.0-2]]
−
| ClearReceiveBuffer
−
|-
−
| 0x00040000
−
| [[2.0.0-2]]
−
| ClearSendBuffer
−
|-
−
| 0x0005....
−
| [[2.0.0-2]]
−
| WaitConnection
−
|-
−
| 0x00060040
−
| [[2.0.0-2]]
−
| RequireConnection (u8 input)
−
|-
−
| 0x0007....
−
| [[2.0.0-2]]
−
| AutoConnection
−
|-
−
| 0x0008....
−
| [[2.0.0-2]]
−
| AnyConnection
−
|-
−
| 0x00090000
−
| [[2.0.0-2]]
−
| Disconnect
−
|-
−
| 0x000A0000
−
| [[2.0.0-2]]
−
| GetReceiveEvent (writes event handle to cmdreply[3])
−
|-
−
| 0x000B0000
−
| [[2.0.0-2]]
−
| GetSendEvent (writes event handle to cmdreply[3])
−
|-
−
| 0x000C0000
−
| [[2.0.0-2]]
−
| GetConnectionStatusEvent (writes event handle to cmdreply[3])
−
|-
−
| 0x000D0042
−
| [[2.0.0-2]]
−
| SendIrnop (u32 size, ((Size<<14) <nowiki>|</nowiki> 2), inbufptr)
−
|-
−
| 0x000E0042
−
| [[2.0.0-2]]
−
| SendIrnopLarge (u32 size, ((Size<<8) <nowiki>|</nowiki> 10), inbufptr)
−
|-
−
| 0x000F....
−
| [[2.0.0-2]]
−
| ReceiveIrnop
−
|-
−
| 0x0010....
−
| [[2.0.0-2]]
−
| ReceiveIrnopLarge
−
|-
−
| 0x0011....
−
| [[2.0.0-2]]
−
| GetLatestReceiveErrorResult
−
|-
−
| 0x0012....
−
| [[2.0.0-2]]
−
| GetLatestSendErrorResult
−
|-
−
| 0x0013....
−
| [[2.0.0-2]]
−
| GetConnectionStatus
−
|-
−
| 0x0014....
−
| [[2.0.0-2]]
−
| GetTryingToConnectStatus
−
|-
−
| 0x0015....
−
| [[2.0.0-2]]
−
| GetReceiveSizeFreeAndUsed
−
|-
−
| 0x0016....
−
| [[2.0.0-2]]
−
| GetSendSizeFreeAndUsed
−
|-
−
| 0x0017....
−
| [[2.2.0-X]]
−
| GetConnectionRole
−
|-
−
| 0x00180182
−
| [[2.2.0-X]]
−
| InitializeIrnopShared (u32, u32, u32, u32, u32, u8, 0, handle)
−
|-
−
| 0x00190040
−
| [[2.2.0-X]]
−
| ReleaseReceivedData (32bit_value input)
−
|-
−
| 0x001A0040
−
| [[2.2.0-X]]
−
| SetOwnMachineId (u8 input)
−
|}
−
−
= Protocol description =
−
Packets are sent using IrDA-SIR, with a 8N1 encoding (eight data bits, one stop bit, without parity). Each one is formed by a 2-byte header, a varint with the payload size, an obfuscated payload, and trailing error detection byte.
−
−
== Packet header ==
−
The packet header is fixed and consists in a synchronization byte (0xA5), followed by a unused (possibly RFU) zero byte. After these two hardcoded bytes, there's a varint representing the payload size, which may use one byte or two, depending on the how big the payload is.
−
−
* For payloads with less than 64 bytes, the third byte represents the payload size.
−
* For packets with up to 16383 bytes, the size is split in two bytes, with the third byte being the upper 6 bits of the payload size, OR'd with 0x40, and the fourth being the lower eight bits of the payload size
−
−
For packets with less than 64 bytes:
−
{| class="wikitable" border="1"
−
! Sync
−
! RFU
−
! Size
−
|-
−
| 0xA5
−
| 0x00
−
| size
−
|}
−
−
For packets with up to 16383 bytes:
−
{| class="wikitable" border="1"
−
! Sync
−
! RFU
−
! Size (1)
−
! Size (2)
−
|-
−
| 0xA5
−
| 0x00
−
| (size >> 8) <nowiki>|</nowiki> 0x40
−
| size & 0xFF
−
|}
−
−
In C:
−
<nowiki>uint8_t * setPacketHeader(uint8_t * buffer, size_t payloadSize) {
−
assert(payloadSize < 16384);
−
−
buffer[0] = 0xA5;
−
buffer[1] = 0x00;
−
−
if (payloadSize < 64) {
−
buffer[2] = payloadSize;
−
buffer += 3;
−
} else {
−
buffer[2] = 0x40 | (payloadSize >> 8);
−
buffer[3] = payloadSize;
−
buffer += 4;
−
}
−
−
return buffer;
−
}</nowiki>
−
−
== Payload ==
−
The payload is obfuscated using a XOR-based encryption. In C:
−
<nowiki>void payloadObfuscate(const void * voidplain, void * voidcipher, size_t size) {
−
uint16_t * plain = (uint16_t *) voidplain;
−
uint16_t * cipher = (uint16_t *) voidcipher;
−
size_t halfCount = size / sizeof(uint16_t);
−
−
uint16_t xorval = htobe16(0xE963);
−
size_t i;
−
−
for (i = 0; i < halfCount; i++) {
−
xorval ^= plain[i];
−
cipher[i] = xorval;
−
}
−
}
−
−
void payloadDeobfuscate(const void * voidcipher, void * voidplain, size_t size) {
−
uint16_t * cipher = (uint16_t *) voidcipher;
−
uint16_t * plain = (uint16_t *) voidplain;
−
size_t halfCount = size / sizeof(uint16_t);
−
−
if (halfCount) {
−
size_t i;
−
for (i = halfCount - 1; i > 0; i--) {
−
plain[i] = cipher[i] ^ cipher[i - 1];
−
}
−
−
plain[0] = cipher[0] ^ htobe16(0xE963);
−
}
−
}</nowiki>
−
−
== Error detection ==
−
The trailing error detection byte is calculated using [[CRC-8-CCITT]] <b>over the whole packet</b> (both the header and the payload)