12.4. Uzgadnianie i negocjacja możliwości¶
Kamera i host docierają do warstwy transportowej, mając własne wyobrażenia o tym, jak protokół powinien działać: które tryby CRC, czy wymagane są ACK-i oraz jaki jest największy ładunek (payload), który potrafią zbuforować. Zanim ruszy właściwy ruch, wymieniają uzgadnianie, które ustala te parametry na resztę sesji.
12.4.1. Host otwiera połączenie¶
Strona kamery uruchamia stos protokołu przy starcie (lub aplikacja restartuje go za pomocą protocol.init(), aby zmienić parametry), a następnie czeka cicho na hosta. Z punktu widzenia kamery nie ma nic do zrobienia, dopóki nie nadejdzie pakiet.
Strona hosta otwiera transport – port USB lub UART – i natychmiast wysyła pakiet PROTO_SYNC (kod operacji 0x00). Ten pakiet ma magiczny ładunek, który pozwala kamerze rozpoznać go nawet wtedy, gdy obie strony się rozsynchronizowały, i jest to jedyny pakiet, na który kamera kiedykolwiek odpowiada przed wynegocjowaniem możliwości.
Jeśli kamera nie odpowie w czasie limitu retransmisji, host wysyła PROTO_SYNC ponownie, maksymalnie rtx_retries razy. Po tym poddaje się i zgłasza niepowodzenie połączenia. To właśnie ponowna próba sprawia, że „odłącz, podłącz, zrestartuj skrypt hosta” działa, a kamera nie musi wiedzieć, że host zniknął.
12.4.2. Wymiana możliwości¶
Gdy kamera potwierdzi synchronizację, host wysyła PROTO_GET_CAPS (kod operacji 0x01), aby zapytać, co kamera obsługuje. Ładunek odpowiedzi raportuje:
Walidacja CRC włączona lub wyłączona
Śledzenie numerów sekwencji włączone lub wyłączone
ACK-i włączone lub wyłączone
Powiadomienia o zdarzeniach włączone lub wyłączone
Maksymalny rozmiar ładunku kamery w bajtach
Bieżąca liczba ponownych prób retransmisji, limit czasu oraz parametry odpytywania
Host porównuje je z własną konfiguracją. Jeśli host musi zmienić którykolwiek z nich – na przykład wynegocjować mniejszy maksymalny ładunek, ponieważ jego bufor odbiorczy jest mniejszy niż kamery – wysyła PROTO_SET_CAPS (kod operacji 0x02) z nowymi wartościami. Kamera rekonfiguruje swój stos i potwierdza. Od tej chwili każdy pakiet przechodzący przez przewód podlega temu wspólnemu kontraktowi.
Jeśli host niczego nie nadpisuje, wszystkie domyślne ustawienia są włączone: walidacja CRC, śledzenie numerów sekwencji, ACK-i oraz powiadomienia o zdarzeniach. Domyślny maksymalny ładunek to bufor kamery właściwy dla danej płytki pomniejszony o 14 bajtów narzutu ramkowania (10-bajtowy nagłówek plus 4-bajtowy końcowy CRC ładunku). Dla większości zastosowań kamera-laptop ustawienia domyślne są właściwym punktem wyjścia; strona poświęcona niezawodności omawia, kiedy i dlaczego aplikacja wyłącza ich poszczególne elementy.
12.4.3. Wykrywanie kanałów¶
Po uzgodnieniu możliwości host wysyła CHANNEL_LIST (kod operacji 0x20). Kamera odpowiada listą zarejestrowanych kanałów – czterech wbudowanych (stdin, stdout, stream, profile) plus dowolnych zarejestrowanych przez aplikację za pomocą protocol.register(). Każdy wpis niesie identyfikator kanału, jego nazwę oraz flagi możliwości (tylko do odczytu, tylko do zapisu, możliwy do zablokowania).
Host zapamiętuje listę i używa jej później, gdy kod aplikacji prosi o channel_read("frame") lub channel_write("config", ...) – nazwa jest jednorazowo wyszukiwana w celu odnalezienia identyfikatora kanału, a następnie każdy kolejny pakiet na tym kanale używa identyfikatora bezpośrednio.
Jeśli kamera zarejestruje nowy kanał po początkowej liście – co jest częste, gdy aplikacja zaczyna działać po uzgodnieniu – kamera emituje pakiet zdarzenia CHANNEL_REGISTERED. Host nasłuchuje ich i odświeża swoją wewnętrzną listę kanałów, dzięki czemu skrypt hosta podłączony wcześnie widzi pojawienie się nowo zarejestrowanych kanałów bez konieczności restartu.
Uzgadnianie zajmuje kilka cykli obiegu przy nawiązywaniu połączenia, a potem nigdy się nie powtarza. Ruch w stanie ustalonym to po prostu pakiety: ramkowane bajty do środka, ramkowane bajty na zewnątrz, a identyfikatory kanałów są już znane po obu stronach.