12.3. Formát paketu#

Každý bajt, který projde přes vedení mezi kamerou a hostitelem, je součástí paketu. Paket začíná 10bajtovou hlavičkou, pokračuje užitečným obsahem (payload) proměnné délky a končí 4bajtovým koncovým CRC. Na vedení se neobjevují žádné jiné bajty – jakmile hostitel uvidí 2bajtové synchronizační slovo, následující bajty jsou hlavička v přesně tomto pořadí.

A horizontal layout of a protocol packet showing the 10-byte header (sync word, sequence number, channel ID, flags, opcode, payload length, header CRC) followed by the variable-length payload and a 4-byte payload CRC.

12.3.1. Hlavička#

Deset bajtů, sbalených bez vycpávky (padding). Každé pole:

  • sync – 16bitové slovo 0xD5AA v pořadí little-endian. Bajt 0 na vedení je 0xAA, bajt 1 je 0xD5. Příjemce procházející bajty může najít začátek paketu vyhledáním dvojice AA D5; vše před ní je považováno za smetí. Volba hodnoty je záměrná: 0xAA a 0xD5 se v tisknutelném textu vyskytují zřídka a je nepravděpodobné, že by se dvojice náhodně objevila uprostřed užitečného obsahu (payload).

  • seq – jeden bajt. Čítač, který se zvyšuje o jedna pro každý paket odeslaný v daném směru. Příjemce kontroluje, že pořadové číslo dalšího paketu je očekávané; pokud ne, vrstva spolehlivosti požádá o opětovné odeslání.

  • chan – jeden bajt. ID kanálu, kterému tento paket patří. Použitelné jsou kanály 0..31; vestavěné kanály stdin, stdout, stream a (volitelně) profile zabírají pevná ID, která si kamera rezervuje.

  • flags – jeden bajt. Bitové pole, které příjemci říká, jak paket interpretovat:

    • bit 0 ACK – tento paket je potvrzení (acknowledgement) předchozího.

    • bit 1 NAK – tento paket odmítá předchozí.

    • bit 2 RTX – tento paket je opětovné odeslání.

    • bit 3 ACK_REQ – odesílatel chce, aby byl tento paket potvrzen.

    • bit 4 FRAGMENT – po tomto následují další fragmenty větší zprávy.

    • bit 5 EVENT – tento paket nese událost kanálu, nikoli data.

    • bity 6 a 7 jsou rezervované.

  • opcode – jeden bajt. Kód příkazu nebo odpovědi. Knihovna protokolu rezervuje rozsahy opcode podle účelu:

    • 0x00..0x0F – příkazy protokolu (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION).

    • 0x10..0x1F – systémové příkazy (RESET, BOOT, INFO, EVENT, MEMORY).

    • 0x20..0x2F – příkazy kanálu (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT).

  • len – dva bajty, little-endian. Počet bajtů užitečného obsahu, které následují po hlavičce. Délka nula je legální – mnoho potvrzení a malých příkazů nenese žádný užitečný obsah (payload).

  • crc – dva bajty. CRC-16 přes předchozích osm bajtů hlavičky. Příjemce, který dostane hlavičku se špatným CRC, zahodí celý paket, aniž by se vůbec podíval na užitečný obsah (payload).

12.3.2. Užitečný obsah (payload)#

Nula nebo více bajtů, vrstvou rámcování považovaných za neprůhledné. Co je v užitečném obsahu, závisí na opcode: pro odpověď CHANNEL_READ jsou to skutečná data kanálu; pro odpověď GET_CAPS je to malá pevná struktura; pro zápis na kanál je to cokoli, co hostitel poslal.

Maximální velikost užitečného obsahu (payload) závisí na velikosti bufferu protokolu kamery (viz tabulka podle desky v protocol.init()). Zprávy delší než limit jsou rozděleny na fragmenty s nastaveným příznakem FRAGMENT u všech kromě posledního.

12.3.3. Koncové CRC#

Čtyři bajty, CRC-32 přes užitečný obsah (payload). Zachytí poškození, které CRC hlavičky nedokáže vidět, zejména u dlouhých užitečných obsahů, kde by jinak jednobitová chyba uprostřed rámce proklouzla.

Rozdělení kontroly integrity mezi dvě CRC je záměrné. CRC hlavičky chrání samotná pole rámcování – zejména délku užitečného obsahu. Bez samostatného CRC hlavičky by jediný překlopený bit v bajtu délky způsobil, že by příjemce přečetl nesprávný počet bajtů užitečného obsahu a zcela se rozsynchronizoval s bajtovým proudem; s ním je poškozená hlavička rovnou odmítnuta a příjemce znovu hledá další synchronizační slovo. CRC užitečného obsahu pak chrání tělo zprávy jako samostatnou záležitost, takže překlopený bit v datech je hlášen jako poškozený užitečný obsah, nikoli zaměněn za chybu rámcování.

Formát je dost malý na to, aby se dal projít bajt po bajtu, a fakt, že každý paket má stejné rozvržení – synchronizace, pak hlavička, pak užitečný obsah, pak CRC – znamená, že ručně napsaný parser se vejde na jednu obrazovku kódu. Proto je drobná hostitelská implementace v C, Pythonu nebo Rustu víkendový projekt; knihovna protokolu je udržovaná verze v Pythonu na každé straně.