diff --git a/bumble/controller.py b/bumble/controller.py index 9113a861..356b7e42 100644 --- a/bumble/controller.py +++ b/bumble/controller.py @@ -618,8 +618,8 @@ class Controller: cis_sync_delay=0, transport_latency_c_to_p=0, transport_latency_p_to_c=0, - phy_c_to_p=0, - phy_p_to_c=0, + phy_c_to_p=1, + phy_p_to_c=1, nse=0, bn_c_to_p=0, bn_p_to_c=0, diff --git a/bumble/device.py b/bumble/device.py index 3eeed842..ad03dacb 100644 --- a/bumble/device.py +++ b/bumble/device.py @@ -1710,6 +1710,8 @@ class Connection(utils.CompositeEventEmitter): pairing_peer_authentication_requirements: Optional[int] cs_configs: dict[int, ChannelSoundingConfig] # Config ID to Configuration cs_procedures: dict[int, ChannelSoundingProcedure] # Config ID to Procedures + classic_mode: int = hci.HCI_Mode_Change_Event.Mode.ACTIVE + classic_interval: int = 0 EVENT_CONNECTION_ATT_MTU_UPDATE = "connection_att_mtu_update" EVENT_DISCONNECTION = "disconnection" @@ -1736,6 +1738,8 @@ class Connection(utils.CompositeEventEmitter): EVENT_CHANNEL_SOUNDING_CONFIG_REMOVED = "channel_sounding_config_removed" EVENT_CHANNEL_SOUNDING_PROCEDURE_FAILURE = "channel_sounding_procedure_failure" EVENT_CHANNEL_SOUNDING_PROCEDURE = "channel_sounding_procedure" + EVENT_MODE_CHANGE = "mode_change" + EVENT_MODE_CHANGE_FAILURE = "mode_change_failure" EVENT_ROLE_CHANGE = "role_change" EVENT_ROLE_CHANGE_FAILURE = "role_change_failure" EVENT_CLASSIC_PAIRING = "classic_pairing" @@ -5888,7 +5892,7 @@ class Device(utils.CompositeEventEmitter): connection.classic_interval = interval connection.emit(connection.EVENT_MODE_CHANGE) else: - connection.emit(connection.EVENT_MODE_CHANGE_FAILURE) + connection.emit(connection.EVENT_MODE_CHANGE_FAILURE, status) # [Classic only] @host_event_handler diff --git a/bumble/hci.py b/bumble/hci.py index 55c6448b..a340bd5b 100644 --- a/bumble/hci.py +++ b/bumble/hci.py @@ -4990,7 +4990,9 @@ class HCI_LE_Set_Privacy_Mode_Command(HCI_Command): NETWORK_PRIVACY_MODE = 0x00 DEVICE_PRIVACY_MODE = 0x01 - peer_identity_address_type: int = field(metadata=Address.ADDRESS_TYPE_SPEC) + peer_identity_address_type: int = field( + metadata=metadata(Address.ADDRESS_TYPE_SPEC) + ) peer_identity_address: Address = field( metadata=metadata(Address.parse_address_preceded_by_type) ) diff --git a/bumble/host.py b/bumble/host.py index 817485a8..bfbe283c 100644 --- a/bumble/host.py +++ b/bumble/host.py @@ -1392,6 +1392,15 @@ class Host(utils.EventEmitter): def on_hci_synchronous_connection_changed_event(self, event): pass + def on_hci_mode_change_event(self, event: hci.HCI_Mode_Change_Event): + self.emit( + 'mode_change', + event.connection_handle, + event.status, + event.current_mode, + event.interval, + ) + def on_hci_role_change_event(self, event): if event.status == hci.HCI_SUCCESS: logger.debug( diff --git a/pyproject.toml b/pyproject.toml index 9474cd18..7c788754 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version"] description = "Bluetooth Stack for Apps, Emulation, Test and Experimentation" readme = "README.md" authors = [{ name = "Google", email = "bumble-dev@google.com" }] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ "aiohttp ~= 3.8; platform_system!='Emscripten'", "appdirs >= 1.4; platform_system!='Emscripten'", diff --git a/tests/device_test.py b/tests/device_test.py index c3f70e30..8d0b5ade 100644 --- a/tests/device_test.py +++ b/tests/device_test.py @@ -581,8 +581,12 @@ async def test_enter_and_exit_sniff_mode(): devices = TwoDevices() await devices.setup_connection() - m = mock.Mock() - devices.connections[0].on(Connection.EVENT_MODE_CHANGE, m) + q = asyncio.Queue() + + def on_mode_change(): + q.put_nowait(lambda: None) + + devices.connections[0].on(Connection.EVENT_MODE_CHANGE, on_mode_change) await devices[0].send_command( hci.HCI_Sniff_Mode_Command( @@ -594,7 +598,7 @@ async def test_enter_and_exit_sniff_mode(): ), ) - m.assert_called_once() + await asyncio.wait_for(q.get(), _TIMEOUT) assert devices.connections[0].classic_mode == hci.HCI_Mode_Change_Event.Mode.SNIFF assert devices.connections[0].classic_interval == 2 @@ -602,6 +606,7 @@ async def test_enter_and_exit_sniff_mode(): hci.HCI_Exit_Sniff_Mode_Command(connection_handle=devices.connections[0].handle) ) + await asyncio.wait_for(q.get(), _TIMEOUT) assert devices.connections[0].classic_mode == hci.HCI_Mode_Change_Event.Mode.ACTIVE assert devices.connections[0].classic_interval == 2