12.4. Рукопожатие и согласование возможностей

Камера и хост оба приходят к транспорту со своими собственными представлениями о том, как должен работать протокол: какие режимы CRC, требуются ли ACK, какой наибольший объём полезных данных они могут буферизовать. Прежде чем начнётся реальный трафик, они обмениваются рукопожатием, которое фиксирует эти параметры на остаток сессии.

12.4.1. Хост открывает соединение

Сторона камеры запускает стек протокола при загрузке (или приложение перезапускает его через protocol.init(), чтобы изменить параметры), затем тихо ждёт хост. С точки зрения камеры делать нечего, пока не придёт пакет.

Сторона хоста открывает транспорт – USB-порт или UART – и немедленно отправляет пакет PROTO_SYNC (код операции 0x00). У этого пакета есть магическая полезная нагрузка, которая позволяет камере распознать его, даже если обе стороны рассинхронизировались, и это единственный пакет, на который камера вообще отвечает до согласования возможностей.

Если камера не отвечает в течение тайм-аута повторной передачи, хост снова отправляет PROTO_SYNC, до rtx_retries раз. После этого он сдаётся и сообщает о сбое соединения. Именно повторная попытка заставляет работать сценарий «отключить, подключить заново, перезапустить хост-скрипт» без необходимости камере знать, что хост ушёл.

12.4.2. Обмен возможностями

Как только камера подтверждает синхронизацию, хост отправляет PROTO_GET_CAPS (код операции 0x01), чтобы спросить, что камера поддерживает. Полезная нагрузка ответа сообщает:

  • Проверка CRC включена или отключена

  • Отслеживание порядковых номеров включено или отключено

  • ACK включены или отключены

  • Уведомления о событиях включены или отключены

  • Максимальный размер полезной нагрузки камеры в байтах

  • Текущее число повторов передачи, тайм-аут и параметры опроса

Хост сравнивает их со своей собственной конфигурацией. Если хосту нужно изменить какие-либо из них – например, чтобы согласовать меньшую максимальную полезную нагрузку, поскольку его приёмный буфер меньше, чем у камеры – он отправляет PROTO_SET_CAPS (код операции 0x02) с новыми значениями. Камера перенастраивает свой стек и подтверждает. С этого момента каждый пакет, пересекающий линию, следует этому общему контракту.

Если хост ничего не переопределяет, все значения по умолчанию включены: проверка CRC, отслеживание порядковых номеров, ACK и уведомления о событиях. Максимальная полезная нагрузка по умолчанию – это буфер камеры на конкретную плату минус 14 байт накладных расходов на формирование кадра (10-байтовый заголовок плюс 4-байтовый завершающий CRC полезной нагрузки). Для большинства задач «камера-ноутбук» значения по умолчанию – правильная отправная точка; страница о надёжности рассказывает, когда и почему приложение отключает какие-то из них.

12.4.3. Обнаружение каналов

После возможностей хост отправляет CHANNEL_LIST (код операции 0x20). Камера отвечает списком зарегистрированных каналов – четырёх встроенных (stdin, stdout, stream, profile) плюс любых, которые приложение зарегистрировало через protocol.register(). Каждая запись несёт ID канала, его имя и его флаги возможностей (только для чтения, только для записи, блокируемый).

Хост сохраняет список и использует его позже, когда прикладной код запрашивает channel_read("frame") или channel_write("config", ...) – имя один раз сопоставляется с ID канала, а затем каждый последующий пакет на этом канале использует ID напрямую.

Если камера регистрирует новый канал после первоначального списка – что обычно происходит, когда приложение начинает работать после рукопожатия – камера испускает пакет события CHANNEL_REGISTERED. Хост слушает их и обновляет свой внутренний список каналов, так что хост-скрипт, подключившийся рано, видит появление вновь зарегистрированных каналов без перезапуска.

Рукопожатие занимает несколько циклов обмена при установке соединения, а затем никогда не повторяется. Трафик в установившемся режиме – это просто пакеты: байты в кадрах внутрь, байты в кадрах наружу, ID каналов уже известны обеим сторонам.