12.4. Handshake e negociação de capacidades

A câmera e o host chegam ao transporte cada um com suas próprias ideias sobre como o protocolo deve funcionar: quais modos de CRC, se ACKs são obrigatórios, qual é a maior carga que conseguem armazenar em buffer. Antes que o tráfego real comece, eles trocam um handshake que fixa esses parâmetros para o resto da sessão.

12.4.1. O host abre a conexão

O lado da câmera inicia a pilha de protocolo na inicialização (ou a aplicação a reinicia com protocol.init() para mudar parâmetros) e então fica quieto aguardando um host. Do ponto de vista da câmera, não há nada a fazer até que um pacote chegue.

O lado do host abre o transporte – porta USB ou UART – e imediatamente envia um pacote PROTO_SYNC (opcode 0x00). Esse pacote tem uma carga mágica que permite à câmera reconhecê-lo mesmo que ambos os lados tenham perdido a sincronia, e é o único pacote ao qual a câmera responde antes de as capacidades serem negociadas.

Se a câmera não responder dentro do tempo limite de retransmissão, o host envia PROTO_SYNC novamente, até rtx_retries vezes. Depois disso ele desiste e reporta uma falha de conexão. A retentativa é o que faz “desconectar, reconectar, reiniciar o script do host” funcionar sem que a câmera precise saber que o host se foi.

12.4.2. Troca de capacidades

Assim que a câmera confirma a sincronização, o host envia PROTO_GET_CAPS (opcode 0x01) para perguntar o que a câmera suporta. A carga de resposta reporta:

  • Validação de CRC habilitada ou desabilitada

  • Rastreamento de número de sequência habilitado ou desabilitado

  • ACKs habilitados ou desabilitados

  • Notificações de eventos habilitadas ou desabilitadas

  • O tamanho máximo de carga da câmera em bytes

  • A contagem atual de retentativas de retransmissão, o tempo limite e os parâmetros de polling

O host compara esses valores com sua própria configuração. Se o host precisar mudar algum deles – por exemplo, para negociar uma carga máxima menor porque seu buffer de recepção é menor que o da câmera – ele envia PROTO_SET_CAPS (opcode 0x02) com os novos valores. A câmera reconfigura sua pilha e confirma. A partir daqui, todo pacote que cruza a transmissão segue esse contrato compartilhado.

Se o host não sobrescrever nada, os padrões estão todos ativos: validação de CRC, rastreamento de número de sequência, ACKs e notificações de eventos. A carga máxima padrão é o buffer por placa da câmera menos 14 bytes de sobrecarga de enquadramento (o cabeçalho de 10 bytes mais o CRC de carga final de 4 bytes). Para a maior parte do trabalho câmera-para-laptop os padrões são o ponto de partida certo; a página de confiabilidade aborda quando e por que uma aplicação opta por desativar partes deles.

12.4.3. Descoberta de canais

Após as capacidades, o host envia CHANNEL_LIST (opcode 0x20). A câmera responde com uma lista de canais registrados – os quatro embutidos (stdin, stdout, stream, profile) mais quaisquer que a aplicação tenha registrado com protocol.register(). Cada entrada carrega o ID do canal, seu nome e suas flags de capacidade (somente leitura, somente escrita, bloqueável).

O host guarda a lista e a usa depois, quando o código da aplicação solicita channel_read("frame") ou channel_write("config", ...) – o nome é resolvido para um ID de canal uma vez, e então todo pacote subsequente naquele canal usa o ID diretamente.

Se a câmera registrar um novo canal após a lista inicial – comum quando uma aplicação começa a rodar depois do handshake – a câmera emite um pacote de evento CHANNEL_REGISTERED. O host escuta esses eventos e atualiza sua lista interna de canais, de modo que um script de host que se conectou cedo vê canais recém-registrados aparecerem sem reiniciar.

O handshake leva algumas idas e vindas na configuração da conexão e então nunca se repete. O tráfego em regime permanente é apenas pacotes: bytes enquadrados entrando, bytes enquadrados saindo, com os IDs de canal já conhecidos em ambos os lados.