Difference between revisions of "Ir:USER"
Socram8888 (talk | contribs) (Redirected page to IR Services#IR Service "ir:USER") |
Socram8888 (talk | contribs) |
||
Line 1: | Line 1: | ||
− | + | This service was added with [[2.0.0-2]]. It employs a custom packet format with obfuscation and error detection. | |
+ | |||
+ | = 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) |
Revision as of 10:48, 16 April 2015
This service was added with 2.0.0-2. It employs a custom packet format with obfuscation and error detection.
Command set
When sending data, SendIrnop is used when the size is <=0xFC, otherwise SendIrnopLarge is used.
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) | 2), inbufptr) |
0x000E0042 | 2.0.0-2 | SendIrnopLarge (u32 size, ((Size<<8) | 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:
Sync | RFU | Size |
---|---|---|
0xA5 | 0x00 | size |
For packets with up to 16383 bytes:
Sync | RFU | Size (1) | Size (2) |
---|---|---|---|
0xA5 | 0x00 | (size >> 8) | 0x40 | size & 0xFF |
In C:
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; }
Payload
The payload is obfuscated using a XOR-based encryption. In C:
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); } }
Error detection
The trailing error detection byte is calculated using CRC-8-CCITT over the whole packet (both the header and the payload)