bumble 0.0.181__py3-none-any.whl → 0.0.182__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.
bumble/hci.py CHANGED
@@ -2026,6 +2026,17 @@ class OwnAddressType(enum.IntEnum):
2026
2026
  return {'size': 1, 'mapper': lambda x: OwnAddressType(x).name}
2027
2027
 
2028
2028
 
2029
+ # -----------------------------------------------------------------------------
2030
+ class LoopbackMode(enum.IntEnum):
2031
+ DISABLED = 0
2032
+ LOCAL = 1
2033
+ REMOTE = 2
2034
+
2035
+ @classmethod
2036
+ def type_spec(cls):
2037
+ return {'size': 1, 'mapper': lambda x: LoopbackMode(x).name}
2038
+
2039
+
2029
2040
  # -----------------------------------------------------------------------------
2030
2041
  class HCI_Packet:
2031
2042
  '''
@@ -3352,6 +3363,27 @@ class HCI_Read_Encryption_Key_Size_Command(HCI_Command):
3352
3363
  '''
3353
3364
 
3354
3365
 
3366
+ # -----------------------------------------------------------------------------
3367
+ @HCI_Command.command(
3368
+ return_parameters_fields=[
3369
+ ('status', STATUS_SPEC),
3370
+ ('loopback_mode', LoopbackMode.type_spec()),
3371
+ ],
3372
+ )
3373
+ class HCI_Read_Loopback_Mode_Command(HCI_Command):
3374
+ '''
3375
+ See Bluetooth spec @ 7.6.1 Read Loopback Mode Command
3376
+ '''
3377
+
3378
+
3379
+ # -----------------------------------------------------------------------------
3380
+ @HCI_Command.command([('loopback_mode', 1)])
3381
+ class HCI_Write_Loopback_Mode_Command(HCI_Command):
3382
+ '''
3383
+ See Bluetooth spec @ 7.6.2 Write Loopback Mode Command
3384
+ '''
3385
+
3386
+
3355
3387
  # -----------------------------------------------------------------------------
3356
3388
  @HCI_Command.command([('le_event_mask', 8)])
3357
3389
  class HCI_LE_Set_Event_Mask_Command(HCI_Command):
@@ -4733,7 +4765,11 @@ class HCI_Event(HCI_Packet):
4733
4765
  HCI_Object.init_from_bytes(self, parameters, 0, fields)
4734
4766
  return self
4735
4767
 
4736
- def __init__(self, event_code, parameters=None, **kwargs):
4768
+ def __init__(self, event_code=-1, parameters=None, **kwargs):
4769
+ # Since the legacy implementation relies on an __init__ injector, typing always
4770
+ # complains that positional argument event_code is not passed, so here sets a
4771
+ # default value to allow building derived HCI_Event without event_code.
4772
+ assert event_code != -1
4737
4773
  super().__init__(HCI_Event.event_name(event_code))
4738
4774
  if (fields := getattr(self, 'fields', None)) and kwargs:
4739
4775
  HCI_Object.init_from_fields(self, fields, kwargs)
bumble/l2cap.py CHANGED
@@ -149,10 +149,11 @@ L2CAP_INVALID_CID_IN_REQUEST_REASON = 0x0002
149
149
 
150
150
  L2CAP_LE_CREDIT_BASED_CONNECTION_MAX_CREDITS = 65535
151
151
  L2CAP_LE_CREDIT_BASED_CONNECTION_MIN_MTU = 23
152
+ L2CAP_LE_CREDIT_BASED_CONNECTION_MAX_MTU = 65535
152
153
  L2CAP_LE_CREDIT_BASED_CONNECTION_MIN_MPS = 23
153
154
  L2CAP_LE_CREDIT_BASED_CONNECTION_MAX_MPS = 65533
154
155
  L2CAP_LE_CREDIT_BASED_CONNECTION_DEFAULT_MTU = 2048
155
- L2CAP_LE_CREDIT_BASED_CONNECTION_DEFAULT_MPS = 2046
156
+ L2CAP_LE_CREDIT_BASED_CONNECTION_DEFAULT_MPS = 2048
156
157
  L2CAP_LE_CREDIT_BASED_CONNECTION_DEFAULT_INITIAL_CREDITS = 256
157
158
 
158
159
  L2CAP_MAXIMUM_TRANSMISSION_UNIT_CONFIGURATION_OPTION_TYPE = 0x01
@@ -188,8 +189,11 @@ class LeCreditBasedChannelSpec:
188
189
  or self.max_credits > L2CAP_LE_CREDIT_BASED_CONNECTION_MAX_CREDITS
189
190
  ):
190
191
  raise ValueError('max credits out of range')
191
- if self.mtu < L2CAP_LE_CREDIT_BASED_CONNECTION_MIN_MTU:
192
- raise ValueError('MTU too small')
192
+ if (
193
+ self.mtu < L2CAP_LE_CREDIT_BASED_CONNECTION_MIN_MTU
194
+ or self.mtu > L2CAP_LE_CREDIT_BASED_CONNECTION_MAX_MTU
195
+ ):
196
+ raise ValueError('MTU out of range')
193
197
  if (
194
198
  self.mps < L2CAP_LE_CREDIT_BASED_CONNECTION_MIN_MPS
195
199
  or self.mps > L2CAP_LE_CREDIT_BASED_CONNECTION_MAX_MPS
@@ -1644,12 +1648,13 @@ class ChannelManager:
1644
1648
 
1645
1649
  def send_pdu(self, connection, cid: int, pdu: Union[SupportsBytes, bytes]) -> None:
1646
1650
  pdu_str = pdu.hex() if isinstance(pdu, bytes) else str(pdu)
1651
+ pdu_bytes = bytes(pdu)
1647
1652
  logger.debug(
1648
1653
  f'{color(">>> Sending L2CAP PDU", "blue")} '
1649
1654
  f'on connection [0x{connection.handle:04X}] (CID={cid}) '
1650
- f'{connection.peer_address}: {pdu_str}'
1655
+ f'{connection.peer_address}: {len(pdu_bytes)} bytes, {pdu_str}'
1651
1656
  )
1652
- self.host.send_l2cap_pdu(connection.handle, cid, bytes(pdu))
1657
+ self.host.send_l2cap_pdu(connection.handle, cid, pdu_bytes)
1653
1658
 
1654
1659
  def on_pdu(self, connection: Connection, cid: int, pdu: bytes) -> None:
1655
1660
  if cid in (L2CAP_SIGNALING_CID, L2CAP_LE_SIGNALING_CID):
bumble/link.py CHANGED
@@ -26,9 +26,13 @@ from bumble.hci import (
26
26
  HCI_SUCCESS,
27
27
  HCI_CONNECTION_ACCEPT_TIMEOUT_ERROR,
28
28
  HCI_CONNECTION_TIMEOUT_ERROR,
29
+ HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
29
30
  HCI_PAGE_TIMEOUT_ERROR,
30
31
  HCI_Connection_Complete_Event,
31
32
  )
33
+ from bumble import controller
34
+
35
+ from typing import Optional, Set
32
36
 
33
37
  # -----------------------------------------------------------------------------
34
38
  # Logging
@@ -57,6 +61,8 @@ class LocalLink:
57
61
  Link bus for controllers to communicate with each other
58
62
  '''
59
63
 
64
+ controllers: Set[controller.Controller]
65
+
60
66
  def __init__(self):
61
67
  self.controllers = set()
62
68
  self.pending_connection = None
@@ -79,7 +85,9 @@ class LocalLink:
79
85
  return controller
80
86
  return None
81
87
 
82
- def find_classic_controller(self, address):
88
+ def find_classic_controller(
89
+ self, address: Address
90
+ ) -> Optional[controller.Controller]:
83
91
  for controller in self.controllers:
84
92
  if controller.public_address == address:
85
93
  return controller
@@ -271,6 +279,52 @@ class LocalLink:
271
279
  initiator_controller.public_address, int(not (initiator_new_role))
272
280
  )
273
281
 
282
+ def classic_sco_connect(
283
+ self,
284
+ initiator_controller: controller.Controller,
285
+ responder_address: Address,
286
+ link_type: int,
287
+ ):
288
+ logger.debug(
289
+ f'[Classic] {initiator_controller.public_address} connects SCO to {responder_address}'
290
+ )
291
+ responder_controller = self.find_classic_controller(responder_address)
292
+ # Initiator controller should handle it.
293
+ assert responder_controller
294
+
295
+ responder_controller.on_classic_connection_request(
296
+ initiator_controller.public_address,
297
+ link_type,
298
+ )
299
+
300
+ def classic_accept_sco_connection(
301
+ self,
302
+ responder_controller: controller.Controller,
303
+ initiator_address: Address,
304
+ link_type: int,
305
+ ):
306
+ logger.debug(
307
+ f'[Classic] {responder_controller.public_address} accepts to connect SCO {initiator_address}'
308
+ )
309
+ initiator_controller = self.find_classic_controller(initiator_address)
310
+ if initiator_controller is None:
311
+ responder_controller.on_classic_sco_connection_complete(
312
+ responder_controller.public_address,
313
+ HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
314
+ link_type,
315
+ )
316
+ return
317
+
318
+ async def task():
319
+ initiator_controller.on_classic_sco_connection_complete(
320
+ responder_controller.public_address, HCI_SUCCESS, link_type
321
+ )
322
+
323
+ asyncio.create_task(task())
324
+ responder_controller.on_classic_sco_connection_complete(
325
+ initiator_controller.public_address, HCI_SUCCESS, link_type
326
+ )
327
+
274
328
 
275
329
  # -----------------------------------------------------------------------------
276
330
  class RemoteLink:
bumble/profiles/csip.py CHANGED
@@ -19,7 +19,7 @@
19
19
  from __future__ import annotations
20
20
  import enum
21
21
  import struct
22
- from typing import Optional
22
+ from typing import Optional, Tuple
23
23
 
24
24
  from bumble import core
25
25
  from bumble import crypto
@@ -31,6 +31,9 @@ from bumble import gatt_client
31
31
  # -----------------------------------------------------------------------------
32
32
  # Constants
33
33
  # -----------------------------------------------------------------------------
34
+ SET_IDENTITY_RESOLVING_KEY_LENGTH = 16
35
+
36
+
34
37
  class SirkType(enum.IntEnum):
35
38
  '''Coordinated Set Identification Service - 5.1 Set Identity Resolving Key.'''
36
39
 
@@ -66,6 +69,10 @@ def k1(n: bytes, salt: bytes, p: bytes) -> bytes:
66
69
  def sef(k: bytes, r: bytes) -> bytes:
67
70
  '''
68
71
  Coordinated Set Identification Service - 4.5 SIRK encryption function sef.
72
+
73
+ SIRK decryption function sdf shares the same algorithm. The only difference is that argument r is:
74
+ * Plaintext in encryption
75
+ * Cipher in decryption
69
76
  '''
70
77
  return crypto.xor(k1(k, s1(b'SIRKenc'[::-1]), b'csis'[::-1]), r)
71
78
 
@@ -105,6 +112,11 @@ class CoordinatedSetIdentificationService(gatt.TemplateService):
105
112
  set_member_lock: Optional[MemberLock] = None,
106
113
  set_member_rank: Optional[int] = None,
107
114
  ) -> None:
115
+ if len(set_identity_resolving_key) != SET_IDENTITY_RESOLVING_KEY_LENGTH:
116
+ raise ValueError(
117
+ f'Invalid SIRK length {len(set_identity_resolving_key)}, expected {SET_IDENTITY_RESOLVING_KEY_LENGTH}'
118
+ )
119
+
108
120
  characteristics = []
109
121
 
110
122
  self.set_identity_resolving_key = set_identity_resolving_key
@@ -113,7 +125,7 @@ class CoordinatedSetIdentificationService(gatt.TemplateService):
113
125
  uuid=gatt.GATT_SET_IDENTITY_RESOLVING_KEY_CHARACTERISTIC,
114
126
  properties=gatt.Characteristic.Properties.READ
115
127
  | gatt.Characteristic.Properties.NOTIFY,
116
- permissions=gatt.Characteristic.Permissions.READABLE,
128
+ permissions=gatt.Characteristic.Permissions.READ_REQUIRES_ENCRYPTION,
117
129
  value=gatt.CharacteristicValue(read=self.on_sirk_read),
118
130
  )
119
131
  characteristics.append(self.set_identity_resolving_key_characteristic)
@@ -123,7 +135,7 @@ class CoordinatedSetIdentificationService(gatt.TemplateService):
123
135
  uuid=gatt.GATT_COORDINATED_SET_SIZE_CHARACTERISTIC,
124
136
  properties=gatt.Characteristic.Properties.READ
125
137
  | gatt.Characteristic.Properties.NOTIFY,
126
- permissions=gatt.Characteristic.Permissions.READABLE,
138
+ permissions=gatt.Characteristic.Permissions.READ_REQUIRES_ENCRYPTION,
127
139
  value=struct.pack('B', coordinated_set_size),
128
140
  )
129
141
  characteristics.append(self.coordinated_set_size_characteristic)
@@ -134,7 +146,7 @@ class CoordinatedSetIdentificationService(gatt.TemplateService):
134
146
  properties=gatt.Characteristic.Properties.READ
135
147
  | gatt.Characteristic.Properties.NOTIFY
136
148
  | gatt.Characteristic.Properties.WRITE,
137
- permissions=gatt.Characteristic.Permissions.READABLE
149
+ permissions=gatt.Characteristic.Permissions.READ_REQUIRES_ENCRYPTION
138
150
  | gatt.Characteristic.Permissions.WRITEABLE,
139
151
  value=struct.pack('B', set_member_lock),
140
152
  )
@@ -145,18 +157,32 @@ class CoordinatedSetIdentificationService(gatt.TemplateService):
145
157
  uuid=gatt.GATT_SET_MEMBER_RANK_CHARACTERISTIC,
146
158
  properties=gatt.Characteristic.Properties.READ
147
159
  | gatt.Characteristic.Properties.NOTIFY,
148
- permissions=gatt.Characteristic.Permissions.READABLE,
160
+ permissions=gatt.Characteristic.Permissions.READ_REQUIRES_ENCRYPTION,
149
161
  value=struct.pack('B', set_member_rank),
150
162
  )
151
163
  characteristics.append(self.set_member_rank_characteristic)
152
164
 
153
165
  super().__init__(characteristics)
154
166
 
155
- def on_sirk_read(self, _connection: Optional[device.Connection]) -> bytes:
167
+ async def on_sirk_read(self, connection: Optional[device.Connection]) -> bytes:
156
168
  if self.set_identity_resolving_key_type == SirkType.PLAINTEXT:
157
- return bytes([SirkType.PLAINTEXT]) + self.set_identity_resolving_key
169
+ sirk_bytes = self.set_identity_resolving_key
158
170
  else:
159
- raise NotImplementedError('TODO: Pending async Characteristic read.')
171
+ assert connection
172
+
173
+ if connection.transport == core.BT_LE_TRANSPORT:
174
+ key = await connection.device.get_long_term_key(
175
+ connection_handle=connection.handle, rand=b'', ediv=0
176
+ )
177
+ else:
178
+ key = await connection.device.get_link_key(connection.peer_address)
179
+
180
+ if not key:
181
+ raise RuntimeError('LTK or LinkKey is not present')
182
+
183
+ sirk_bytes = sef(key, self.set_identity_resolving_key)
184
+
185
+ return bytes([self.set_identity_resolving_key_type]) + sirk_bytes
160
186
 
161
187
  def get_advertising_data(self) -> bytes:
162
188
  return bytes(
@@ -203,3 +229,29 @@ class CoordinatedSetIdentificationProxy(gatt_client.ProfileServiceProxy):
203
229
  gatt.GATT_SET_MEMBER_RANK_CHARACTERISTIC
204
230
  ):
205
231
  self.set_member_rank = characteristics[0]
232
+
233
+ async def read_set_identity_resolving_key(self) -> Tuple[SirkType, bytes]:
234
+ '''Reads SIRK and decrypts if encrypted.'''
235
+ response = await self.set_identity_resolving_key.read_value()
236
+ if len(response) != SET_IDENTITY_RESOLVING_KEY_LENGTH + 1:
237
+ raise RuntimeError('Invalid SIRK value')
238
+
239
+ sirk_type = SirkType(response[0])
240
+ if sirk_type == SirkType.PLAINTEXT:
241
+ sirk = response[1:]
242
+ else:
243
+ connection = self.service_proxy.client.connection
244
+ device = connection.device
245
+ if connection.transport == core.BT_LE_TRANSPORT:
246
+ key = await device.get_long_term_key(
247
+ connection_handle=connection.handle, rand=b'', ediv=0
248
+ )
249
+ else:
250
+ key = await device.get_link_key(connection.peer_address)
251
+
252
+ if not key:
253
+ raise RuntimeError('LTK or LinkKey is not present')
254
+
255
+ sirk = sef(key, response[1:])
256
+
257
+ return (sirk_type, sirk)
bumble/rfcomm.py CHANGED
@@ -454,6 +454,8 @@ class DLC(EventEmitter):
454
454
  self.c_r = 1 if self.role == Multiplexer.Role.INITIATOR else 0
455
455
  self.sink = None
456
456
  self.connection_result = None
457
+ self.drained = asyncio.Event()
458
+ self.drained.set()
457
459
 
458
460
  # Compute the MTU
459
461
  max_overhead = 4 + 1 # header with 2-byte length + fcs
@@ -633,6 +635,8 @@ class DLC(EventEmitter):
633
635
  )
634
636
 
635
637
  rx_credits_needed = 0
638
+ if not self.tx_buffer:
639
+ self.drained.set()
636
640
 
637
641
  # Stream protocol
638
642
  def write(self, data: Union[bytes, str]) -> None:
@@ -645,11 +649,11 @@ class DLC(EventEmitter):
645
649
  raise ValueError('write only accept bytes or strings')
646
650
 
647
651
  self.tx_buffer += data
652
+ self.drained.clear()
648
653
  self.process_tx()
649
654
 
650
- def drain(self) -> None:
651
- # TODO
652
- pass
655
+ async def drain(self) -> None:
656
+ await self.drained.wait()
653
657
 
654
658
  def __str__(self) -> str:
655
659
  return f'DLC(dlci={self.dlci},state={self.state.name})'
@@ -198,12 +198,13 @@ async def open_transport_or_link(name: str) -> Transport:
198
198
 
199
199
  """
200
200
  if name.startswith('link-relay:'):
201
+ logger.warning('Link Relay has been deprecated.')
201
202
  from ..controller import Controller
202
203
  from ..link import RemoteLink # lazy import
203
204
 
204
205
  link = RemoteLink(name[11:])
205
206
  await link.wait_until_connected()
206
- controller = Controller('remote', link=link)
207
+ controller = Controller('remote', link=link) # type:ignore[arg-type]
207
208
 
208
209
  class LinkTransport(Transport):
209
210
  async def close(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bumble
3
- Version: 0.0.181
3
+ Version: 0.0.182
4
4
  Summary: Bluetooth Stack for Apps, Emulation, Test and Experimentation
5
5
  Home-page: https://github.com/google/bumble
6
6
  Author: Google
@@ -1,5 +1,5 @@
1
1
  bumble/__init__.py,sha256=Q8jkz6rgl95IMAeInQVt_2GLoJl3DcEP2cxtrQ-ho5c,110
2
- bumble/_version.py,sha256=kEdx0bkEZGn_C1UTJUkEEzk1Q-ubIPoEpesXzdNR5jw,415
2
+ bumble/_version.py,sha256=jNNHSrRJTup4dBd5BRhfsjHh4m5-E9mCCGmW1eJZQnw,415
3
3
  bumble/a2dp.py,sha256=NqdmHIeEe3kThoHqdOgC3Wkywc6H7zqwGbjRYYFtNoQ,22321
4
4
  bumble/at.py,sha256=kdrcsx2C8Rg61EWESD2QHwpZntkXkRBJLrPn9auv9K8,2961
5
5
  bumble/att.py,sha256=_HrhlCl4CXZM9mmBLTCPq5v2OW9eZ0-H6cSu5_jG_5o,32365
@@ -8,41 +8,42 @@ bumble/bridge.py,sha256=T6es5oS1dy8QgkxQ8iOD-YcZ0SWOv8jaqC7TGxqodk4,3003
8
8
  bumble/codecs.py,sha256=Vc7FOo6d-6VCgDI0ibnLmX8vCZ4-jtX_-0vEUM-yOrI,15343
9
9
  bumble/colors.py,sha256=9H-qzGgMr-YoWdIFpcGPaiRvTvkCzz7FPIkpwqKyKug,3033
10
10
  bumble/company_ids.py,sha256=B68e2QPsDeRYP9jjbGs4GGDwEkGxcXGTsON_CHA0uuI,118528
11
- bumble/controller.py,sha256=Wd6TpcJJCvXaIw9Kf9D7FKc7xQYSm1xJS9usnCYsYDE,46131
11
+ bumble/controller.py,sha256=1Uvn1IkEIVkPOEMF8ed26SkiEBzmnH-PlCrE-WDFahE,49945
12
12
  bumble/core.py,sha256=HjRpUseyVsueNkZ-KhPPTf1vNkNnI02eNcaOe685V_0,52949
13
13
  bumble/crypto.py,sha256=L6z3dn9-dgKYRtOM6O3F6n6Ju4PwTM3LAFJtCg_ie78,9382
14
14
  bumble/decoder.py,sha256=N9nMvuVhuwpnfw7EDVuNe9uYY6B6c3RY2dh8RhRPC1U,9608
15
- bumble/device.py,sha256=jKIJ_V-xMV5R-FTHY18r1PSemuWd9oZo2CKKDxM3swU,153640
15
+ bumble/device.py,sha256=OmcjQS-z7xmJ55zgq20-0bUngAQKhdYJs4WJ-XdlS_I,154100
16
16
  bumble/gap.py,sha256=axlOZIv99357Ehq2vMokeioU85z81qdQvplGn0pF70Q,2137
17
17
  bumble/gatt.py,sha256=L3RLHiyAKMIZHLfkbH09V9yTNNKymacDtpvwmSoRQRY,38405
18
18
  bumble/gatt_client.py,sha256=JuyFUHEc5xd2astr2XCZrTiAla2FoDkKe4lH1oSQOPA,42551
19
19
  bumble/gatt_server.py,sha256=Ebu-VBIPUPZiwHl207ncuC-tCF7oUkR4B8BlE0GruY8,37112
20
- bumble/hci.py,sha256=gotHTh9hpcVDKztCe-SE5wdV2LosHVN94mNH5AhK-EI,237190
20
+ bumble/hci.py,sha256=0pDWOQIQQ1e8WSnfKsFCOg1xXmEQtHQHmrLPBk6nKyo,238361
21
21
  bumble/helpers.py,sha256=pxSNAuLnMhU8eg3AdqUNoCyA8Q5-GZ1_SdgFS2nOp_M,10412
22
22
  bumble/hfp.py,sha256=8b6zR4YhGl9Rc2vxL9AFAYZ2kyxe5SaLWUUXHDpeEoU,38487
23
23
  bumble/hid.py,sha256=KiY6v5G8qAQoP_IzjiY68b7vF9izpwJyGovUHRH3AmA,20584
24
24
  bumble/host.py,sha256=dUoy421swHti2d0rNPR61_bsSkPqanHRYS7wHwsPswU,39154
25
25
  bumble/keys.py,sha256=_ibaJ4CxM5zyxnTp7wnihIQSsEAEkCiPxx9qHsGA04Q,12601
26
- bumble/l2cap.py,sha256=yNfS76khPHbhabfCWP-iRh9Po3GGzv3tk_R0ESBclxg,80752
27
- bumble/link.py,sha256=dvb3fdmV8689A4rLhFVHHKMR3u4wQbUapFi-GeheK0M,20220
26
+ bumble/l2cap.py,sha256=Uh9qSTzR_xQA7zb_oz85AmNWmhqV3xXQYumNeuoPahQ,80965
27
+ bumble/link.py,sha256=PaQwHhKgZ80IMtkcZFXzH1bVotvYk3QXMBf4d7UU90k,22075
28
28
  bumble/pairing.py,sha256=tgPUba6xNxMi-2plm3xfRlzHq-uPRNZEIGWaN0qNGCs,9853
29
29
  bumble/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- bumble/rfcomm.py,sha256=9q0c8ngZV-F0OzC5CWdocHfj4nsw1pk9qdey9jycSyY,33807
30
+ bumble/rfcomm.py,sha256=9uTvEDz8fY-xqUHV7p4WzZoRhvz9W0rE9n966jgnjj0,33984
31
31
  bumble/sdp.py,sha256=D5pG7cuAoFBygdmxExyuRhU4aVsvkWB9WQVnONCU-L0,44854
32
32
  bumble/smp.py,sha256=NmDWTxXJIzVnwFqG3M2OduduP_ryGh5y886RCigqPvs,76235
33
33
  bumble/snoop.py,sha256=_QfF36eylBW6Snd-_KYOwKaGiM8i_Ed-B5XoFIPt3Dg,5631
34
34
  bumble/utils.py,sha256=RXx5-6YkUwrCGQRChy80bJ2ifZ2frdXZCcMXHu_pnqI,14083
35
35
  bumble/apps/README.md,sha256=XTwjRAY-EJWDXpl1V8K3Mw8B7kIqzUIUizRjVBVhoIE,1769
36
36
  bumble/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- bumble/apps/bench.py,sha256=YQT-Ord7o7_D8R2EcJTJwr50EzEuV1ezAvRGJijBapM,45735
37
+ bumble/apps/bench.py,sha256=HCMY9IQSvyfEQsNUDWWw_51iMgwZ7wE_pMdTAeHno2E,52444
38
38
  bumble/apps/ble_rpa_tool.py,sha256=ZQtsbfnLPd5qUAkEBPpNgJLRynBBc7q_9cDHKUW2SQ0,1701
39
39
  bumble/apps/console.py,sha256=rVR2jmP6Yd76B4zzGPYnpJFtgeYgq19CL6DMSe2-A1M,46093
40
- bumble/apps/controller_info.py,sha256=K9Yci0cJvVviUQdNLOKFGAgSDurv4oQddHdYGcTI3vk,8410
40
+ bumble/apps/controller_info.py,sha256=bgbyrHZFvrTBKzKfQkGcJvoSPsSaVv7xOzXmb42sHv8,9302
41
+ bumble/apps/controller_loopback.py,sha256=eBcutzSDT8bp8348b2cxa4LCjZPRqWm0bYTq6yPwg5I,7073
41
42
  bumble/apps/controllers.py,sha256=R6XJ1XpyuXlyqSCmI7PromVIcoYTcYfpmO-TqTYXnUI,2326
42
43
  bumble/apps/gatt_dump.py,sha256=-dCvCgjuHAp0h1zxm-gmqB4lVlSdas1Kp4cpzzx4gGw,4245
43
44
  bumble/apps/gg_bridge.py,sha256=JdW5QT6xN9c2XDDJoHDRo5W3N_RdVkCtTmlcOsJhlx8,14693
44
45
  bumble/apps/hci_bridge.py,sha256=KISv352tKnsQsoxjkDiCQbMFmhnPWdnug5wSFAAXxEs,4033
45
- bumble/apps/l2cap_bridge.py,sha256=9yjpznRivCtwcO1ivLmEvOAe3fdqyJZLxN82uwZqLiQ,12844
46
+ bumble/apps/l2cap_bridge.py,sha256=524VgEmgCP4g7T0UdgmsePmNVhDFRJECeaZ_uzKsbco,13062
46
47
  bumble/apps/pair.py,sha256=COU2D7YAIn4lo5iuM0ClObA1zZqQCdrXOcnsiCm0YlQ,17529
47
48
  bumble/apps/pandora_server.py,sha256=5qaoLCpcZE2KsGO21-7t6Vg4dBjBWbnyOQXwrLhxkuE,1397
48
49
  bumble/apps/scan.py,sha256=_fMG_1j1HZQ_8SrJ0ZOxJaWB1OR4mKBaZuQMgm8viYI,7439
@@ -73,7 +74,7 @@ bumble/profiles/asha_service.py,sha256=J4i5jkJciZWMtTWJ1zGJkEx65DlAEIADqjCRYf_CW
73
74
  bumble/profiles/bap.py,sha256=GJOn1t7ZGcm-woFnI4JFx4I4Z_rnv5GQIB4dnrwULlY,44900
74
75
  bumble/profiles/battery_service.py,sha256=w-uF4jLoDozJOoykimb2RkrKjVyCke6ts2-h-F1PYyc,2292
75
76
  bumble/profiles/cap.py,sha256=6gH7oOnUKjOggMPuB7rtbwj0AneoNmnWzQ_iR3io8e0,1945
76
- bumble/profiles/csip.py,sha256=cnbZN4UuxheBFtWDe_42U7mzp9XWJ_WV8mVlTNbIGZk,8070
77
+ bumble/profiles/csip.py,sha256=wzSpNRCOMWtKw2Yd9OTAzPoFDoQWG-KYwWdA6sUkwiI,10102
77
78
  bumble/profiles/device_information_service.py,sha256=H1Db4BAOnsC-rRtfpoAIsDETYT4F9yM_WgByn_3LfRQ,5658
78
79
  bumble/profiles/heart_rate_service.py,sha256=7V2LGcWLp6RurjWxsVgMWr3wPDt5aS9qjNxTbHcOK6o,8575
79
80
  bumble/profiles/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -81,7 +82,7 @@ bumble/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
82
  bumble/tools/generate_company_id_list.py,sha256=ysbPb3zmxKFBiSQ_MBG2r15-sqR5P_GWT6i0YUTTXOM,1736
82
83
  bumble/tools/rtk_fw_download.py,sha256=kTxR9UaNiD8VtzWVAVxsCx5c_tkfz9OKe-vxdlfKQRY,5454
83
84
  bumble/tools/rtk_util.py,sha256=TwZhupHQrQYsYHLdRGyzXKd24pwCk8kkzqK1Rj2guco,5087
84
- bumble/transport/__init__.py,sha256=_gd1PnGJsRyojkfS2ZpnW3RnyKjuo9veN7tpsgwd2aw,6769
85
+ bumble/transport/__init__.py,sha256=DQe4KOqGOAu7UEDCuysGJXIhWka53Bo13vLt0W-dR_I,6852
85
86
  bumble/transport/android_emulator.py,sha256=eH8H1aB7MvQ8lpdwVG6SGKg5uwCRb_aPJk8pPwoTXSY,4321
86
87
  bumble/transport/android_netsim.py,sha256=SVh-IUZ2bhcIESZFGzOsofybsi4H0qoBRwBieeqUINE,16215
87
88
  bumble/transport/common.py,sha256=ZrW-CuEqf7xNcCK29gvC9azOLgPA7IqKgoyfKQxdsLo,15654
@@ -131,9 +132,9 @@ bumble/vendor/android/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
131
132
  bumble/vendor/android/hci.py,sha256=GZrkhaWmcMt1JpnRhv0NoySGkf2H4lNUV2f_omRZW0I,10741
132
133
  bumble/vendor/zephyr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
133
134
  bumble/vendor/zephyr/hci.py,sha256=d83bC0TvT947eN4roFjLkQefWtHOoNsr4xib2ctSkvA,3195
134
- bumble-0.0.181.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
135
- bumble-0.0.181.dist-info/METADATA,sha256=VEwA-oV3z1wx7OJDfOAuV9XVmRsMxhOON11AdcwjKW8,5681
136
- bumble-0.0.181.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
137
- bumble-0.0.181.dist-info/entry_points.txt,sha256=96i3Nmc2zjWeSWTYH2x3lPV7nH1KvOK2jrF0spSjpYc,817
138
- bumble-0.0.181.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
139
- bumble-0.0.181.dist-info/RECORD,,
135
+ bumble-0.0.182.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
136
+ bumble-0.0.182.dist-info/METADATA,sha256=qwhQQGzsmCfpLay30Xzd7dUREps21OAGPhcgkfk-K3U,5681
137
+ bumble-0.0.182.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
138
+ bumble-0.0.182.dist-info/entry_points.txt,sha256=96i3Nmc2zjWeSWTYH2x3lPV7nH1KvOK2jrF0spSjpYc,817
139
+ bumble-0.0.182.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
140
+ bumble-0.0.182.dist-info/RECORD,,