12.3. Il formato del pacchetto¶
Ogni byte che attraversa la linea tra la camera e l’host fa parte di un pacchetto. Un pacchetto inizia con un’intestazione di 10 byte, prosegue con un payload di lunghezza variabile e termina con un CRC finale di 4 byte. Nessun altro byte compare sulla linea – una volta che l’host ha visto la parola di sincronizzazione di 2 byte, i byte successivi sono un’intestazione in questa sequenza esatta.
12.3.1. L’intestazione¶
Dieci byte, impacchettati senza padding. Ogni campo:
sync– la parola a 16 bit0xD5AAin ordine little-endian. Il byte 0 sulla linea è0xAA, il byte 1 è0xD5. Un ricevitore che scandisce i byte può trovare l’inizio di un pacchetto cercando la coppiaAA D5; tutto ciò che la precede è trattato come spazzatura. La scelta del valore è deliberata:0xAAe0xD5compaiono raramente nel testo stampabile, ed è improbabile che la coppia si verifichi per caso nel mezzo di un payload.seq– un byte. Un contatore che si incrementa di uno per ogni pacchetto inviato in una data direzione. Il ricevitore verifica che il numero di sequenza del pacchetto successivo sia quello atteso; in caso contrario, il livello di affidabilità chiede una ritrasmissione.chan– un byte. L’ID del canale a cui appartiene questo pacchetto. I canali da 0 a 31 sono utilizzabili; i canali integratistdin,stdout,streame (opzionalmente)profileoccupano ID fissi che la camera riserva.flags– un byte. Un campo di bit che indica al ricevitore come interpretare il pacchetto:bit 0
ACK– questo pacchetto è una conferma di uno precedente.bit 1
NAK– questo pacchetto rifiuta uno precedente.bit 2
RTX– questo pacchetto è una ritrasmissione.bit 3
ACK_REQ– il mittente vuole che questo pacchetto venga confermato.bit 4
FRAGMENT– altri frammenti seguono questo in un messaggio più grande.bit 5
EVENT– questo pacchetto trasporta un evento di canale anziché dati.i bit 6 e 7 sono riservati.
opcode– un byte. Il codice di comando o di risposta. La libreria di protocollo riserva intervalli di opcode per scopo:0x00..0x0F– comandi di protocollo (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION).0x10..0x1F– comandi di sistema (RESET, BOOT, INFO, EVENT, MEMORY).0x20..0x2F– comandi di canale (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT).
len– due byte, little-endian. Il numero di byte di payload che seguono l’intestazione. Una lunghezza pari a zero è valida – molte conferme e piccoli comandi non trasportano alcun payload.crc– due byte. Un CRC-16 sui precedenti otto byte dell’intestazione. Un ricevitore che riceve un’intestazione con un CRC errato scarta l’intero pacchetto senza nemmeno guardare il payload.
12.3.2. Il payload¶
Zero o più byte, trattati come opachi dal livello di framing. Ciò che si trova nel payload dipende dall’opcode: per una risposta CHANNEL_READ sono i dati effettivi del canale; per una risposta GET_CAPS è una piccola struttura fissa; per una scrittura su canale è qualunque cosa l’host abbia inviato.
La dimensione massima del payload dipende dalla dimensione del buffer di protocollo della camera (fai riferimento alla tabella per scheda in protocol.init()). I messaggi più lunghi del limite vengono suddivisi in frammenti con il flag FRAGMENT impostato su tutti tranne l’ultimo.
12.3.3. Il CRC finale¶
Quattro byte, un CRC-32 sul payload. Rileva la corruzione che il CRC dell’intestazione non può vedere, in particolare su payload lunghi dove un errore di singolo bit a metà del frame altrimenti sfuggirebbe.
Suddividere il controllo di integrità tra due CRC è deliberato. Il CRC dell’intestazione protegge i campi di framing stessi – in particolare la lunghezza del payload. Senza un CRC dell’intestazione separato, l’inversione di un singolo bit nel byte di lunghezza farebbe leggere al ricevitore il numero errato di byte per il payload, desincronizzandolo completamente dal flusso di byte; con esso, un’intestazione danneggiata viene rifiutata del tutto e il ricevitore ricerca nuovamente la parola di sincronizzazione successiva. Il CRC del payload protegge poi il corpo del messaggio come questione a sé, così l’inversione di un bit nei dati viene segnalata come payload corrotto anziché scambiata per un errore di framing.
Il formato è abbastanza piccolo da poter essere percorso byte per byte, e il fatto che ogni pacchetto abbia lo stesso layout – sync, poi intestazione, poi payload, poi CRC – significa che un parser scritto a mano sta in una schermata di codice. Ecco perché una minuscola implementazione host in C, Python o Rust è un progetto da fine settimana; la libreria di protocollo è la versione Python mantenuta su ciascun lato.