Line 38: |
Line 38: |
| Packets are sent using IrDA-SIR (using [[ir:USER]]), 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. | | Packets are sent using IrDA-SIR (using [[ir:USER]]), 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 == | + | == Layer 1 - framing format == |
− | 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.
| + | Frames are encoded using two different yet very simmilar formats, depending on how large the payload to be transmitted is: |
− | | |
| * For payloads with less than 64 bytes, the third byte represents the payload size. | | * 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 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" style="margin: 0 auto; text-align: center;" |
− | {| class="wikitable" border="1" | + | |+IR framing format - short frame |
− | ! Sync | + | |- |
− | ! RFU | + | ! style="border-top: none" | Byte |
− | ! Size
| + | ! style="width:10%;"| 7 |
| + | ! style="width:10%;"| 6 |
| + | ! style="width:10%;"| 5 |
| + | ! style="width:10%;"| 4 |
| + | ! style="width:10%;"| 3 |
| + | ! style="width:10%;"| 2 |
| + | ! style="width:10%;"| 1 |
| + | ! style="width:10%;"| 0 |
| + | |- |
| + | ! 0x00 |
| + | | colspan="8"|Synchronization byte (<code>0xA5</code>) |
| + | |- |
| + | ! 0x01 |
| + | | colspan="8"|Reserved for future use (<code>0x00</code>) |
| + | |- |
| + | ! 0x02 |
| + | | RFU (<code>0</code>) |
| + | | Short frame (<code>0</code>) |
| + | | colspan="6"|Payload size |
| |- | | |- |
− | | 0xA5 | + | ! 0x03 |
− | | 0x00 | + | | colspan="8"|Payload byte 0 |
− | | size | + | |- |
| + | | colspan="9"|... |
| + | |- |
| + | ! 0x03+n-1 |
| + | | colspan="8"|Payload byte n-1 |
| + | |- |
| + | ! 0x03+n |
| + | | colspan="8"|[[CRC-8-CCITT]] computer over whole packet |
| |} | | |} |
| | | |
− | For packets with up to 16383 bytes:
| + | |
− | {| class="wikitable" border="1" | + | {| class="wikitable" style="margin: 0 auto; text-align: center;" |
− | ! Sync | + | |+IR framing format - long frame |
− | ! RFU | + | |- |
− | ! Size (1)
| + | ! style="border-top: none" | Byte |
− | ! Size (2) | + | ! style="width:10%;"| 7 |
| + | ! style="width:10%;"| 6 |
| + | ! style="width:10%;"| 5 |
| + | ! style="width:10%;"| 4 |
| + | ! style="width:10%;"| 3 |
| + | ! style="width:10%;"| 2 |
| + | ! style="width:10%;"| 1 |
| + | ! style="width:10%;"| 0 |
| + | |- |
| + | ! 0x00 |
| + | | colspan="8"|Synchronization byte (<code>0xA5</code>) |
| + | |- |
| + | ! 0x01 |
| + | | colspan="8"|Reserved for future use (<code>0x00</code>) |
| + | |- |
| + | ! 0x02 |
| + | | RFU (<code>0</code>) |
| + | | Long frame (<code>1</code>) |
| + | | colspan="6"|Payload size (upper 6 bits) |
| + | |- |
| + | ! 0x03 |
| + | | colspan="8"|Payload size (lower 8 bits) |
| + | |- |
| + | ! 0x04 |
| + | | colspan="8"|Payload byte 0 |
| |- | | |- |
− | | 0xA5 | + | | colspan="9"|... |
− | | 0x00 | + | |- |
− | | (size >> 8) <nowiki>|</nowiki> 0x40 | + | ! 0x04+n-1 |
− | | size & 0xFF | + | | colspan="8"|Payload byte n-1 |
| + | |- |
| + | ! 0x04+n |
| + | | colspan="8"|[[CRC-8-CCITT]] computer over whole 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. |
| | | |
| In C: | | In C: |
Line 87: |
Line 141: |
| }</nowiki> | | }</nowiki> |
| | | |
− | == Payload == | + | === Payload === |
| The payload is obfuscated using a XOR-based encryption. In C: | | The payload is obfuscated using a XOR-based encryption. In C: |
| <nowiki>void payloadObfuscate(const void * voidplain, void * voidcipher, size_t size) { | | <nowiki>void payloadObfuscate(const void * voidplain, void * voidcipher, size_t size) { |
Line 118: |
Line 172: |
| }</nowiki> | | }</nowiki> |
| | | |
− | == Error detection == | + | === 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) | | The trailing error detection byte is calculated using [[CRC-8-CCITT]] <b>over the whole packet</b> (both the header and the payload) |
| | | |