12.3. Format paket

Setiap byte yang melewati wire antara kamera dan host adalah bagian dari sebuah paket. Sebuah paket dimulai dengan header 10-byte, diikuti payload dengan panjang variabel, dan diakhiri dengan CRC trailing 4-byte. Tidak ada byte lain yang muncul di wire -- setelah host melihat kata sinkronisasi 2-byte, byte berikutnya adalah header dalam urutan yang tepat ini.

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. Header

Sepuluh byte, dikemas tanpa padding. Setiap field:

  • sync -- kata 16-bit 0xD5AA dalam urutan little-endian. Byte 0 di wire adalah 0xAA, byte 1 adalah 0xD5. Penerima yang memindai byte dapat menemukan awal paket dengan mencari pasangan AA D5; apa pun sebelumnya dianggap sampah. Pemilihan nilai ini disengaja: 0xAA dan 0xD5 jarang muncul dalam teks yang dapat dicetak, dan pasangan ini kecil kemungkinan muncul secara tidak sengaja di tengah payload.

  • seq -- satu byte. Counter yang bertambah satu untuk setiap paket yang dikirim pada arah tertentu. Penerima memeriksa bahwa sequence number paket berikutnya adalah yang diharapkan; jika tidak, layer reliabilitas meminta retransmit.

  • chan -- satu byte. ID channel tempat paket ini berada. Channel 0..31 dapat digunakan; channel bawaan stdin, stdout, stream, dan (opsional) profile menggunakan ID tetap yang dicadangkan kamera.

  • flags -- satu byte. Bit-field yang memberi tahu penerima cara menginterpretasikan paket:

    • bit 0 ACK -- paket ini adalah pengakuan dari paket sebelumnya.

    • bit 1 NAK -- paket ini menolak paket sebelumnya.

    • bit 2 RTX -- paket ini adalah retransmit.

    • bit 3 ACK_REQ -- pengirim ingin paket ini diakui.

    • bit 4 FRAGMENT -- lebih banyak fragmen mengikuti yang ini dalam pesan yang lebih besar.

    • bit 5 EVENT -- paket ini membawa event channel bukan data.

    • bit 6 dan 7 dicadangkan.

  • opcode -- satu byte. Kode perintah atau respons. Library protokol mencadangkan rentang opcode berdasarkan tujuan:

    • 0x00..0x0F -- perintah protokol (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION).

    • 0x10..0x1F -- perintah sistem (RESET, BOOT, INFO, EVENT, MEMORY).

    • 0x20..0x2F -- perintah channel (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT).

  • len -- dua byte, little-endian. Jumlah byte payload yang mengikuti header. Panjang nol adalah sah -- banyak pengakuan dan perintah kecil tidak membawa payload.

  • crc -- dua byte. CRC-16 atas delapan byte header sebelumnya. Penerima yang mendapatkan header dengan CRC yang buruk membuang seluruh paket tanpa melihat payload.

12.3.2. Payload

Nol atau lebih byte, diperlakukan sebagai opaque oleh layer framing. Isi payload bergantung pada opcode: untuk balasan CHANNEL_READ berisi data channel aktual; untuk balasan GET_CAPS berisi struktur tetap kecil; untuk penulisan channel berisi apa pun yang dikirim host.

Ukuran payload maksimum bergantung pada ukuran buffer protokol kamera (lihat tabel per-board di protocol.init()). Pesan yang lebih panjang dari batas dibagi menjadi fragmen dengan flag FRAGMENT diset pada semua kecuali yang terakhir.

12.3.3. CRC trailing

Empat byte, CRC-32 atas payload. Menangkap kerusakan yang tidak dapat dilihat oleh header CRC, terutama pada payload panjang di mana kesalahan satu bit di tengah bingkai sebaliknya akan lolos.

Memisahkan pemeriksaan integritas ke dalam dua CRC adalah disengaja. Header CRC melindungi field framing itu sendiri -- terutama panjang payload. Tanpa header CRC terpisah, satu bit flip pada byte panjang akan menyebabkan penerima membaca jumlah byte yang salah untuk payload dan kehilangan sinkronisasi dari stream byte sepenuhnya; dengan adanya header CRC, header yang rusak langsung ditolak dan penerima memindai ulang untuk kata sinkronisasi berikutnya. Payload CRC kemudian melindungi badan pesan sebagai masalah terpisah, sehingga bit flip pada data dilaporkan sebagai payload yang rusak bukan sebagai kesalahan framing.

Format ini cukup kecil untuk ditelusuri byte per byte, dan fakta bahwa setiap paket memiliki tata letak yang sama -- sinkronisasi, lalu header, lalu payload, lalu CRC -- berarti parser buatan tangan muat dalam satu layar kode. Itulah mengapa implementasi host kecil dalam C, Python, atau Rust adalah proyek akhir pekan; library protokol adalah versi Python yang dirawat di setiap sisi.