12.3. Format pakietu¶
Każdy bajt przechodzący przez przewód między kamerą a hostem jest częścią pakietu. Pakiet zaczyna się od 10-bajtowego nagłówka, zawiera ładunek o zmiennej długości i kończy się 4-bajtowym końcowym CRC. Na przewodzie nie pojawiają się żadne inne bajty – gdy host zobaczy 2-bajtowe słowo synchronizacji, kolejne bajty są nagłówkiem w dokładnie tej kolejności.
12.3.1. Nagłówek¶
Dziesięć bajtów, upakowanych bez dopełnienia. Każde pole:
sync– 16-bitowe słowo0xD5AAw kolejności little-endian. Bajt 0 na przewodzie to0xAA, bajt 1 to0xD5. Odbiornik skanujący bajty potrafi znaleźć początek pakietu, wyszukując paręAA D5; wszystko przed nią jest traktowane jako śmieci. Wybór wartości jest celowy:0xAAi0xD5rzadko pojawiają się w tekście drukowalnym, a para ta jest mało prawdopodobna do przypadkowego wystąpienia w środku ładunku.seq– jeden bajt. Licznik, który zwiększa się o jeden dla każdego pakietu wysłanego w danym kierunku. Odbiornik sprawdza, czy numer sekwencji kolejnego pakietu jest oczekiwany; jeśli nie, warstwa niezawodności prosi o retransmisję.chan– jeden bajt. Identyfikator kanału, do którego należy ten pakiet. Kanały 0..31 są dostępne; wbudowane kanałystdin,stdout,streamoraz (opcjonalnie)profilezajmują stałe identyfikatory zarezerwowane przez kamerę.flags– jeden bajt. Pole bitowe informujące odbiornik, jak interpretować pakiet:bit 0
ACK– ten pakiet jest potwierdzeniem poprzedniego.bit 1
NAK– ten pakiet odrzuca poprzedni.bit 2
RTX– ten pakiet jest retransmisją.bit 3
ACK_REQ– nadawca chce, aby ten pakiet został potwierdzony.bit 4
FRAGMENT– po tym pakiecie następują kolejne fragmenty większej wiadomości.bit 5
EVENT– ten pakiet niesie zdarzenie kanału zamiast danych.bity 6 i 7 są zarezerwowane.
opcode– jeden bajt. Kod polecenia lub odpowiedzi. Biblioteka protokołu rezerwuje zakresy kodów operacji według przeznaczenia:0x00..0x0F– polecenia protokołu (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION).0x10..0x1F– polecenia systemowe (RESET, BOOT, INFO, EVENT, MEMORY).0x20..0x2F– polecenia kanałów (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT).
len– dwa bajty, little-endian. Liczba bajtów ładunku następujących po nagłówku. Długość zero jest dozwolona – wiele potwierdzeń i małych poleceń nie niesie żadnego ładunku.crc– dwa bajty. CRC-16 obliczone z poprzednich ośmiu bajtów nagłówka. Odbiornik, który otrzyma nagłówek z błędnym CRC, odrzuca cały pakiet, nawet nie patrząc na ładunek.
12.3.2. Ładunek¶
Zero lub więcej bajtów, traktowanych przez warstwę ramkowania jako nieprzezroczyste. Zawartość ładunku zależy od kodu operacji: dla odpowiedzi CHANNEL_READ są to faktyczne dane kanału; dla odpowiedzi GET_CAPS jest to mała struktura o stałym rozmiarze; dla zapisu na kanale jest to cokolwiek, co wysłał host.
Maksymalny rozmiar ładunku zależy od rozmiaru bufora protokołu kamery (zobacz tabelę dla poszczególnych płytek w protocol.init()). Wiadomości dłuższe niż ten limit są dzielone na fragmenty z ustawioną flagą FRAGMENT na wszystkich oprócz ostatniego.
12.3.3. Końcowy CRC¶
Cztery bajty, CRC-32 obliczone z ładunku. Wychwytuje uszkodzenia, których CRC nagłówka nie jest w stanie zauważyć, szczególnie w przypadku długich ładunków, gdzie błąd pojedynczego bitu w środku ramki w przeciwnym razie przeszedłby niezauważony.
Rozdzielenie kontroli integralności na dwa CRC jest celowe. CRC nagłówka chroni same pola ramkowania – w szczególności długość ładunku. Bez osobnego CRC nagłówka pojedyncze odwrócenie bitu w bajcie długości spowodowałoby, że odbiornik odczytałby błędną liczbę bajtów ładunku i całkowicie rozsynchronizował się ze strumieniem bajtów; przy jego obecności uszkodzony nagłówek jest od razu odrzucany, a odbiornik ponownie skanuje w poszukiwaniu kolejnego słowa synchronizacji. CRC ładunku chroni następnie treść wiadomości jako odrębną kwestię, dzięki czemu odwrócenie bitu w danych jest zgłaszane jako uszkodzony ładunek, a nie mylone z błędem ramkowania.
Format jest na tyle mały, że można go prześledzić bajt po bajcie, a fakt, że każdy pakiet ma ten sam układ – synchronizacja, potem nagłówek, potem ładunek, potem CRC – oznacza, że ręcznie napisany parser mieści się na jednym ekranie kodu. Dlatego niewielka implementacja hosta w C, Pythonie lub Ruście to projekt na weekend; biblioteka protokołu to utrzymywana wersja Pythona po każdej ze stron.