bumble 0.0.209__py3-none-any.whl → 0.0.210__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. bumble/_version.py +2 -2
  2. bumble/a2dp.py +7 -7
  3. bumble/apps/auracast.py +37 -29
  4. bumble/apps/bench.py +9 -7
  5. bumble/apps/console.py +1 -1
  6. bumble/apps/lea_unicast/app.py +6 -2
  7. bumble/apps/pair.py +4 -3
  8. bumble/apps/player/player.py +3 -3
  9. bumble/apps/rfcomm_bridge.py +1 -1
  10. bumble/apps/speaker/speaker.py +4 -2
  11. bumble/att.py +2 -3
  12. bumble/avc.py +5 -5
  13. bumble/avdtp.py +9 -10
  14. bumble/avrcp.py +18 -19
  15. bumble/bridge.py +2 -2
  16. bumble/controller.py +6 -7
  17. bumble/core.py +56 -56
  18. bumble/device.py +169 -137
  19. bumble/drivers/__init__.py +2 -2
  20. bumble/gap.py +1 -1
  21. bumble/gatt_adapters.py +3 -3
  22. bumble/gatt_client.py +27 -21
  23. bumble/gatt_server.py +9 -10
  24. bumble/hci.py +34 -20
  25. bumble/hfp.py +3 -3
  26. bumble/hid.py +4 -3
  27. bumble/host.py +22 -16
  28. bumble/keys.py +3 -3
  29. bumble/l2cap.py +19 -17
  30. bumble/link.py +3 -4
  31. bumble/pairing.py +3 -3
  32. bumble/pandora/__init__.py +5 -5
  33. bumble/pandora/host.py +18 -12
  34. bumble/pandora/l2cap.py +2 -2
  35. bumble/pandora/security.py +15 -16
  36. bumble/profiles/aics.py +6 -6
  37. bumble/profiles/ancs.py +9 -10
  38. bumble/profiles/ascs.py +17 -10
  39. bumble/profiles/asha.py +5 -5
  40. bumble/profiles/bass.py +1 -1
  41. bumble/profiles/csip.py +10 -10
  42. bumble/profiles/gatt_service.py +12 -12
  43. bumble/profiles/hap.py +16 -16
  44. bumble/profiles/mcp.py +26 -24
  45. bumble/profiles/pacs.py +6 -6
  46. bumble/profiles/pbp.py +1 -1
  47. bumble/profiles/vcs.py +6 -4
  48. bumble/profiles/vocs.py +3 -3
  49. bumble/rfcomm.py +8 -8
  50. bumble/sdp.py +1 -1
  51. bumble/smp.py +36 -30
  52. bumble/transport/__init__.py +24 -19
  53. bumble/transport/android_emulator.py +8 -4
  54. bumble/transport/android_netsim.py +8 -5
  55. bumble/transport/common.py +5 -1
  56. bumble/transport/file.py +1 -1
  57. bumble/transport/hci_socket.py +1 -1
  58. bumble/transport/pty.py +1 -1
  59. bumble/transport/pyusb.py +3 -3
  60. bumble/transport/serial.py +1 -1
  61. bumble/transport/tcp_client.py +1 -1
  62. bumble/transport/tcp_server.py +1 -1
  63. bumble/transport/udp.py +1 -1
  64. bumble/transport/unix.py +1 -1
  65. bumble/transport/vhci.py +2 -2
  66. bumble/transport/ws_client.py +6 -1
  67. bumble/transport/ws_server.py +1 -1
  68. bumble/utils.py +89 -76
  69. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/METADATA +3 -2
  70. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/RECORD +74 -74
  71. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/WHEEL +1 -1
  72. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/entry_points.txt +0 -0
  73. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info/licenses}/LICENSE +0 -0
  74. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/top_level.txt +0 -0
@@ -25,8 +25,8 @@ import pathlib
25
25
  import platform
26
26
  from typing import Dict, Iterable, Optional, Type, TYPE_CHECKING
27
27
 
28
- from . import rtk, intel
29
- from .common import Driver
28
+ from bumble.drivers import rtk, intel
29
+ from bumble.drivers.common import Driver
30
30
 
31
31
  if TYPE_CHECKING:
32
32
  from bumble.host import Host
bumble/gap.py CHANGED
@@ -18,7 +18,7 @@
18
18
  import logging
19
19
  import struct
20
20
 
21
- from .gatt import (
21
+ from bumble.gatt import (
22
22
  Service,
23
23
  Characteristic,
24
24
  GATT_GENERIC_ACCESS_SERVICE,
bumble/gatt_adapters.py CHANGED
@@ -35,15 +35,15 @@ from typing import (
35
35
  from bumble.core import InvalidOperationError
36
36
  from bumble.gatt import Characteristic
37
37
  from bumble.gatt_client import CharacteristicProxy
38
- from bumble.utils import ByteSerializable, IntConvertible
38
+ from bumble import utils
39
39
 
40
40
 
41
41
  # -----------------------------------------------------------------------------
42
42
  # Typing
43
43
  # -----------------------------------------------------------------------------
44
44
  _T = TypeVar('_T')
45
- _T2 = TypeVar('_T2', bound=ByteSerializable)
46
- _T3 = TypeVar('_T3', bound=IntConvertible)
45
+ _T2 = TypeVar('_T2', bound=utils.ByteSerializable)
46
+ _T3 = TypeVar('_T3', bound=utils.IntConvertible)
47
47
 
48
48
 
49
49
  # -----------------------------------------------------------------------------
bumble/gatt_client.py CHANGED
@@ -44,11 +44,10 @@ from typing import (
44
44
  TYPE_CHECKING,
45
45
  )
46
46
 
47
- from pyee import EventEmitter
48
47
 
49
- from .colors import color
50
- from .hci import HCI_Constant
51
- from .att import (
48
+ from bumble.colors import color
49
+ from bumble.hci import HCI_Constant
50
+ from bumble.att import (
52
51
  ATT_ATTRIBUTE_NOT_FOUND_ERROR,
53
52
  ATT_ATTRIBUTE_NOT_LONG_ERROR,
54
53
  ATT_CID,
@@ -69,9 +68,10 @@ from .att import (
69
68
  ATT_Write_Request,
70
69
  ATT_Error,
71
70
  )
72
- from . import core
73
- from .core import UUID, InvalidStateError
74
- from .gatt import (
71
+ from bumble import utils
72
+ from bumble import core
73
+ from bumble.core import UUID, InvalidStateError
74
+ from bumble.gatt import (
75
75
  GATT_CHARACTERISTIC_ATTRIBUTE_TYPE,
76
76
  GATT_CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR,
77
77
  GATT_PRIMARY_SERVICE_ATTRIBUTE_TYPE,
@@ -117,11 +117,11 @@ def show_services(services: Iterable[ServiceProxy]) -> None:
117
117
  # -----------------------------------------------------------------------------
118
118
  # Proxies
119
119
  # -----------------------------------------------------------------------------
120
- class AttributeProxy(EventEmitter, Generic[_T]):
120
+ class AttributeProxy(utils.EventEmitter, Generic[_T]):
121
121
  def __init__(
122
122
  self, client: Client, handle: int, end_group_handle: int, attribute_type: UUID
123
123
  ) -> None:
124
- EventEmitter.__init__(self)
124
+ utils.EventEmitter.__init__(self)
125
125
  self.client = client
126
126
  self.handle = handle
127
127
  self.end_group_handle = end_group_handle
@@ -149,7 +149,7 @@ class AttributeProxy(EventEmitter, Generic[_T]):
149
149
 
150
150
  class ServiceProxy(AttributeProxy):
151
151
  uuid: UUID
152
- characteristics: List[CharacteristicProxy]
152
+ characteristics: List[CharacteristicProxy[bytes]]
153
153
  included_services: List[ServiceProxy]
154
154
 
155
155
  @staticmethod
@@ -170,14 +170,20 @@ class ServiceProxy(AttributeProxy):
170
170
  self.uuid = uuid
171
171
  self.characteristics = []
172
172
 
173
- async def discover_characteristics(self, uuids=()) -> list[CharacteristicProxy]:
173
+ async def discover_characteristics(
174
+ self, uuids=()
175
+ ) -> list[CharacteristicProxy[bytes]]:
174
176
  return await self.client.discover_characteristics(uuids, self)
175
177
 
176
- def get_characteristics_by_uuid(self, uuid: UUID) -> list[CharacteristicProxy]:
178
+ def get_characteristics_by_uuid(
179
+ self, uuid: UUID
180
+ ) -> list[CharacteristicProxy[bytes]]:
177
181
  """Get all the characteristics with a specified UUID."""
178
182
  return self.client.get_characteristics_by_uuid(uuid, self)
179
183
 
180
- def get_required_characteristic_by_uuid(self, uuid: UUID) -> CharacteristicProxy:
184
+ def get_required_characteristic_by_uuid(
185
+ self, uuid: UUID
186
+ ) -> CharacteristicProxy[bytes]:
181
187
  """
182
188
  Get the first characteristic with a specified UUID.
183
189
 
@@ -256,7 +262,7 @@ class CharacteristicProxy(AttributeProxy[_T]):
256
262
  )
257
263
 
258
264
 
259
- class DescriptorProxy(AttributeProxy):
265
+ class DescriptorProxy(AttributeProxy[bytes]):
260
266
  def __init__(self, client: Client, handle: int, descriptor_type: UUID) -> None:
261
267
  super().__init__(client, handle, 0, descriptor_type)
262
268
 
@@ -376,7 +382,7 @@ class Client:
376
382
 
377
383
  def get_characteristics_by_uuid(
378
384
  self, uuid: UUID, service: Optional[ServiceProxy] = None
379
- ) -> List[CharacteristicProxy]:
385
+ ) -> List[CharacteristicProxy[bytes]]:
380
386
  services = [service] if service else self.services
381
387
  return [
382
388
  c
@@ -628,7 +634,7 @@ class Client:
628
634
 
629
635
  async def discover_characteristics(
630
636
  self, uuids, service: Optional[ServiceProxy]
631
- ) -> List[CharacteristicProxy]:
637
+ ) -> List[CharacteristicProxy[bytes]]:
632
638
  '''
633
639
  See Vol 3, Part G - 4.6.1 Discover All Characteristics of a Service and 4.6.2
634
640
  Discover Characteristics by UUID
@@ -641,12 +647,12 @@ class Client:
641
647
  services = [service] if service else self.services
642
648
 
643
649
  # Perform characteristic discovery for each service
644
- discovered_characteristics: List[CharacteristicProxy] = []
650
+ discovered_characteristics: List[CharacteristicProxy[bytes]] = []
645
651
  for service in services:
646
652
  starting_handle = service.handle
647
653
  ending_handle = service.end_group_handle
648
654
 
649
- characteristics: List[CharacteristicProxy] = []
655
+ characteristics: List[CharacteristicProxy[bytes]] = []
650
656
  while starting_handle <= ending_handle:
651
657
  response = await self.send_request(
652
658
  ATT_Read_By_Type_Request(
@@ -686,7 +692,7 @@ class Client:
686
692
 
687
693
  properties, handle = struct.unpack_from('<BH', attribute_value)
688
694
  characteristic_uuid = UUID.from_bytes(attribute_value[3:])
689
- characteristic: CharacteristicProxy = CharacteristicProxy(
695
+ characteristic = CharacteristicProxy[bytes](
690
696
  self, handle, 0, characteristic_uuid, properties
691
697
  )
692
698
 
@@ -779,7 +785,7 @@ class Client:
779
785
 
780
786
  return descriptors
781
787
 
782
- async def discover_attributes(self) -> List[AttributeProxy]:
788
+ async def discover_attributes(self) -> List[AttributeProxy[bytes]]:
783
789
  '''
784
790
  Discover all attributes, regardless of type
785
791
  '''
@@ -812,7 +818,7 @@ class Client:
812
818
  logger.warning(f'bogus handle value: {attribute_handle}')
813
819
  return []
814
820
 
815
- attribute: AttributeProxy = AttributeProxy(
821
+ attribute = AttributeProxy[bytes](
816
822
  self, attribute_handle, 0, UUID.from_bytes(attribute_uuid)
817
823
  )
818
824
  attributes.append(attribute)
bumble/gatt_server.py CHANGED
@@ -38,7 +38,6 @@ from typing import (
38
38
  Type,
39
39
  TYPE_CHECKING,
40
40
  )
41
- from pyee import EventEmitter
42
41
 
43
42
  from bumble.colors import color
44
43
  from bumble.core import UUID
@@ -83,7 +82,7 @@ from bumble.gatt import (
83
82
  Descriptor,
84
83
  Service,
85
84
  )
86
- from bumble.utils import AsyncRunner
85
+ from bumble import utils
87
86
 
88
87
  if TYPE_CHECKING:
89
88
  from bumble.device import Device, Connection
@@ -103,7 +102,7 @@ GATT_SERVER_DEFAULT_MAX_MTU = 517
103
102
  # -----------------------------------------------------------------------------
104
103
  # GATT Server
105
104
  # -----------------------------------------------------------------------------
106
- class Server(EventEmitter):
105
+ class Server(utils.EventEmitter):
107
106
  attributes: List[Attribute]
108
107
  services: List[Service]
109
108
  attributes_by_handle: Dict[int, Attribute]
@@ -662,7 +661,7 @@ class Server(EventEmitter):
662
661
 
663
662
  self.send_response(connection, response)
664
663
 
665
- @AsyncRunner.run_in_task()
664
+ @utils.AsyncRunner.run_in_task()
666
665
  async def on_att_find_by_type_value_request(self, connection, request):
667
666
  '''
668
667
  See Bluetooth spec Vol 3, Part F - 3.4.3.3 Find By Type Value Request
@@ -715,7 +714,7 @@ class Server(EventEmitter):
715
714
 
716
715
  self.send_response(connection, response)
717
716
 
718
- @AsyncRunner.run_in_task()
717
+ @utils.AsyncRunner.run_in_task()
719
718
  async def on_att_read_by_type_request(self, connection, request):
720
719
  '''
721
720
  See Bluetooth spec Vol 3, Part F - 3.4.4.1 Read By Type Request
@@ -781,7 +780,7 @@ class Server(EventEmitter):
781
780
 
782
781
  self.send_response(connection, response)
783
782
 
784
- @AsyncRunner.run_in_task()
783
+ @utils.AsyncRunner.run_in_task()
785
784
  async def on_att_read_request(self, connection, request):
786
785
  '''
787
786
  See Bluetooth spec Vol 3, Part F - 3.4.4.3 Read Request
@@ -807,7 +806,7 @@ class Server(EventEmitter):
807
806
  )
808
807
  self.send_response(connection, response)
809
808
 
810
- @AsyncRunner.run_in_task()
809
+ @utils.AsyncRunner.run_in_task()
811
810
  async def on_att_read_blob_request(self, connection, request):
812
811
  '''
813
812
  See Bluetooth spec Vol 3, Part F - 3.4.4.5 Read Blob Request
@@ -852,7 +851,7 @@ class Server(EventEmitter):
852
851
  )
853
852
  self.send_response(connection, response)
854
853
 
855
- @AsyncRunner.run_in_task()
854
+ @utils.AsyncRunner.run_in_task()
856
855
  async def on_att_read_by_group_type_request(self, connection, request):
857
856
  '''
858
857
  See Bluetooth spec Vol 3, Part F - 3.4.4.9 Read by Group Type Request
@@ -920,7 +919,7 @@ class Server(EventEmitter):
920
919
 
921
920
  self.send_response(connection, response)
922
921
 
923
- @AsyncRunner.run_in_task()
922
+ @utils.AsyncRunner.run_in_task()
924
923
  async def on_att_write_request(self, connection, request):
925
924
  '''
926
925
  See Bluetooth spec Vol 3, Part F - 3.4.5.1 Write Request
@@ -967,7 +966,7 @@ class Server(EventEmitter):
967
966
  response = ATT_Write_Response()
968
967
  self.send_response(connection, response)
969
968
 
970
- @AsyncRunner.run_in_task()
969
+ @utils.AsyncRunner.run_in_task()
971
970
  async def on_att_write_command(self, connection, request):
972
971
  '''
973
972
  See Bluetooth spec Vol 3, Part F - 3.4.5.3 Write Command
bumble/hci.py CHANGED
@@ -29,7 +29,7 @@ from typing_extensions import Self
29
29
  from bumble import crypto
30
30
  from bumble.colors import color
31
31
  from bumble.core import (
32
- BT_BR_EDR_TRANSPORT,
32
+ PhysicalTransport,
33
33
  AdvertisingData,
34
34
  DeviceClass,
35
35
  InvalidArgumentError,
@@ -40,7 +40,7 @@ from bumble.core import (
40
40
  name_or_number,
41
41
  padded_bytes,
42
42
  )
43
- from bumble.utils import OpenIntEnum
43
+ from bumble import utils
44
44
 
45
45
 
46
46
  # -----------------------------------------------------------------------------
@@ -739,7 +739,7 @@ class PhyBit(enum.IntFlag):
739
739
  LE_CODED = 1 << HCI_LE_CODED_PHY_BIT
740
740
 
741
741
 
742
- class CsRole(OpenIntEnum):
742
+ class CsRole(utils.OpenIntEnum):
743
743
  INITIATOR = 0x00
744
744
  REFLECTOR = 0x01
745
745
 
@@ -749,7 +749,7 @@ class CsRoleMask(enum.IntFlag):
749
749
  REFLECTOR = 0x02
750
750
 
751
751
 
752
- class CsSyncPhy(OpenIntEnum):
752
+ class CsSyncPhy(utils.OpenIntEnum):
753
753
  LE_1M = 1
754
754
  LE_2M = 2
755
755
  LE_2M_2BT = 3
@@ -760,7 +760,7 @@ class CsSyncPhySupported(enum.IntFlag):
760
760
  LE_2M_2BT = 0x02
761
761
 
762
762
 
763
- class RttType(OpenIntEnum):
763
+ class RttType(utils.OpenIntEnum):
764
764
  AA_ONLY = 0x00
765
765
  SOUNDING_SEQUENCE_32_BIT = 0x01
766
766
  SOUNDING_SEQUENCE_96_BIT = 0x02
@@ -770,7 +770,7 @@ class RttType(OpenIntEnum):
770
770
  RANDOM_SEQUENCE_128_BIT = 0x06
771
771
 
772
772
 
773
- class CsSnr(OpenIntEnum):
773
+ class CsSnr(utils.OpenIntEnum):
774
774
  SNR_18_DB = 0x00
775
775
  SNR_21_DB = 0x01
776
776
  SNR_24_DB = 0x02
@@ -779,20 +779,20 @@ class CsSnr(OpenIntEnum):
779
779
  NOT_APPLIED = 0xFF
780
780
 
781
781
 
782
- class CsDoneStatus(OpenIntEnum):
782
+ class CsDoneStatus(utils.OpenIntEnum):
783
783
  ALL_RESULTS_COMPLETED = 0x00
784
784
  PARTIAL = 0x01
785
785
  ABORTED = 0x0F
786
786
 
787
787
 
788
- class CsProcedureAbortReason(OpenIntEnum):
788
+ class CsProcedureAbortReason(utils.OpenIntEnum):
789
789
  NO_ABORT = 0x00
790
790
  LOCAL_HOST_OR_REMOTE_REQUEST = 0x01
791
791
  CHANNEL_MAP_UPDATE_INSTANT_PASSED = 0x02
792
792
  UNSPECIFIED = 0x0F
793
793
 
794
794
 
795
- class CsSubeventAbortReason(OpenIntEnum):
795
+ class CsSubeventAbortReason(utils.OpenIntEnum):
796
796
  NO_ABORT = 0x00
797
797
  LOCAL_HOST_OR_REMOTE_REQUEST = 0x01
798
798
  NO_CS_SYNC_RECEIVED = 0x02
@@ -890,7 +890,7 @@ HCI_LINK_TYPE_NAMES = {
890
890
  }
891
891
 
892
892
  # Address types
893
- class AddressType(OpenIntEnum):
893
+ class AddressType(utils.OpenIntEnum):
894
894
  PUBLIC_DEVICE = 0x00
895
895
  RANDOM_DEVICE = 0x01
896
896
  PUBLIC_IDENTITY = 0x02
@@ -1239,7 +1239,7 @@ HCI_SUPPORTED_COMMANDS_MASKS = {
1239
1239
 
1240
1240
  # LE Supported Features
1241
1241
  # See Bluetooth spec @ Vol 6, Part B, 4.6 FEATURE SUPPORT
1242
- class LeFeature(OpenIntEnum):
1242
+ class LeFeature(utils.OpenIntEnum):
1243
1243
  LE_ENCRYPTION = 0
1244
1244
  CONNECTION_PARAMETERS_REQUEST_PROCEDURE = 1
1245
1245
  EXTENDED_REJECT_INDICATION = 2
@@ -1537,7 +1537,7 @@ RTT_TYPE_SPEC = {'size': 1, 'mapper': lambda x: RttType(x).name}
1537
1537
  CS_SNR_SPEC = {'size': 1, 'mapper': lambda x: CsSnr(x).name}
1538
1538
 
1539
1539
 
1540
- class CodecID(OpenIntEnum):
1540
+ class CodecID(utils.OpenIntEnum):
1541
1541
  # fmt: off
1542
1542
  U_LOG = 0x00
1543
1543
  A_LOG = 0x01
@@ -1976,7 +1976,7 @@ class Address:
1976
1976
  def from_string_for_transport(
1977
1977
  cls: type[Self], string: str, transport: PhysicalTransport
1978
1978
  ) -> Self:
1979
- if transport == BT_BR_EDR_TRANSPORT:
1979
+ if transport == PhysicalTransport.BR_EDR:
1980
1980
  address_type = Address.PUBLIC_DEVICE_ADDRESS
1981
1981
  else:
1982
1982
  address_type = Address.RANDOM_DEVICE_ADDRESS
@@ -4883,6 +4883,20 @@ class HCI_LE_Periodic_Advertising_Sync_Transfer_Command(HCI_Command):
4883
4883
  '''
4884
4884
 
4885
4885
 
4886
+ # -----------------------------------------------------------------------------
4887
+ @HCI_Command.command(
4888
+ fields=[('connection_handle', 2), ('service_data', 2), ('advertising_handle', 1)],
4889
+ return_parameters_fields=[
4890
+ ('status', STATUS_SPEC),
4891
+ ('connection_handle', 2),
4892
+ ],
4893
+ )
4894
+ class HCI_LE_Periodic_Advertising_Set_Info_Transfer_Command(HCI_Command):
4895
+ '''
4896
+ See Bluetooth spec @ 7.8.90 LE Periodic Advertising Set Info Transfer Command
4897
+ '''
4898
+
4899
+
4886
4900
  # -----------------------------------------------------------------------------
4887
4901
  @HCI_Command.command(
4888
4902
  fields=[
@@ -5356,11 +5370,11 @@ class HCI_LE_CS_Create_Config_Command(HCI_Command):
5356
5370
  See Bluetooth spec @ 7.8.137 LE CS Create Config command
5357
5371
  '''
5358
5372
 
5359
- class ChannelSelectionType(OpenIntEnum):
5373
+ class ChannelSelectionType(utils.OpenIntEnum):
5360
5374
  ALGO_3B = 0
5361
5375
  ALGO_3C = 1
5362
5376
 
5363
- class Ch3cShape(OpenIntEnum):
5377
+ class Ch3cShape(utils.OpenIntEnum):
5364
5378
  HAT = 0x00
5365
5379
  X = 0x01
5366
5380
 
@@ -6189,13 +6203,13 @@ class HCI_LE_Periodic_Advertising_Report_Event(HCI_LE_Meta_Event):
6189
6203
  TX_POWER_INFORMATION_NOT_AVAILABLE = 0x7F
6190
6204
  RSSI_NOT_AVAILABLE = 0x7F
6191
6205
 
6192
- class CteType(OpenIntEnum):
6206
+ class CteType(utils.OpenIntEnum):
6193
6207
  AOA_CONSTANT_TONE_EXTENSION = 0x00
6194
6208
  AOD_CONSTANT_TONE_EXTENSION_1US = 0x01
6195
6209
  AOD_CONSTANT_TONE_EXTENSION_2US = 0x02
6196
6210
  NO_CONSTANT_TONE_EXTENSION = 0xFF
6197
6211
 
6198
- class DataStatus(OpenIntEnum):
6212
+ class DataStatus(utils.OpenIntEnum):
6199
6213
  DATA_COMPLETE = 0x00
6200
6214
  DATA_INCOMPLETE_MORE_TO_COME = 0x01
6201
6215
  DATA_INCOMPLETE_TRUNCATED_NO_MORE_TO_COME = 0x02
@@ -6576,7 +6590,7 @@ class HCI_LE_CS_Config_Complete_Event(HCI_LE_Meta_Event):
6576
6590
  See Bluetooth spec @ 7.7.65.42 LE CS Config Complete event
6577
6591
  '''
6578
6592
 
6579
- class Action(OpenIntEnum):
6593
+ class Action(utils.OpenIntEnum):
6580
6594
  REMOVED = 0
6581
6595
  CREATED = 1
6582
6596
 
@@ -6628,7 +6642,7 @@ class HCI_LE_CS_Procedure_Enable_Complete_Event(HCI_LE_Meta_Event):
6628
6642
  See Bluetooth spec @ 7.7.65.43 LE CS Procedure Enable Complete event
6629
6643
  '''
6630
6644
 
6631
- class State(OpenIntEnum):
6645
+ class State(utils.OpenIntEnum):
6632
6646
  DISABLED = 0
6633
6647
  ENABLED = 1
6634
6648
 
@@ -6970,7 +6984,7 @@ class HCI_QOS_Setup_Complete_Event(HCI_Event):
6970
6984
  See Bluetooth spec @ 7.7.13 QoS Setup Complete Event
6971
6985
  '''
6972
6986
 
6973
- class ServiceType(OpenIntEnum):
6987
+ class ServiceType(utils.OpenIntEnum):
6974
6988
  NO_TRAFFIC_AVAILABLE = 0x00
6975
6989
  BEST_EFFORT_AVAILABLE = 0x01
6976
6990
  GUARANTEED_AVAILABLE = 0x02
bumble/hfp.py CHANGED
@@ -24,7 +24,6 @@ import asyncio
24
24
  import dataclasses
25
25
  import enum
26
26
  import traceback
27
- import pyee
28
27
  import re
29
28
  from typing import (
30
29
  Dict,
@@ -45,6 +44,7 @@ from bumble import at
45
44
  from bumble import device
46
45
  from bumble import rfcomm
47
46
  from bumble import sdp
47
+ from bumble import utils
48
48
  from bumble.colors import color
49
49
  from bumble.core import (
50
50
  ProtocolError,
@@ -690,7 +690,7 @@ class HfIndicatorState:
690
690
  current_status: int = 0
691
691
 
692
692
 
693
- class HfProtocol(pyee.EventEmitter):
693
+ class HfProtocol(utils.EventEmitter):
694
694
  """
695
695
  Implementation for the Hands-Free side of the Hands-Free profile.
696
696
 
@@ -1146,7 +1146,7 @@ class HfProtocol(pyee.EventEmitter):
1146
1146
  logger.error(traceback.format_exc())
1147
1147
 
1148
1148
 
1149
- class AgProtocol(pyee.EventEmitter):
1149
+ class AgProtocol(utils.EventEmitter):
1150
1150
  """
1151
1151
  Implementation for the Audio-Gateway side of the Hands-Free profile.
1152
1152
 
bumble/hid.py CHANGED
@@ -22,11 +22,12 @@ import enum
22
22
  import struct
23
23
 
24
24
  from abc import ABC, abstractmethod
25
- from pyee import EventEmitter
26
25
  from typing import Optional, Callable
27
26
  from typing_extensions import override
28
27
 
29
- from bumble import l2cap, device
28
+ from bumble import l2cap
29
+ from bumble import device
30
+ from bumble import utils
30
31
  from bumble.core import InvalidStateError, ProtocolError
31
32
  from bumble.hci import Address
32
33
 
@@ -195,7 +196,7 @@ class SendHandshakeMessage(Message):
195
196
 
196
197
 
197
198
  # -----------------------------------------------------------------------------
198
- class HID(ABC, EventEmitter):
199
+ class HID(ABC, utils.EventEmitter):
199
200
  l2cap_ctrl_channel: Optional[l2cap.ClassicChannel] = None
200
201
  l2cap_intr_channel: Optional[l2cap.ClassicChannel] = None
201
202
  connection: Optional[device.Connection] = None
bumble/host.py CHANGED
@@ -34,7 +34,6 @@ from typing import (
34
34
  TYPE_CHECKING,
35
35
  )
36
36
 
37
- import pyee
38
37
 
39
38
  from bumble.colors import color
40
39
  from bumble.l2cap import L2CAP_PDU
@@ -42,17 +41,16 @@ from bumble.snoop import Snooper
42
41
  from bumble import drivers
43
42
  from bumble import hci
44
43
  from bumble.core import (
45
- BT_BR_EDR_TRANSPORT,
46
- BT_LE_TRANSPORT,
44
+ PhysicalTransport,
47
45
  PhysicalTransport,
48
46
  ConnectionPHY,
49
47
  ConnectionParameters,
50
48
  )
51
- from bumble.utils import AbortableEventEmitter
49
+ from bumble import utils
52
50
  from bumble.transport.common import TransportLostError
53
51
 
54
52
  if TYPE_CHECKING:
55
- from .transport.common import TransportSink, TransportSource
53
+ from bumble.transport.common import TransportSink, TransportSource
56
54
 
57
55
 
58
56
  # -----------------------------------------------------------------------------
@@ -62,7 +60,7 @@ logger = logging.getLogger(__name__)
62
60
 
63
61
 
64
62
  # -----------------------------------------------------------------------------
65
- class DataPacketQueue(pyee.EventEmitter):
63
+ class DataPacketQueue(utils.EventEmitter):
66
64
  """
67
65
  Flow-control queue for host->controller data packets (ACL, ISO).
68
66
 
@@ -200,7 +198,7 @@ class Connection:
200
198
  self.transport = transport
201
199
  acl_packet_queue: Optional[DataPacketQueue] = (
202
200
  host.le_acl_packet_queue
203
- if transport == BT_LE_TRANSPORT
201
+ if transport == PhysicalTransport.LE
204
202
  else host.acl_packet_queue
205
203
  )
206
204
  assert acl_packet_queue
@@ -235,7 +233,7 @@ class IsoLink:
235
233
 
236
234
 
237
235
  # -----------------------------------------------------------------------------
238
- class Host(AbortableEventEmitter):
236
+ class Host(utils.EventEmitter):
239
237
  connections: Dict[int, Connection]
240
238
  cis_links: Dict[int, IsoLink]
241
239
  bis_links: Dict[int, IsoLink]
@@ -967,7 +965,7 @@ class Host(AbortableEventEmitter):
967
965
  self,
968
966
  event.connection_handle,
969
967
  event.peer_address,
970
- BT_LE_TRANSPORT,
968
+ PhysicalTransport.LE,
971
969
  )
972
970
  self.connections[event.connection_handle] = connection
973
971
 
@@ -980,7 +978,7 @@ class Host(AbortableEventEmitter):
980
978
  self.emit(
981
979
  'connection',
982
980
  event.connection_handle,
983
- BT_LE_TRANSPORT,
981
+ PhysicalTransport.LE,
984
982
  event.peer_address,
985
983
  getattr(event, 'local_resolvable_private_address', None),
986
984
  getattr(event, 'peer_resolvable_private_address', None),
@@ -992,7 +990,10 @@ class Host(AbortableEventEmitter):
992
990
 
993
991
  # Notify the listeners
994
992
  self.emit(
995
- 'connection_failure', BT_LE_TRANSPORT, event.peer_address, event.status
993
+ 'connection_failure',
994
+ PhysicalTransport.LE,
995
+ event.peer_address,
996
+ event.status,
996
997
  )
997
998
 
998
999
  def on_hci_le_enhanced_connection_complete_event(self, event):
@@ -1017,7 +1018,7 @@ class Host(AbortableEventEmitter):
1017
1018
  self,
1018
1019
  event.connection_handle,
1019
1020
  event.bd_addr,
1020
- BT_BR_EDR_TRANSPORT,
1021
+ PhysicalTransport.BR_EDR,
1021
1022
  )
1022
1023
  self.connections[event.connection_handle] = connection
1023
1024
 
@@ -1025,7 +1026,7 @@ class Host(AbortableEventEmitter):
1025
1026
  self.emit(
1026
1027
  'connection',
1027
1028
  event.connection_handle,
1028
- BT_BR_EDR_TRANSPORT,
1029
+ PhysicalTransport.BR_EDR,
1029
1030
  event.bd_addr,
1030
1031
  None,
1031
1032
  None,
@@ -1037,7 +1038,10 @@ class Host(AbortableEventEmitter):
1037
1038
 
1038
1039
  # Notify the client
1039
1040
  self.emit(
1040
- 'connection_failure', BT_BR_EDR_TRANSPORT, event.bd_addr, event.status
1041
+ 'connection_failure',
1042
+ PhysicalTransport.BR_EDR,
1043
+ event.bd_addr,
1044
+ event.status,
1041
1045
  )
1042
1046
 
1043
1047
  def on_hci_disconnection_complete_event(self, event):
@@ -1284,7 +1288,8 @@ class Host(AbortableEventEmitter):
1284
1288
  logger.debug('no long term key provider')
1285
1289
  long_term_key = None
1286
1290
  else:
1287
- long_term_key = await self.abort_on(
1291
+ long_term_key = await utils.cancel_on_event(
1292
+ self,
1288
1293
  'flush',
1289
1294
  # pylint: disable-next=not-callable
1290
1295
  self.long_term_key_provider(
@@ -1442,7 +1447,8 @@ class Host(AbortableEventEmitter):
1442
1447
  logger.debug('no link key provider')
1443
1448
  link_key = None
1444
1449
  else:
1445
- link_key = await self.abort_on(
1450
+ link_key = await utils.cancel_on_event(
1451
+ self,
1446
1452
  'flush',
1447
1453
  # pylint: disable-next=not-callable
1448
1454
  self.link_key_provider(event.bd_addr),
bumble/keys.py CHANGED
@@ -28,11 +28,11 @@ import json
28
28
  from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type
29
29
  from typing_extensions import Self
30
30
 
31
- from .colors import color
32
- from .hci import Address
31
+ from bumble.colors import color
32
+ from bumble.hci import Address
33
33
 
34
34
  if TYPE_CHECKING:
35
- from .device import Device
35
+ from bumble.device import Device
36
36
 
37
37
 
38
38
  # -----------------------------------------------------------------------------