12.4. Negocierea conexiunii (handshake) și a capabilităților¶
Atât camera, cât și gazda ajung la transport cu propriile idei despre cum ar trebui să ruleze protocolul: ce moduri CRC, dacă sunt necesare confirmările (ACK), care este cea mai mare sarcină utilă pe care o pot stoca în tampon. Înainte ca traficul real să înceapă, ele schimbă o negociere (handshake) care fixează acei parametri pentru restul sesiunii.
12.4.1. Gazda deschide conexiunea¶
Partea camerei pornește stiva de protocol la pornire (sau aplicația o repornește cu protocol.init() pentru a schimba parametrii), apoi rămâne liniștită așteptând o gazdă. Din punctul de vedere al camerei, nu este nimic de făcut până când sosește un pachet.
Partea gazdei deschide transportul – port USB sau UART – și trimite imediat un pachet PROTO_SYNC (codul de operație 0x00). Acest pachet are o sarcină utilă magică ce permite camerei să-l recunoască chiar dacă ambele părți s-au desincronizat și este singurul pachet la care camera răspunde vreodată înainte ca capabilitățile să fie negociate.
Dacă camera nu răspunde în timpul limitei de retransmisie, gazda trimite din nou PROTO_SYNC, de până la rtx_retries ori. După aceea renunță și raportează un eșec de conexiune. Reîncercarea este ceea ce face ca „deconectează, reconectează, repornește scriptul gazdei” să funcționeze fără ca camera să trebuiască să știe că gazda a dispărut.
12.4.2. Schimbul de capabilități¶
Odată ce camera confirmă sincronizarea, gazda trimite PROTO_GET_CAPS (codul de operație 0x01) pentru a întreba ce acceptă camera. Sarcina utilă a răspunsului raportează:
validarea CRC activată sau dezactivată
urmărirea numărului de secvență activată sau dezactivată
confirmările (ACK) activate sau dezactivate
notificările de evenimente activate sau dezactivate
dimensiunea maximă a sarcinii utile a camerei, în octeți
numărul curent de reîncercări de retransmisie, limita de timp și parametrii de interogare (polling)
Gazda compară acele valori cu propria configurație. Dacă gazda trebuie să schimbe vreuna dintre ele – de exemplu, pentru a negocia o sarcină utilă maximă mai mică deoarece tamponul său de recepție este mai mic decât al camerei – trimite PROTO_SET_CAPS (codul de operație 0x02) cu noile valori. Camera își reconfigurează stiva și confirmă. De aici încolo, fiecare pachet care traversează linia respectă acel contract partajat.
Dacă gazda nu suprascrie nimic, valorile implicite sunt toate activate: validarea CRC, urmărirea numărului de secvență, confirmările (ACK) și notificările de evenimente. Sarcina utilă maximă implicită este tamponul per placă al camerei minus 14 octeți de supraîncărcare de încadrare (antetul de 10 octeți plus CRC-ul de 4 octeți de la finalul sarcinii utile). Pentru majoritatea lucrărilor cameră-laptop, valorile implicite sunt punctul de plecare corect; pagina despre fiabilitate descrie când și de ce o aplicație dezactivează părți din acestea.
12.4.3. Descoperirea canalelor¶
După capabilități, gazda trimite CHANNEL_LIST (codul de operație 0x20). Camera răspunde cu o listă de canale înregistrate – cele patru încorporate (stdin, stdout, stream, profile) plus oricare altele înregistrate de aplicație cu protocol.register(). Fiecare intrare conține ID-ul canalului, numele său și indicatorii de capabilitate (doar-citire, doar-scriere, blocabil).
Gazda stochează lista și o folosește mai târziu când codul aplicației cere channel_read("frame") sau channel_write("config", ...) – numele este căutat o singură dată pentru a obține un ID de canal, apoi fiecare pachet ulterior pe acel canal folosește direct ID-ul.
Dacă camera înregistrează un canal nou după lista inițială – ceva obișnuit când o aplicație începe să ruleze după negociere – camera emite un pachet de eveniment CHANNEL_REGISTERED. Gazda ascultă după acestea și își reîmprospătează lista internă de canale, astfel încât un script de gazdă care s-a atașat devreme vede apărând canalele nou înregistrate fără a reporni.
Negocierea necesită câteva schimburi dus-întors la configurarea conexiunii și apoi nu se mai repetă niciodată. Traficul în regim stabil este doar pachete: octeți încadrați la intrare, octeți încadrați la ieșire, ID-urile de canal fiind deja cunoscute de ambele părți.