12.3. Формат пакету

Кожен байт, що перетинає дріт між камерою та хостом, є частиною пакету. Пакет починається з 10-байтного заголовка, містить корисне навантаження змінної довжини та завершується 4-байтним кінцевим CRC. На дроті не з’являються жодні інші байти – після того як хост побачив 2-байтне синхрослово, наступні байти є заголовком у такій точній послідовності.

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. Заголовок

Десять байтів, упакованих без відступів. Кожне поле:

  • sync – 16-бітне слово 0xD5AA у форматі little-endian. Байт 0 на дроті – 0xAA, байт 1 – 0xD5. Одержувач, що сканує байти, може знайти початок пакету, шукаючи пару AA D5; все, що перед нею, вважається сміттям. Вибір значення є навмисним: 0xAA та 0xD5 рідко зустрічаються в друкованому тексті, і пара навряд чи виникне випадково всередині корисного навантаження.

  • seq – один байт. Лічильник, що збільшується на одиницю для кожного надісланого пакету у заданому напрямку. Одержувач перевіряє, що порядковий номер наступного пакету є очікуваним; якщо ні, рівень надійності запитує повторну передачу.

  • chan – один байт. ID каналу, якому належить цей пакет. Канали 0..31 є придатними для використання; вбудовані канали stdin, stdout, stream та (опційно) profile отримують фіксовані ID, зарезервовані камерою.

  • flags – один байт. Бітове поле, що повідомляє одержувачу, як інтерпретувати пакет:

    • біт 0 ACK – цей пакет є підтвердженням попереднього.

    • біт 1 NAK – цей пакет відхиляє попередній.

    • біт 2 RTX – цей пакет є повторною передачею.

    • біт 3 ACK_REQ – відправник бажає, щоб цей пакет було підтверджено.

    • біт 4 FRAGMENT – за цим фрагментом ідуть ще в межах більшого повідомлення.

    • біт 5 EVENT – цей пакет містить подію каналу, а не дані.

    • біти 6 та 7 зарезервовані.

  • opcode – один байт. Код команди або відповіді. Бібліотека протоколу резервує діапазони опкодів за призначенням:

    • 0x00..0x0F – команди протоколу (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION).

    • 0x10..0x1F – системні команди (RESET, BOOT, INFO, EVENT, MEMORY).

    • 0x20..0x2F – команди каналів (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT).

  • len – два байти, little-endian. Кількість байтів корисного навантаження, що йдуть після заголовка. Довжина нуль є допустимою – багато підтверджень і невеликих команд не містять корисного навантаження.

  • crc – два байти. CRC-16 від попередніх восьми байтів заголовка. Одержувач, що отримав заголовок із неправильним CRC, відкидає весь пакет, навіть не дивлячись на корисне навантаження.

12.3.2. Корисне навантаження

Нуль або більше байтів, що вважаються непрозорими для рівня обрамлення. Вміст корисного навантаження залежить від опкоду: для відповіді CHANNEL_READ – це фактичні дані каналу; для відповіді GET_CAPS – невелика фіксована структура; для запису в канал – це те, що надіслав хост.

Максимальний розмір корисного навантаження залежить від розміру буфера протоколу камери (зверніться до таблиці для відповідної плати у protocol.init()). Повідомлення, що перевищують ліміт, розбиваються на фрагменти з прапорцем FRAGMENT, встановленим для всіх, крім останнього.

12.3.3. Кінцевий CRC

Чотири байти, CRC-32 від корисного навантаження. Виявляє пошкодження, яке не може побачити CRC заголовка, зокрема у довгих корисних навантаженнях, де інакше одноразова помилка посередині кадру непомітно проскочила б.

Розбиття перевірки цілісності на два CRC є навмисним. CRC заголовка захищає самі поля обрамлення – зокрема довжину корисного навантаження. Без окремого CRC заголовка єдине перевернуте бітове значення в байті довжини змусило б одержувача прочитати неправильну кількість байтів корисного навантаження і повністю вийти із синхронізації з байтовим потоком; з ним пошкоджений заголовок одразу відхиляється, а одержувач знову шукає наступне синхрослово. CRC корисного навантаження потім захищає тіло повідомлення як окрему проблему, тому перевернутий біт у даних повідомляється як пошкоджене корисне навантаження, а не помилка обрамлення.

Формат достатньо малий, щоб розібрати його байт за байтом, а той факт, що кожен пакет має однакове розташування – синхрослово, потім заголовок, потім корисне навантаження, потім CRC – означає, що власноруч написаний аналізатор вміщується на екрані коду. Саме тому мала реалізація хоста на C, Python або Rust – це проект вихідних днів; бібліотека протоколу є підтримуваною версією на Python для кожної зі сторін.