From c901e1566656172bb74fa488066b5009f49b8846 Mon Sep 17 00:00:00 2001 From: Gilles Boccon-Gibod Date: Fri, 23 Jan 2026 21:35:28 -0800 Subject: [PATCH] fix a few HCI types and make the bridge more robust --- apps/hci_bridge.py | 4 +++- bumble/bridge.py | 7 ++++++- bumble/device.py | 6 +++--- bumble/hci.py | 34 +++++++++++++++++++--------------- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/apps/hci_bridge.py b/apps/hci_bridge.py index e50d4051..4114bf44 100644 --- a/apps/hci_bridge.py +++ b/apps/hci_bridge.py @@ -81,7 +81,9 @@ async def async_main(): response = hci.HCI_Command_Complete_Event( num_hci_command_packets=1, command_opcode=hci_packet.op_code, - return_parameters=bytes([hci.HCI_SUCCESS]), + return_parameters=hci.HCI_StatusReturnParameters( + status=hci.HCI_ErrorCode.SUCCESS + ), ) # Return a packet with 'respond to sender' set to True return (bytes(response), True) diff --git a/bumble/bridge.py b/bumble/bridge.py index 27ff3abd..168f7734 100644 --- a/bumble/bridge.py +++ b/bumble/bridge.py @@ -37,7 +37,12 @@ class HCI_Bridge: def on_packet(self, packet): # Convert the packet bytes to an object - hci_packet = HCI_Packet.from_bytes(packet) + try: + hci_packet = HCI_Packet.from_bytes(packet) + except Exception: + logger.warning('forwarding unparsed packet as-is') + self.hci_sink.on_packet(packet) + return # Filter the packet if self.packet_filter is not None: diff --git a/bumble/device.py b/bumble/device.py index ffaaa7b1..7b1b826b 100644 --- a/bumble/device.py +++ b/bumble/device.py @@ -1177,7 +1177,7 @@ class ChannelSoundingCapabilities: rtt_capability: int rtt_aa_only_n: int rtt_sounding_n: int - rtt_random_payload_n: int + rtt_random_sequence_n: int nadm_sounding_capability: int nadm_random_capability: int cs_sync_phys_supported: int @@ -2926,7 +2926,7 @@ class Device(utils.CompositeEventEmitter): rtt_capability=result.rtt_capability, rtt_aa_only_n=result.rtt_aa_only_n, rtt_sounding_n=result.rtt_sounding_n, - rtt_random_payload_n=result.rtt_random_payload_n, + rtt_random_sequence_n=result.rtt_random_sequence_n, nadm_sounding_capability=result.nadm_sounding_capability, nadm_random_capability=result.nadm_random_capability, cs_sync_phys_supported=result.cs_sync_phys_supported, @@ -6673,7 +6673,7 @@ class Device(utils.CompositeEventEmitter): rtt_capability=event.rtt_capability, rtt_aa_only_n=event.rtt_aa_only_n, rtt_sounding_n=event.rtt_sounding_n, - rtt_random_payload_n=event.rtt_random_payload_n, + rtt_random_sequence_n=event.rtt_random_sequence_n, nadm_sounding_capability=event.nadm_sounding_capability, nadm_random_capability=event.nadm_random_capability, cs_sync_phys_supported=event.cs_sync_phys_supported, diff --git a/bumble/hci.py b/bumble/hci.py index 474c1a80..7e38814e 100644 --- a/bumble/hci.py +++ b/bumble/hci.py @@ -2407,24 +2407,28 @@ class HCI_Packet: @classmethod def from_bytes(cls, packet: bytes) -> HCI_Packet: - packet_type = packet[0] + try: + packet_type = packet[0] - if packet_type == HCI_COMMAND_PACKET: - return HCI_Command.from_bytes(packet) + if packet_type == HCI_COMMAND_PACKET: + return HCI_Command.from_bytes(packet) - if packet_type == HCI_ACL_DATA_PACKET: - return HCI_AclDataPacket.from_bytes(packet) + if packet_type == HCI_ACL_DATA_PACKET: + return HCI_AclDataPacket.from_bytes(packet) - if packet_type == HCI_SYNCHRONOUS_DATA_PACKET: - return HCI_SynchronousDataPacket.from_bytes(packet) + if packet_type == HCI_SYNCHRONOUS_DATA_PACKET: + return HCI_SynchronousDataPacket.from_bytes(packet) - if packet_type == HCI_EVENT_PACKET: - return HCI_Event.from_bytes(packet) + if packet_type == HCI_EVENT_PACKET: + return HCI_Event.from_bytes(packet) - if packet_type == HCI_ISO_DATA_PACKET: - return HCI_IsoDataPacket.from_bytes(packet) + if packet_type == HCI_ISO_DATA_PACKET: + return HCI_IsoDataPacket.from_bytes(packet) - return HCI_CustomPacket(packet) + return HCI_CustomPacket(packet) + except Exception as e: + logger.error(f'error parsing HCI packet [{packet.hex()}]: {e}') + raise def __init__(self, name: str) -> None: self.name = name @@ -5854,7 +5858,7 @@ class HCI_LE_CS_Read_Local_Supported_Capabilities_ReturnParameters( rtt_capability: int = field(metadata=metadata(1)) rtt_aa_only_n: int = field(metadata=metadata(1)) rtt_sounding_n: int = field(metadata=metadata(1)) - rtt_random_payload_n: int = field(metadata=metadata(1)) + rtt_random_sequence_n: int = field(metadata=metadata(1)) nadm_sounding_capability: int = field(metadata=metadata(2)) nadm_random_capability: int = field(metadata=metadata(2)) cs_sync_phys_supported: int = field(metadata=metadata(CS_SYNC_PHY_SUPPORTED_SPEC)) @@ -5910,7 +5914,7 @@ class HCI_LE_CS_Write_Cached_Remote_Supported_Capabilities_Command( rtt_capability: int = field(metadata=metadata(1)) rtt_aa_only_n: int = field(metadata=metadata(1)) rtt_sounding_n: int = field(metadata=metadata(1)) - rtt_random_payload_n: int = field(metadata=metadata(1)) + rtt_random_sequence_n: int = field(metadata=metadata(1)) nadm_sounding_capability: int = field(metadata=metadata(2)) nadm_random_capability: int = field(metadata=metadata(2)) cs_sync_phys_supported: int = field(metadata=metadata(CS_SYNC_PHY_SUPPORTED_SPEC)) @@ -7118,7 +7122,7 @@ class HCI_LE_CS_Read_Remote_Supported_Capabilities_Complete_Event(HCI_LE_Meta_Ev rtt_capability: int = field(metadata=metadata(1)) rtt_aa_only_n: int = field(metadata=metadata(1)) rtt_sounding_n: int = field(metadata=metadata(1)) - rtt_random_payload_n: int = field(metadata=metadata(1)) + rtt_random_sequence_n: int = field(metadata=metadata(1)) nadm_sounding_capability: int = field(metadata=metadata(2)) nadm_random_capability: int = field(metadata=metadata(2)) cs_sync_phys_supported: int = field(metadata=metadata(CS_SYNC_PHY_SUPPORTED_SPEC))