Skip to content

Hardware Protocol Specification: Bluetooth HCI UART Transport (H4)

Version: 5.4
Physical Layer: 115200 bps, 8N1.0
Framing: binary
Integrity Algorithm: none

📄 AsyncAPI Artifacts: Download AsyncAPI 2.6.0 YAML | View Interactive AsyncAPI HTML Docs

Description

Host <-> Bluetooth radio controller link. Includes HCI_Set_AFH_Host_Channel_Classification, which is literally a frequency-hopping control command: it tells the radio which of Bluetooth's 79 hop channels to avoid. No checksum at all -- H4 relies entirely on the underlying UART/transport for integrity.

Command Catalog & Message Signatures

Category: GENERAL

HCI_Set_AFH_Host_Channel_Classification (Command ID: 0xC3F) - typeField=0x01 (Command), using framing's top-level lengthField (no variantsByType entry needed for Command itself). opcode is now a named, typed position=before-length-field value (OGF=0x03 Host Controller & Baseband, OCF=0x3F -> 0x0C3F) rather than an anonymous 2-byte count, and doubles as this message's discriminator against any other Command. The 10-byte channel map below is the LENGTH-counted payload: 79 bits, one per hop channel (1=unknown/usable, 0=bad), packed LSB-first.

Parameter Type Unit Range / Constraints Options
opcode uint16 - - -
channelClassification bytes - - -

HCI_ACL_Data (Command ID: 0x01) - typeField=0x02, selecting the variantsByType['2'] override: LENGTH is 2 bytes here (Data Total Length), not 1 -- ACL packets can carry far more data than a Command's single-byte length would allow. handleAndFlags is now correctly position=before-length-field -- it isn't part of the LENGTH-counted region either.

Parameter Type Unit Range / Constraints Options
handleAndFlags uint16 - - -
data bytes - - -

Device-Initiated Messages

HCI_Command_Complete_Event (Message ID: 0x0E) - typeField=0x04, selecting the variantsByType['4'] override: only 1 precedingHeaderByte (eventCode), not 2 -- an earlier version of this instance wrongly folded numHciCommandPackets into the header count. eventCode is now a named, typed position=before-length-field value (0x0E for Command Complete specifically) and doubles as this message's discriminator against any other Event. numHciCommandPackets is genuinely the first byte of THIS event's own LENGTH-counted parameters, alongside every other Command Complete field, which is where it's listed below.

Field Name Type Unit
eventCode uint8 -
numHciCommandPackets uint8 -
commandOpcode uint16 -
returnParameters bytes -

Formal AsyncAPI 2.6.0 Specification

asyncapi: 2.6.0
info:
  title: Bluetooth HCI UART Transport (H4)
  version: '5.4'
  description: 'Host <-> Bluetooth radio controller link. Includes HCI_Set_AFH_Host_Channel_Classification,
    which is literally a frequency-hopping control command: it tells the radio which
    of Bluetooth''s 79 hop channels to avoid. No checksum at all -- H4 relies entirely
    on the underlying UART/transport for integrity.'
servers:
  serial_link:
    url: serial://tty/115200
    protocol: serial
    description: Physical UART Transport (115200 bps, 8N1.0)
    bindings:
      serial:
        baudRate: 115200
        dataBits: 8
        parity: none
        stopBits: 1.0
        framingType: binary
        integrity: none
channels:
  omniuart/cmd/HCI_Set_AFH_Host_Channel_Classification:
    publish:
      summary: 'Send command HCI_Set_AFH_Host_Channel_Classification (ID: 0xC3F)'
      description: 'typeField=0x01 (Command), using framing''s top-level lengthField
        (no variantsByType entry needed for Command itself). opcode is now a named,
        typed position=before-length-field value (OGF=0x03 Host Controller & Baseband,
        OCF=0x3F -> 0x0C3F) rather than an anonymous 2-byte count, and doubles as
        this message''s discriminator against any other Command. The 10-byte channel
        map below is the LENGTH-counted payload: 79 bits, one per hop channel (1=unknown/usable,
        0=bad), packed LSB-first.'
      message:
        name: HCI_Set_AFH_Host_Channel_Classification_Message
        title: HCI_Set_AFH_Host_Channel_Classification Command
        payload:
          $ref: '#/components/schemas/HCI_Set_AFH_Host_Channel_Classification_Request'
  omniuart/cmd/HCI_ACL_Data:
    publish:
      summary: 'Send command HCI_ACL_Data (ID: 0x01)'
      description: 'typeField=0x02, selecting the variantsByType[''2''] override:
        LENGTH is 2 bytes here (Data Total Length), not 1 -- ACL packets can carry
        far more data than a Command''s single-byte length would allow. handleAndFlags
        is now correctly position=before-length-field -- it isn''t part of the LENGTH-counted
        region either.'
      message:
        name: HCI_ACL_Data_Message
        title: HCI_ACL_Data Command
        payload:
          $ref: '#/components/schemas/HCI_ACL_Data_Request'
  omniuart/telemetry/HCI_Command_Complete_Event:
    subscribe:
      summary: 'Unsolicited telemetry message HCI_Command_Complete_Event (ID: 0x0E)'
      description: 'typeField=0x04, selecting the variantsByType[''4''] override:
        only 1 precedingHeaderByte (eventCode), not 2 -- an earlier version of this
        instance wrongly folded numHciCommandPackets into the header count. eventCode
        is now a named, typed position=before-length-field value (0x0E for Command
        Complete specifically) and doubles as this message''s discriminator against
        any other Event. numHciCommandPackets is genuinely the first byte of THIS
        event''s own LENGTH-counted parameters, alongside every other Command Complete
        field, which is where it''s listed below.'
      message:
        name: HCI_Command_Complete_Event_Telemetry_Message
        title: HCI_Command_Complete_Event Telemetry
        payload:
          $ref: '#/components/schemas/HCI_Command_Complete_Event_Telemetry'
components:
  messages: {}
  schemas:
    HCI_Set_AFH_Host_Channel_Classification_Request:
      type: object
      properties:
        command_id:
          type: integer
          const: 3135
          description: Opcode ID for HCI_Set_AFH_Host_Channel_Classification
        opcode:
          type: integer
          default: 3135
        channelClassification:
          type: string
          contentEncoding: base64
      description: 'typeField=0x01 (Command), using framing''s top-level lengthField
        (no variantsByType entry needed for Command itself). opcode is now a named,
        typed position=before-length-field value (OGF=0x03 Host Controller & Baseband,
        OCF=0x3F -> 0x0C3F) rather than an anonymous 2-byte count, and doubles as
        this message''s discriminator against any other Command. The 10-byte channel
        map below is the LENGTH-counted payload: 79 bits, one per hop channel (1=unknown/usable,
        0=bad), packed LSB-first.'
    HCI_ACL_Data_Request:
      type: object
      properties:
        command_id:
          type: integer
          const: 1
          description: Opcode ID for HCI_ACL_Data
        handleAndFlags:
          type: integer
        data:
          type: string
          contentEncoding: base64
      description: 'typeField=0x02, selecting the variantsByType[''2''] override:
        LENGTH is 2 bytes here (Data Total Length), not 1 -- ACL packets can carry
        far more data than a Command''s single-byte length would allow. handleAndFlags
        is now correctly position=before-length-field -- it isn''t part of the LENGTH-counted
        region either.'
    HCI_Command_Complete_Event_Telemetry:
      type: object
      properties:
        eventCode:
          type: integer
          default: 14
        numHciCommandPackets:
          type: integer
        commandOpcode:
          type: integer
        returnParameters:
          type: string
          contentEncoding: base64
      description: 'typeField=0x04, selecting the variantsByType[''4''] override:
        only 1 precedingHeaderByte (eventCode), not 2 -- an earlier version of this
        instance wrongly folded numHciCommandPackets into the header count. eventCode
        is now a named, typed position=before-length-field value (0x0E for Command
        Complete specifically) and doubles as this message''s discriminator against
        any other Event. numHciCommandPackets is genuinely the first byte of THIS
        event''s own LENGTH-counted parameters, alongside every other Command Complete
        field, which is where it''s listed below.'