12.4. 핸드셰이크 및 기능 협상

카메라와 호스트는 모두 프로토콜이 어떻게 동작해야 하는지에 대한 각자의 생각을 가지고 트랜스포트에 도달합니다: 어떤 CRC 모드를 쓸지, ACK가 필요한지, 버퍼링할 수 있는 최대 페이로드가 얼마인지 등입니다. 실제 트래픽이 시작되기 전에 양측은 세션의 나머지 기간 동안 이러한 매개변수를 고정하는 핸드셰이크를 교환합니다.

12.4.1. 호스트가 연결을 엽니다

카메라 측은 부팅 시 프로토콜 스택을 시작하며(또는 애플리케이션이 매개변수를 변경하기 위해 protocol.init() 으로 재시작), 그 후 호스트를 조용히 기다립니다. 카메라 관점에서는 패킷이 도착할 때까지 할 일이 없습니다.

호스트 측은 트랜스포트 – USB 포트 또는 UART – 를 열고 즉시 PROTO_SYNC 패킷(opcode 0x00)을 보냅니다. 이 패킷에는 양측의 동기가 어긋났더라도 카메라가 이를 인식할 수 있게 해 주는 매직 페이로드가 있으며, 기능이 협상되기 전에 카메라가 응답하는 유일한 패킷입니다.

카메라가 재전송 타임아웃 내에 응답하지 않으면 호스트는 rtx_retries 횟수까지 PROTO_SYNC 를 다시 보냅니다. 그 후에는 포기하고 연결 실패를 보고합니다. 이 재시도 덕분에 “뽑았다 다시 꽂고, 호스트 스크립트 재시작” 이 카메라가 호스트가 사라졌음을 알 필요 없이 동작합니다.

12.4.2. 기능 교환

카메라가 동기화를 확인하고 나면, 호스트는 카메라가 무엇을 지원하는지 묻기 위해 PROTO_GET_CAPS (opcode 0x01)를 보냅니다. 응답 페이로드는 다음을 보고합니다:

  • CRC 검증 활성화 또는 비활성화

  • 시퀀스 번호 추적 활성화 또는 비활성화

  • ACK 활성화 또는 비활성화

  • 이벤트 알림 활성화 또는 비활성화

  • 카메라의 최대 페이로드 크기(바이트 단위)

  • 현재 재전송 재시도 횟수, 타임아웃, 폴링 매개변수

호스트는 이를 자신의 설정과 비교합니다. 호스트가 그중 어느 하나라도 변경 해야 한다면 – 예를 들어 수신 버퍼가 카메라보다 작아서 더 작은 최대 페이로드를 협상해야 하는 경우 – 새 값과 함께 PROTO_SET_CAPS (opcode 0x02)를 보냅니다. 카메라는 스택을 재구성하고 이를 확인합니다. 이후로는 와이어를 건너는 모든 패킷이 그 공유된 계약을 따릅니다.

호스트가 아무것도 재정의하지 않으면 기본값은 모두 켜져 있습니다: CRC 검증, 시퀀스 번호 추적, ACK, 이벤트 알림입니다. 기본 최대 페이로드는 카메라의 보드별 버퍼에서 프레이밍 오버헤드 14바이트(10바이트 헤더에 4바이트 후행 페이로드 CRC를 더한 것)를 뺀 값입니다. 대부분의 카메라-노트북 작업에서는 기본값이 올바른 출발점이며, 애플리케이션이 그중 일부를 언제 왜 끄는지는 신뢰성 페이지에서 다룹니다.

12.4.3. 채널 검색

기능 교환 후 호스트는 CHANNEL_LIST (opcode 0x20)를 보냅니다. 카메라는 등록된 채널 목록으로 응답합니다 – 네 개의 내장 채널(stdin, stdout, stream, profile)과 애플리케이션이 protocol.register() 로 등록한 채널들입니다. 각 항목에는 채널의 ID, 이름, 그리고 기능 플래그(읽기 전용, 쓰기 전용, 잠금 가능)가 담겨 있습니다.

호스트는 이 목록을 보관해 두었다가, 나중에 애플리케이션 코드가 channel_read("frame") 또는 channel_write("config", ...) 를 요청할 때 사용합니다 – 이름은 한 번 채널 ID로 조회되고, 그 후 해당 채널의 모든 후속 패킷은 ID를 직접 사용합니다.

카메라가 초기 목록 이후에 새 채널을 등록하면 – 핸드셰이크 후에 애플리케이션이 실행되기 시작할 때 흔한 일입니다 – 카메라는 CHANNEL_REGISTERED 이벤트 패킷을 발생시킵니다. 호스트는 이를 수신 대기하다가 내부 채널 목록을 갱신하므로, 일찍 연결된 호스트 스크립트도 재시작 없이 새로 등록된 채널이 나타나는 것을 볼 수 있습니다.

핸드셰이크는 연결 설정 시 몇 차례의 왕복을 거치고 나면 다시는 반복되지 않습니다. 정상 상태 트래픽은 그저 패킷일 뿐입니다: 프레임화된 바이트가 들어오고 나가며, 채널 ID는 양측에서 이미 알고 있습니다.