diff --git a/bumble/device.py b/bumble/device.py index 3725fbb9..4ab5c286 100644 --- a/bumble/device.py +++ b/bumble/device.py @@ -257,7 +257,7 @@ def from_advertising_report(cls, report): secondary_phy = report.secondary_phy, tx_power = report.tx_power, sid = report.advertising_sid, - data_bytes = report.data + data_bytes = report.data, ) # fmt: on @@ -912,11 +912,11 @@ async def transfer(self, connection: Connection, service_data: int = 0) -> None: def on_establishment( self, - status, - sync_handle, - advertiser_phy, - periodic_advertising_interval, - advertiser_clock_accuracy, + status: int, + sync_handle: int, + advertiser_phy: int, + periodic_advertising_interval: int, + advertiser_clock_accuracy: int, ) -> None: self.status = status @@ -3183,6 +3183,41 @@ def on_periodic_advertising_sync_establishment( "periodic advertising sync establishment for unknown address/sid" ) + @host_event_handler + def on_periodic_advertising_sync_transfer( + self, + status: int, + connection_handle: int, + sync_handle: int, + advertising_sid: int, + advertiser_address: hci.Address, + advertiser_phy: int, + periodic_advertising_interval: int, + advertiser_clock_accuracy: int, + ) -> None: + if not (connection := self.lookup_connection(connection_handle)): + logger.error( + "Receive PAST from unknown connection 0x%04X", connection_handle + ) + + pa_sync = PeriodicAdvertisingSync( + device=self, + advertiser_address=advertiser_address, + sid=advertising_sid, + skip=0, + sync_timeout=0.0, + filter_duplicates=False, + ) + self.periodic_advertising_syncs.append(pa_sync) + pa_sync.on_establishment( + status=status, + sync_handle=sync_handle, + advertiser_phy=advertiser_phy, + periodic_advertising_interval=periodic_advertising_interval, + advertiser_clock_accuracy=advertiser_clock_accuracy, + ) + self.emit('periodic_advertising_sync_transfer', pa_sync, connection) + @host_event_handler @with_periodic_advertising_sync_from_handle def on_periodic_advertising_sync_loss( diff --git a/bumble/hci.py b/bumble/hci.py index 44b32b1a..a18d04f8 100644 --- a/bumble/hci.py +++ b/bumble/hci.py @@ -4878,6 +4878,62 @@ class HCI_LE_Periodic_Advertising_Sync_Transfer_Command(HCI_Command): ''' +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + ('connection_handle', 2), + ('mode', 1), + ('skip', 2), + ('sync_timeout', 2), + ( + 'cte_type', + { + 'size': 1, + 'mapper': lambda x: HCI_LE_Periodic_Advertising_Report_Event.CteType( + x + ).name, + }, + ), + ], + return_parameters_fields=[ + ('status', STATUS_SPEC), + ('connection_handle', 2), + ], +) +class HCI_LE_Set_Periodic_Advertising_Sync_Transfer_Parameters_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.91 LE Set Periodic Advertising Sync Transfer Parameters command + ''' + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + ('mode', 1), + ('skip', 2), + ('sync_timeout', 2), + ( + 'cte_type', + { + 'size': 1, + 'mapper': lambda x: HCI_LE_Periodic_Advertising_Report_Event.CteType( + x + ).name, + }, + ), + ], + return_parameters_fields=[ + ('status', STATUS_SPEC), + ], +) +class HCI_LE_Set_Default_Periodic_Advertising_Sync_Transfer_Parameters_Command( + HCI_Command +): + ''' + See Bluetooth spec @ 7.8.92 LE Set Default Periodic Advertising Sync Transfer Parameters command + ''' + + # ----------------------------------------------------------------------------- @HCI_Command.command( fields=[ @@ -6231,6 +6287,31 @@ class HCI_LE_Periodic_Advertising_Sync_Transfer_Received_Event(HCI_LE_Meta_Event ''' +# ----------------------------------------------------------------------------- +@HCI_LE_Meta_Event.event( + [ + ('status', STATUS_SPEC), + ('connection_handle', 2), + ('service_data', 2), + ('sync_handle', 2), + ('advertising_sid', 1), + ('advertiser_address_type', Address.ADDRESS_TYPE_SPEC), + ('advertiser_address', Address.parse_address_preceded_by_type), + ('advertiser_phy', 1), + ('periodic_advertising_interval', 2), + ('advertiser_clock_accuracy', 1), + ('num_subevents', 1), + ('subevent_interval', 1), + ('response_slot_delay', 1), + ('response_slot_spacing', 1), + ] +) +class HCI_LE_Periodic_Advertising_Sync_Transfer_Received_V2_Event(HCI_LE_Meta_Event): + ''' + See Bluetooth spec @ 7.7.65.24 LE Periodic Advertising Sync Transfer Received Event + ''' + + # ----------------------------------------------------------------------------- @HCI_LE_Meta_Event.event( [ diff --git a/bumble/host.py b/bumble/host.py index 1c356cc9..57ad36ca 100644 --- a/bumble/host.py +++ b/bumble/host.py @@ -1204,6 +1204,32 @@ def on_hci_le_terminate_big_complete_event(self, event): self.remove_big(event.big_handle) self.emit('big_termination', event.reason, event.big_handle) + def on_hci_le_periodic_advertising_sync_transfer_received_event(self, event): + self.emit( + 'periodic_advertising_sync_transfer', + event.status, + event.connection_handle, + event.sync_handle, + event.advertising_sid, + event.advertiser_address, + event.advertiser_phy, + event.periodic_advertising_interval, + event.advertiser_clock_accuracy, + ) + + def on_hci_le_periodic_advertising_sync_transfer_received_v2_event(self, event): + self.emit( + 'periodic_advertising_sync_transfer', + event.status, + event.connection_handle, + event.sync_handle, + event.advertising_sid, + event.advertiser_address, + event.advertiser_phy, + event.periodic_advertising_interval, + event.advertiser_clock_accuracy, + ) + def on_hci_le_cis_established_event(self, event): # The remaining parameters are unused for now. if event.status == hci.HCI_SUCCESS: