bumble 0.0.214__py3-none-any.whl → 0.0.215__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 (122) hide show
  1. bumble/_version.py +16 -3
  2. bumble/a2dp.py +15 -16
  3. bumble/apps/auracast.py +13 -38
  4. bumble/apps/bench.py +9 -10
  5. bumble/apps/ble_rpa_tool.py +1 -0
  6. bumble/apps/console.py +22 -25
  7. bumble/apps/controller_info.py +19 -19
  8. bumble/apps/controller_loopback.py +2 -2
  9. bumble/apps/controllers.py +1 -1
  10. bumble/apps/device_info.py +3 -3
  11. bumble/apps/gatt_dump.py +1 -1
  12. bumble/apps/gg_bridge.py +5 -6
  13. bumble/apps/hci_bridge.py +3 -3
  14. bumble/apps/l2cap_bridge.py +3 -3
  15. bumble/apps/lea_unicast/app.py +15 -25
  16. bumble/apps/pair.py +30 -43
  17. bumble/apps/pandora_server.py +5 -4
  18. bumble/apps/player/player.py +19 -22
  19. bumble/apps/rfcomm_bridge.py +3 -8
  20. bumble/apps/scan.py +16 -6
  21. bumble/apps/show.py +3 -4
  22. bumble/apps/speaker/speaker.py +22 -22
  23. bumble/apps/unbond.py +2 -1
  24. bumble/apps/usb_probe.py +1 -2
  25. bumble/att.py +241 -246
  26. bumble/audio/io.py +5 -9
  27. bumble/avc.py +2 -2
  28. bumble/avctp.py +6 -7
  29. bumble/avdtp.py +19 -22
  30. bumble/avrcp.py +1096 -588
  31. bumble/codecs.py +2 -0
  32. bumble/controller.py +52 -13
  33. bumble/core.py +567 -248
  34. bumble/crypto/__init__.py +2 -2
  35. bumble/crypto/builtin.py +1 -1
  36. bumble/crypto/cryptography.py +2 -4
  37. bumble/data_types.py +1025 -0
  38. bumble/device.py +280 -278
  39. bumble/drivers/__init__.py +3 -2
  40. bumble/drivers/intel.py +3 -4
  41. bumble/drivers/rtk.py +26 -9
  42. bumble/gap.py +4 -4
  43. bumble/gatt.py +3 -2
  44. bumble/gatt_adapters.py +3 -11
  45. bumble/gatt_client.py +69 -81
  46. bumble/gatt_server.py +124 -124
  47. bumble/hci.py +67 -18
  48. bumble/helpers.py +19 -26
  49. bumble/hfp.py +10 -21
  50. bumble/hid.py +22 -16
  51. bumble/host.py +181 -103
  52. bumble/keys.py +5 -3
  53. bumble/l2cap.py +121 -74
  54. bumble/link.py +8 -9
  55. bumble/pairing.py +7 -6
  56. bumble/pandora/__init__.py +8 -7
  57. bumble/pandora/config.py +3 -1
  58. bumble/pandora/device.py +3 -2
  59. bumble/pandora/host.py +38 -36
  60. bumble/pandora/l2cap.py +22 -21
  61. bumble/pandora/security.py +15 -15
  62. bumble/pandora/utils.py +5 -3
  63. bumble/profiles/aics.py +11 -11
  64. bumble/profiles/ams.py +7 -8
  65. bumble/profiles/ancs.py +6 -7
  66. bumble/profiles/ascs.py +4 -9
  67. bumble/profiles/asha.py +8 -12
  68. bumble/profiles/bap.py +11 -23
  69. bumble/profiles/bass.py +2 -7
  70. bumble/profiles/battery_service.py +3 -4
  71. bumble/profiles/cap.py +1 -2
  72. bumble/profiles/csip.py +2 -6
  73. bumble/profiles/device_information_service.py +2 -2
  74. bumble/profiles/gap.py +4 -4
  75. bumble/profiles/gatt_service.py +1 -4
  76. bumble/profiles/gmap.py +5 -5
  77. bumble/profiles/hap.py +62 -59
  78. bumble/profiles/heart_rate_service.py +5 -4
  79. bumble/profiles/le_audio.py +3 -1
  80. bumble/profiles/mcp.py +3 -7
  81. bumble/profiles/pacs.py +3 -6
  82. bumble/profiles/pbp.py +2 -0
  83. bumble/profiles/tmap.py +2 -3
  84. bumble/profiles/vcs.py +2 -8
  85. bumble/profiles/vocs.py +8 -8
  86. bumble/rfcomm.py +11 -14
  87. bumble/rtp.py +1 -0
  88. bumble/sdp.py +10 -8
  89. bumble/smp.py +142 -153
  90. bumble/snoop.py +5 -5
  91. bumble/tools/generate_company_id_list.py +1 -0
  92. bumble/tools/intel_fw_download.py +3 -3
  93. bumble/tools/intel_util.py +4 -4
  94. bumble/tools/rtk_fw_download.py +6 -3
  95. bumble/tools/rtk_util.py +24 -7
  96. bumble/transport/__init__.py +19 -15
  97. bumble/transport/android_emulator.py +8 -13
  98. bumble/transport/android_netsim.py +19 -18
  99. bumble/transport/common.py +12 -15
  100. bumble/transport/file.py +1 -1
  101. bumble/transport/hci_socket.py +4 -6
  102. bumble/transport/pty.py +5 -6
  103. bumble/transport/pyusb.py +7 -10
  104. bumble/transport/serial.py +2 -1
  105. bumble/transport/tcp_client.py +2 -2
  106. bumble/transport/tcp_server.py +11 -14
  107. bumble/transport/udp.py +3 -3
  108. bumble/transport/unix.py +67 -1
  109. bumble/transport/usb.py +6 -6
  110. bumble/transport/vhci.py +0 -1
  111. bumble/transport/ws_client.py +2 -1
  112. bumble/transport/ws_server.py +3 -2
  113. bumble/utils.py +20 -5
  114. bumble/vendor/android/hci.py +1 -2
  115. bumble/vendor/zephyr/hci.py +0 -1
  116. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/METADATA +2 -1
  117. bumble-0.0.215.dist-info/RECORD +183 -0
  118. bumble-0.0.214.dist-info/RECORD +0 -182
  119. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/WHEEL +0 -0
  120. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/entry_points.txt +0 -0
  121. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/licenses/LICENSE +0 -0
  122. {bumble-0.0.214.dist-info → bumble-0.0.215.dist-info}/top_level.txt +0 -0
bumble/l2cap.py CHANGED
@@ -16,32 +16,32 @@
16
16
  # Imports
17
17
  # -----------------------------------------------------------------------------
18
18
  from __future__ import annotations
19
+
19
20
  import asyncio
20
21
  import dataclasses
21
22
  import enum
22
23
  import logging
23
24
  import struct
24
-
25
25
  from collections import deque
26
+ from collections.abc import Sequence
26
27
  from typing import (
27
- Optional,
28
- Callable,
28
+ TYPE_CHECKING,
29
29
  Any,
30
- Union,
30
+ Callable,
31
+ ClassVar,
31
32
  Iterable,
33
+ Optional,
32
34
  SupportsBytes,
33
35
  TypeVar,
34
- ClassVar,
35
- TYPE_CHECKING,
36
+ Union,
36
37
  )
37
38
 
38
- from bumble import utils
39
- from bumble import hci
39
+ from bumble import hci, utils
40
40
  from bumble.colors import color
41
41
  from bumble.core import (
42
- InvalidStateError,
43
42
  InvalidArgumentError,
44
43
  InvalidPacketError,
44
+ InvalidStateError,
45
45
  OutOfResourcesError,
46
46
  ProtocolError,
47
47
  )
@@ -112,6 +112,10 @@ class CommandCode(hci.SpecableEnum):
112
112
  L2CAP_LE_CREDIT_BASED_CONNECTION_REQUEST = 0x14
113
113
  L2CAP_LE_CREDIT_BASED_CONNECTION_RESPONSE = 0x15
114
114
  L2CAP_LE_FLOW_CONTROL_CREDIT = 0x16
115
+ L2CAP_CREDIT_BASED_CONNECTION_REQUEST = 0x17
116
+ L2CAP_CREDIT_BASED_CONNECTION_RESPONSE = 0x18
117
+ L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST = 0x19
118
+ L2CAP_CREDIT_BASED_RECONFIGURE_RESPONSE = 0x1A
115
119
 
116
120
  L2CAP_CONNECTION_PARAMETERS_ACCEPTED_RESULT = 0x0000
117
121
  L2CAP_CONNECTION_PARAMETERS_REJECTED_RESULT = 0x0001
@@ -595,6 +599,109 @@ class L2CAP_LE_Flow_Control_Credit(L2CAP_Control_Frame):
595
599
  credits: int = dataclasses.field(metadata=hci.metadata(2))
596
600
 
597
601
 
602
+ # -----------------------------------------------------------------------------
603
+ @L2CAP_Control_Frame.subclass
604
+ @dataclasses.dataclass
605
+ class L2CAP_Credit_Based_Connection_Request(L2CAP_Control_Frame):
606
+ '''
607
+ See Bluetooth spec @ Vol 3, Part A - 4.25 L2CAP_CREDIT_BASED_CONNECTION_REQ (0x17).
608
+ '''
609
+
610
+ @classmethod
611
+ def parse_cid_list(cls, data: bytes, offset: int) -> tuple[int, list[int]]:
612
+ count = (len(data) - offset) // 2
613
+ return len(data), list(struct.unpack_from("<" + ("H" * count), data, offset))
614
+
615
+ @classmethod
616
+ def serialize_cid_list(cls, cids: Sequence[int]) -> bytes:
617
+ return b"".join([struct.pack("<H", cid) for cid in cids])
618
+
619
+ CID_METADATA: ClassVar[dict[str, Any]] = hci.metadata(
620
+ {
621
+ 'parser': lambda data, offset: L2CAP_Credit_Based_Connection_Request.parse_cid_list(
622
+ data, offset
623
+ ),
624
+ 'serializer': lambda value: L2CAP_Credit_Based_Connection_Request.serialize_cid_list(
625
+ value
626
+ ),
627
+ }
628
+ )
629
+
630
+ spsm: int = dataclasses.field(metadata=hci.metadata(2))
631
+ mtu: int = dataclasses.field(metadata=hci.metadata(2))
632
+ mps: int = dataclasses.field(metadata=hci.metadata(2))
633
+ initial_credits: int = dataclasses.field(metadata=hci.metadata(2))
634
+ source_cid: Sequence[int] = dataclasses.field(metadata=CID_METADATA)
635
+
636
+
637
+ # -----------------------------------------------------------------------------
638
+ @L2CAP_Control_Frame.subclass
639
+ @dataclasses.dataclass
640
+ class L2CAP_Credit_Based_Connection_Response(L2CAP_Control_Frame):
641
+ '''
642
+ See Bluetooth spec @ Vol 3, Part A - 4.26 L2CAP_CREDIT_BASED_CONNECTION_RSP (0x18).
643
+ '''
644
+
645
+ class Result(hci.SpecableEnum):
646
+ ALL_CONNECTIONS_SUCCESSFUL = 0x0000
647
+ ALL_CONNECTIONS_REFUSED_SPSM_NOT_SUPPORTED = 0x0002
648
+ SOME_CONNECTIONS_REFUSED_INSUFFICIENT_RESOURCES_AVAILABLE = 0x0004
649
+ ALL_CONNECTIONS_REFUSED_INSUFFICIENT_AUTHENTICATION = 0x0005
650
+ ALL_CONNECTIONS_REFUSED_INSUFFICIENT_AUTHORIZATION = 0x0006
651
+ ALL_CONNECTIONS_REFUSED_ENCRYPTION_KEY_SIZE_TOO_SHORT = 0x0007
652
+ ALL_CONNECTIONS_REFUSED_INSUFFICIENT_ENCRYPTION = 0x0008
653
+ SOME_CONNECTIONS_REFUSED_INVALID_SOURCE_CID = 0x0009
654
+ SOME_CONNECTIONS_REFUSED_SOURCE_CID_ALREADY_ALLOCATED = 0x000A
655
+ ALL_CONNECTIONS_REFUSED_UNACCEPTABLE_PARAMETERS = 0x000B
656
+ ALL_CONNECTIONS_REFUSED_INVALID_PARAMETERS = 0x000C
657
+ ALL_CONNECTIONS_PENDING_NO_FURTHER_INFORMATION_AVAILABLE = 0x000D
658
+ ALL_CONNECTIONS_PENDING_AUTHENTICATION_PENDING = 0x000E
659
+ ALL_CONNECTIONS_PENDING_AUTHORIZATION_PENDING = 0x000F
660
+
661
+ mtu: int = dataclasses.field(metadata=hci.metadata(2))
662
+ mps: int = dataclasses.field(metadata=hci.metadata(2))
663
+ initial_credits: int = dataclasses.field(metadata=hci.metadata(2))
664
+ result: int = dataclasses.field(metadata=Result.type_metadata(2))
665
+ destination_cid: Sequence[int] = dataclasses.field(
666
+ metadata=L2CAP_Credit_Based_Connection_Request.CID_METADATA
667
+ )
668
+
669
+
670
+ # -----------------------------------------------------------------------------
671
+ @L2CAP_Control_Frame.subclass
672
+ @dataclasses.dataclass
673
+ class L2CAP_Credit_Based_Reconfigure_Request(L2CAP_Control_Frame):
674
+ '''
675
+ See Bluetooth spec @ Vol 3, Part A - 4.27 L2CAP_CREDIT_BASED_RECONFIGURE_REQ (0x19).
676
+ '''
677
+
678
+ mtu: int = dataclasses.field(metadata=hci.metadata(2))
679
+ mps: int = dataclasses.field(metadata=hci.metadata(2))
680
+ destination_cid: Sequence[int] = dataclasses.field(
681
+ metadata=L2CAP_Credit_Based_Connection_Request.CID_METADATA
682
+ )
683
+
684
+
685
+ # -----------------------------------------------------------------------------
686
+ @L2CAP_Control_Frame.subclass
687
+ @dataclasses.dataclass
688
+ class L2CAP_Credit_Based_Reconfigure_Response(L2CAP_Control_Frame):
689
+ '''
690
+ See Bluetooth spec @ Vol 3, Part A - 4.28 L2CAP_CREDIT_BASED_RECONFIGURE_RSP (0x1A).
691
+ '''
692
+
693
+ class Result(hci.SpecableEnum):
694
+ RECONFIGURATION_SUCCESSFUL = 0x0000
695
+ RECONFIGURATION_FAILED_REDUCTION_IN_SIZE_OF_MTU_NOT_ALLOWED = 0x0001
696
+ RECONFIGURATION_FAILED_REDUCTION_IN_SIZE_OF_MPS_NOT_ALLOWED_FOR_MORE_THAN_ONE_CHANNEL_AT_A_TIME = (
697
+ 0x0002
698
+ )
699
+ RECONFIGURATION_FAILED_ONE_OR_MORE_DESTINATION_CIDS_INVALID = 0x0003
700
+ RECONFIGURATION_FAILED_OTHER_UNACCEPTABLE_PARAMETERS = 0x0004
701
+
702
+ result: int = dataclasses.field(metadata=Result.type_metadata(2))
703
+
704
+
598
705
  # -----------------------------------------------------------------------------
599
706
  class ClassicChannel(utils.EventEmitter):
600
707
  class State(enum.IntEnum):
@@ -1424,16 +1531,6 @@ class ChannelManager:
1424
1531
  if cid in self.fixed_channels:
1425
1532
  del self.fixed_channels[cid]
1426
1533
 
1427
- @utils.deprecated("Please use create_classic_server")
1428
- def register_server(
1429
- self,
1430
- psm: int,
1431
- server: Callable[[ClassicChannel], Any],
1432
- ) -> int:
1433
- return self.create_classic_server(
1434
- handler=server, spec=ClassicChannelSpec(psm=psm)
1435
- ).psm
1436
-
1437
1534
  def create_classic_server(
1438
1535
  self,
1439
1536
  spec: ClassicChannelSpec,
@@ -1470,22 +1567,6 @@ class ChannelManager:
1470
1567
 
1471
1568
  return self.servers[spec.psm]
1472
1569
 
1473
- @utils.deprecated("Please use create_le_credit_based_server()")
1474
- def register_le_coc_server(
1475
- self,
1476
- psm: int,
1477
- server: Callable[[LeCreditBasedChannel], Any],
1478
- max_credits: int,
1479
- mtu: int,
1480
- mps: int,
1481
- ) -> int:
1482
- return self.create_le_credit_based_server(
1483
- spec=LeCreditBasedChannelSpec(
1484
- psm=None if psm == 0 else psm, mtu=mtu, mps=mps, max_credits=max_credits
1485
- ),
1486
- handler=server,
1487
- ).psm
1488
-
1489
1570
  def create_le_credit_based_server(
1490
1571
  self,
1491
1572
  spec: LeCreditBasedChannelSpec,
@@ -1587,8 +1668,8 @@ class ChannelManager:
1587
1668
  if handler:
1588
1669
  try:
1589
1670
  handler(connection, cid, control_frame)
1590
- except Exception as error:
1591
- logger.warning(f'{color("!!! Exception in handler:", "red")} {error}')
1671
+ except Exception:
1672
+ logger.exception(color("!!! Exception in handler:", "red"))
1592
1673
  self.send_control_frame(
1593
1674
  connection,
1594
1675
  cid,
@@ -1598,7 +1679,7 @@ class ChannelManager:
1598
1679
  data=b'',
1599
1680
  ),
1600
1681
  )
1601
- raise error
1682
+ raise
1602
1683
  else:
1603
1684
  logger.error(color('Channel Manager command not handled???', 'red'))
1604
1685
  self.send_control_frame(
@@ -2038,17 +2119,6 @@ class ChannelManager:
2038
2119
  if channel.source_cid in connection_channels:
2039
2120
  del connection_channels[channel.source_cid]
2040
2121
 
2041
- @utils.deprecated("Please use create_le_credit_based_channel()")
2042
- async def open_le_coc(
2043
- self, connection: Connection, psm: int, max_credits: int, mtu: int, mps: int
2044
- ) -> LeCreditBasedChannel:
2045
- return await self.create_le_credit_based_channel(
2046
- connection=connection,
2047
- spec=LeCreditBasedChannelSpec(
2048
- psm=psm, max_credits=max_credits, mtu=mtu, mps=mps
2049
- ),
2050
- )
2051
-
2052
2122
  async def create_le_credit_based_channel(
2053
2123
  self,
2054
2124
  connection: Connection,
@@ -2084,8 +2154,8 @@ class ChannelManager:
2084
2154
  # Connect
2085
2155
  try:
2086
2156
  await channel.connect()
2087
- except Exception as error:
2088
- logger.warning(f'connection failed: {error}')
2157
+ except Exception:
2158
+ logger.exception('connection failed')
2089
2159
  del connection_channels[source_cid]
2090
2160
  raise
2091
2161
 
@@ -2095,12 +2165,6 @@ class ChannelManager:
2095
2165
 
2096
2166
  return channel
2097
2167
 
2098
- @utils.deprecated("Please use create_classic_channel()")
2099
- async def connect(self, connection: Connection, psm: int) -> ClassicChannel:
2100
- return await self.create_classic_channel(
2101
- connection=connection, spec=ClassicChannelSpec(psm=psm)
2102
- )
2103
-
2104
2168
  async def create_classic_channel(
2105
2169
  self, connection: Connection, spec: ClassicChannelSpec
2106
2170
  ) -> ClassicChannel:
@@ -2137,20 +2201,3 @@ class ChannelManager:
2137
2201
  raise e
2138
2202
 
2139
2203
  return channel
2140
-
2141
-
2142
- # -----------------------------------------------------------------------------
2143
- # Deprecated Classes
2144
- # -----------------------------------------------------------------------------
2145
-
2146
-
2147
- class Channel(ClassicChannel):
2148
- @utils.deprecated("Please use ClassicChannel")
2149
- def __init__(self, *args, **kwargs) -> None:
2150
- super().__init__(*args, **kwargs)
2151
-
2152
-
2153
- class LeConnectionOrientedChannel(LeCreditBasedChannel):
2154
- @utils.deprecated("Please use LeCreditBasedChannel")
2155
- def __init__(self, *args, **kwargs) -> None:
2156
- super().__init__(*args, **kwargs)
bumble/link.py CHANGED
@@ -12,25 +12,24 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import asyncio
16
+
15
17
  # -----------------------------------------------------------------------------
16
18
  # Imports
17
19
  # -----------------------------------------------------------------------------
18
20
  import logging
19
- import asyncio
21
+ from typing import Optional
20
22
 
21
- from bumble import core
23
+ from bumble import controller, core
22
24
  from bumble.hci import (
23
- Address,
24
- Role,
25
- HCI_SUCCESS,
26
25
  HCI_CONNECTION_ACCEPT_TIMEOUT_ERROR,
27
- HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
28
26
  HCI_PAGE_TIMEOUT_ERROR,
27
+ HCI_SUCCESS,
28
+ HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
29
+ Address,
29
30
  HCI_Connection_Complete_Event,
31
+ Role,
30
32
  )
31
- from bumble import controller
32
-
33
- from typing import Optional
34
33
 
35
34
  # -----------------------------------------------------------------------------
36
35
  # Logging
bumble/pairing.py CHANGED
@@ -16,27 +16,28 @@
16
16
  # Imports
17
17
  # -----------------------------------------------------------------------------
18
18
  from __future__ import annotations
19
+
19
20
  import enum
20
- from dataclasses import dataclass
21
21
  import secrets
22
+ from dataclasses import dataclass
22
23
  from typing import Optional
23
24
 
24
25
  from bumble import hci
26
+ from bumble.core import AdvertisingData, LeRole
25
27
  from bumble.smp import (
26
- SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY,
27
- SMP_KEYBOARD_ONLY_IO_CAPABILITY,
28
28
  SMP_DISPLAY_ONLY_IO_CAPABILITY,
29
29
  SMP_DISPLAY_YES_NO_IO_CAPABILITY,
30
- SMP_KEYBOARD_DISPLAY_IO_CAPABILITY,
31
30
  SMP_ENC_KEY_DISTRIBUTION_FLAG,
32
31
  SMP_ID_KEY_DISTRIBUTION_FLAG,
33
- SMP_SIGN_KEY_DISTRIBUTION_FLAG,
32
+ SMP_KEYBOARD_DISPLAY_IO_CAPABILITY,
33
+ SMP_KEYBOARD_ONLY_IO_CAPABILITY,
34
34
  SMP_LINK_KEY_DISTRIBUTION_FLAG,
35
+ SMP_NO_INPUT_NO_OUTPUT_IO_CAPABILITY,
36
+ SMP_SIGN_KEY_DISTRIBUTION_FLAG,
35
37
  OobContext,
36
38
  OobLegacyContext,
37
39
  OobSharedData,
38
40
  )
39
- from bumble.core import AdvertisingData, LeRole
40
41
 
41
42
 
42
43
  # -----------------------------------------------------------------------------
@@ -19,21 +19,22 @@ This module implement the Pandora Bluetooth test APIs for the Bumble stack.
19
19
 
20
20
  __version__ = "0.0.1"
21
21
 
22
+ from typing import Callable, List, Optional
23
+
22
24
  import grpc
23
25
  import grpc.aio
24
-
25
- from bumble.pandora.config import Config
26
- from bumble.pandora.device import PandoraDevice
27
- from bumble.pandora.host import HostService
28
- from bumble.pandora.l2cap import L2CAPService
29
- from bumble.pandora.security import SecurityService, SecurityStorageService
30
26
  from pandora.host_grpc_aio import add_HostServicer_to_server
31
27
  from pandora.l2cap_grpc_aio import add_L2CAPServicer_to_server
32
28
  from pandora.security_grpc_aio import (
33
29
  add_SecurityServicer_to_server,
34
30
  add_SecurityStorageServicer_to_server,
35
31
  )
36
- from typing import Callable, List, Optional
32
+
33
+ from bumble.pandora.config import Config
34
+ from bumble.pandora.device import PandoraDevice
35
+ from bumble.pandora.host import HostService
36
+ from bumble.pandora.l2cap import L2CAPService
37
+ from bumble.pandora.security import SecurityService, SecurityStorageService
37
38
 
38
39
  # public symbols
39
40
  __all__ = [
bumble/pandora/config.py CHANGED
@@ -13,10 +13,12 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from __future__ import annotations
16
- from bumble.pairing import PairingConfig, PairingDelegate
16
+
17
17
  from dataclasses import dataclass
18
18
  from typing import Any
19
19
 
20
+ from bumble.pairing import PairingConfig, PairingDelegate
21
+
20
22
 
21
23
  @dataclass
22
24
  class Config:
bumble/pandora/device.py CHANGED
@@ -15,6 +15,9 @@
15
15
  """Generic & dependency free Bumble (reference) device."""
16
16
 
17
17
  from __future__ import annotations
18
+
19
+ from typing import Any, Optional
20
+
18
21
  from bumble import transport
19
22
  from bumble.core import (
20
23
  BT_GENERIC_AUDIO_SERVICE,
@@ -32,8 +35,6 @@ from bumble.sdp import (
32
35
  DataElement,
33
36
  ServiceAttribute,
34
37
  )
35
- from typing import Any, Optional
36
-
37
38
 
38
39
  # Default rootcanal HCI TCP address
39
40
  ROOTCANAL_HCI_ADDRESS = "localhost:6402"
bumble/pandora/host.py CHANGED
@@ -13,51 +13,23 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from __future__ import annotations
16
+
16
17
  import asyncio
17
- import bumble.device
18
- import grpc
19
- import grpc.aio
20
18
  import logging
21
19
  import struct
20
+ from typing import AsyncGenerator, Optional, cast
22
21
 
23
- import bumble.utils
24
- from bumble.pandora import utils
25
- from bumble.pandora.config import Config
26
- from bumble.core import (
27
- PhysicalTransport,
28
- UUID,
29
- AdvertisingData,
30
- Appearance,
31
- ConnectionError,
32
- )
33
- from bumble.device import (
34
- DEVICE_DEFAULT_SCAN_INTERVAL,
35
- DEVICE_DEFAULT_SCAN_WINDOW,
36
- Advertisement,
37
- AdvertisingParameters,
38
- AdvertisingEventProperties,
39
- AdvertisingType,
40
- Device,
41
- )
42
- from bumble.gatt import Service
43
- from bumble.hci import (
44
- HCI_CONNECTION_ALREADY_EXISTS_ERROR,
45
- HCI_PAGE_TIMEOUT_ERROR,
46
- HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR,
47
- Address,
48
- Phy,
49
- Role,
50
- OwnAddressType,
51
- )
22
+ import grpc
23
+ import grpc.aio
52
24
  from google.protobuf import any_pb2 # pytype: disable=pyi-error
53
25
  from google.protobuf import empty_pb2 # pytype: disable=pyi-error
54
- from pandora.host_grpc_aio import HostServicer
55
26
  from pandora import host_pb2
27
+ from pandora.host_grpc_aio import HostServicer
56
28
  from pandora.host_pb2 import (
29
+ DISCOVERABLE_GENERAL,
30
+ DISCOVERABLE_LIMITED,
57
31
  NOT_CONNECTABLE,
58
32
  NOT_DISCOVERABLE,
59
- DISCOVERABLE_LIMITED,
60
- DISCOVERABLE_GENERAL,
61
33
  PRIMARY_1M,
62
34
  PRIMARY_CODED,
63
35
  SECONDARY_1M,
@@ -85,7 +57,37 @@ from pandora.host_pb2 import (
85
57
  WaitConnectionResponse,
86
58
  WaitDisconnectionRequest,
87
59
  )
88
- from typing import AsyncGenerator, Optional, cast
60
+
61
+ import bumble.device
62
+ import bumble.utils
63
+ from bumble.core import (
64
+ UUID,
65
+ AdvertisingData,
66
+ Appearance,
67
+ ConnectionError,
68
+ PhysicalTransport,
69
+ )
70
+ from bumble.device import (
71
+ DEVICE_DEFAULT_SCAN_INTERVAL,
72
+ DEVICE_DEFAULT_SCAN_WINDOW,
73
+ Advertisement,
74
+ AdvertisingEventProperties,
75
+ AdvertisingParameters,
76
+ AdvertisingType,
77
+ Device,
78
+ )
79
+ from bumble.gatt import Service
80
+ from bumble.hci import (
81
+ HCI_CONNECTION_ALREADY_EXISTS_ERROR,
82
+ HCI_PAGE_TIMEOUT_ERROR,
83
+ HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR,
84
+ Address,
85
+ OwnAddressType,
86
+ Phy,
87
+ Role,
88
+ )
89
+ from bumble.pandora import utils
90
+ from bumble.pandora.config import Config
89
91
 
90
92
  PRIMARY_PHY_MAP: dict[int, PrimaryPhy] = {
91
93
  # Default value reported by Bumble for legacy Advertising reports.
bumble/pandora/l2cap.py CHANGED
@@ -12,31 +12,21 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  from __future__ import annotations
15
+
15
16
  import asyncio
16
- import grpc
17
17
  import json
18
18
  import logging
19
+ from asyncio import Future
20
+ from asyncio import Queue as AsyncQueue
21
+ from dataclasses import dataclass
22
+ from typing import AsyncGenerator, Optional, Union
19
23
 
20
- from asyncio import Queue as AsyncQueue, Future
21
-
22
- from bumble.pandora import utils
23
- from bumble.pandora.config import Config
24
- from bumble.core import OutOfResourcesError, InvalidArgumentError
25
- from bumble.device import Device
26
- from bumble.l2cap import (
27
- ClassicChannel,
28
- ClassicChannelServer,
29
- ClassicChannelSpec,
30
- LeCreditBasedChannel,
31
- LeCreditBasedChannelServer,
32
- LeCreditBasedChannelSpec,
33
- )
24
+ import grpc
34
25
  from google.protobuf import any_pb2, empty_pb2 # pytype: disable=pyi-error
35
26
  from pandora.l2cap_grpc_aio import L2CAPServicer # pytype: disable=pyi-error
36
- from pandora.l2cap_pb2 import ( # pytype: disable=pyi-error
37
- COMMAND_NOT_UNDERSTOOD,
38
- INVALID_CID_IN_REQUEST,
39
- Channel as PandoraChannel,
27
+ from pandora.l2cap_pb2 import COMMAND_NOT_UNDERSTOOD, INVALID_CID_IN_REQUEST
28
+ from pandora.l2cap_pb2 import Channel as PandoraChannel # pytype: disable=pyi-error
29
+ from pandora.l2cap_pb2 import (
40
30
  ConnectRequest,
41
31
  ConnectResponse,
42
32
  CreditBasedChannelRequest,
@@ -51,8 +41,19 @@ from pandora.l2cap_pb2 import ( # pytype: disable=pyi-error
51
41
  WaitDisconnectionRequest,
52
42
  WaitDisconnectionResponse,
53
43
  )
54
- from typing import AsyncGenerator, Optional, Union
55
- from dataclasses import dataclass
44
+
45
+ from bumble.core import InvalidArgumentError, OutOfResourcesError
46
+ from bumble.device import Device
47
+ from bumble.l2cap import (
48
+ ClassicChannel,
49
+ ClassicChannelServer,
50
+ ClassicChannelSpec,
51
+ LeCreditBasedChannel,
52
+ LeCreditBasedChannelServer,
53
+ LeCreditBasedChannelSpec,
54
+ )
55
+ from bumble.pandora import utils
56
+ from bumble.pandora.config import Config
56
57
 
57
58
  L2capChannel = Union[ClassicChannel, LeCreditBasedChannel]
58
59
 
@@ -13,24 +13,14 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from __future__ import annotations
16
+
16
17
  import asyncio
17
18
  import contextlib
18
- from collections.abc import Awaitable
19
- import grpc
20
19
  import logging
20
+ from collections.abc import Awaitable
21
+ from typing import Any, AsyncGenerator, AsyncIterator, Callable, Optional, Union
21
22
 
22
- from bumble.pandora import utils
23
- from bumble.pandora.config import Config
24
- from bumble import hci
25
- from bumble.core import (
26
- PhysicalTransport,
27
- ProtocolError,
28
- InvalidArgumentError,
29
- )
30
- import bumble.utils
31
- from bumble.device import Connection as BumbleConnection, Device
32
- from bumble.hci import HCI_Error, Role
33
- from bumble.pairing import PairingConfig, PairingDelegate as BasePairingDelegate
23
+ import grpc
34
24
  from google.protobuf import any_pb2 # pytype: disable=pyi-error
35
25
  from google.protobuf import empty_pb2 # pytype: disable=pyi-error
36
26
  from google.protobuf import wrappers_pb2 # pytype: disable=pyi-error
@@ -57,7 +47,17 @@ from pandora.security_pb2 import (
57
47
  WaitSecurityRequest,
58
48
  WaitSecurityResponse,
59
49
  )
60
- from typing import Any, AsyncGenerator, AsyncIterator, Callable, Optional, Union
50
+
51
+ import bumble.utils
52
+ from bumble import hci
53
+ from bumble.core import InvalidArgumentError, PhysicalTransport, ProtocolError
54
+ from bumble.device import Connection as BumbleConnection
55
+ from bumble.device import Device
56
+ from bumble.hci import HCI_Error, Role
57
+ from bumble.pairing import PairingConfig
58
+ from bumble.pairing import PairingDelegate as BasePairingDelegate
59
+ from bumble.pandora import utils
60
+ from bumble.pandora.config import Config
61
61
 
62
62
 
63
63
  class PairingDelegate(BasePairingDelegate):
bumble/pandora/utils.py CHANGED
@@ -13,16 +13,18 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from __future__ import annotations
16
+
16
17
  import contextlib
17
18
  import functools
18
- import grpc
19
19
  import inspect
20
20
  import logging
21
+ from typing import Any, Generator, MutableMapping, Optional
22
+
23
+ import grpc
24
+ from google.protobuf.message import Message # pytype: disable=pyi-error
21
25
 
22
26
  from bumble.device import Device
23
27
  from bumble.hci import Address, AddressType
24
- from google.protobuf.message import Message # pytype: disable=pyi-error
25
- from typing import Any, Generator, MutableMapping, Optional
26
28
 
27
29
  ADDRESS_TYPES: dict[str, AddressType] = {
28
30
  "public": Address.PUBLIC_DEVICE_ADDRESS,
bumble/profiles/aics.py CHANGED
@@ -18,26 +18,27 @@
18
18
  # Imports
19
19
  # -----------------------------------------------------------------------------
20
20
  from __future__ import annotations
21
+
21
22
  import logging
22
23
  import struct
23
-
24
24
  from dataclasses import dataclass
25
25
  from typing import Optional
26
26
 
27
- from bumble.device import Connection
27
+ from bumble import utils
28
28
  from bumble.att import ATT_Error
29
+ from bumble.device import Connection
29
30
  from bumble.gatt import (
30
- Attribute,
31
- Characteristic,
32
- TemplateService,
33
- CharacteristicValue,
31
+ GATT_AUDIO_INPUT_CONTROL_POINT_CHARACTERISTIC,
34
32
  GATT_AUDIO_INPUT_CONTROL_SERVICE,
33
+ GATT_AUDIO_INPUT_DESCRIPTION_CHARACTERISTIC,
35
34
  GATT_AUDIO_INPUT_STATE_CHARACTERISTIC,
36
- GATT_GAIN_SETTINGS_ATTRIBUTE_CHARACTERISTIC,
37
- GATT_AUDIO_INPUT_TYPE_CHARACTERISTIC,
38
35
  GATT_AUDIO_INPUT_STATUS_CHARACTERISTIC,
39
- GATT_AUDIO_INPUT_CONTROL_POINT_CHARACTERISTIC,
40
- GATT_AUDIO_INPUT_DESCRIPTION_CHARACTERISTIC,
36
+ GATT_AUDIO_INPUT_TYPE_CHARACTERISTIC,
37
+ GATT_GAIN_SETTINGS_ATTRIBUTE_CHARACTERISTIC,
38
+ Attribute,
39
+ Characteristic,
40
+ CharacteristicValue,
41
+ TemplateService,
41
42
  )
42
43
  from bumble.gatt_adapters import (
43
44
  CharacteristicProxy,
@@ -48,7 +49,6 @@ from bumble.gatt_adapters import (
48
49
  UTF8CharacteristicProxyAdapter,
49
50
  )
50
51
  from bumble.gatt_client import ProfileServiceProxy, ServiceProxy
51
- from bumble import utils
52
52
 
53
53
  # -----------------------------------------------------------------------------
54
54
  # Logging