bumble 0.0.211__py3-none-any.whl → 0.0.213__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 (95) hide show
  1. bumble/_version.py +2 -2
  2. bumble/a2dp.py +6 -0
  3. bumble/apps/README.md +0 -3
  4. bumble/apps/auracast.py +11 -9
  5. bumble/apps/bench.py +482 -31
  6. bumble/apps/console.py +5 -5
  7. bumble/apps/controller_info.py +47 -10
  8. bumble/apps/controller_loopback.py +7 -3
  9. bumble/apps/controllers.py +2 -2
  10. bumble/apps/device_info.py +2 -2
  11. bumble/apps/gatt_dump.py +2 -2
  12. bumble/apps/gg_bridge.py +2 -2
  13. bumble/apps/hci_bridge.py +2 -2
  14. bumble/apps/l2cap_bridge.py +2 -2
  15. bumble/apps/lea_unicast/app.py +6 -1
  16. bumble/apps/pair.py +204 -43
  17. bumble/apps/pandora_server.py +2 -2
  18. bumble/apps/rfcomm_bridge.py +1 -1
  19. bumble/apps/scan.py +2 -2
  20. bumble/apps/show.py +4 -2
  21. bumble/apps/speaker/speaker.html +1 -0
  22. bumble/apps/speaker/speaker.js +113 -62
  23. bumble/apps/speaker/speaker.py +126 -18
  24. bumble/at.py +4 -4
  25. bumble/att.py +15 -18
  26. bumble/avc.py +7 -7
  27. bumble/avctp.py +5 -5
  28. bumble/avdtp.py +138 -88
  29. bumble/avrcp.py +52 -58
  30. bumble/colors.py +2 -2
  31. bumble/controller.py +84 -23
  32. bumble/core.py +13 -7
  33. bumble/{crypto.py → crypto/__init__.py} +11 -95
  34. bumble/crypto/builtin.py +652 -0
  35. bumble/crypto/cryptography.py +84 -0
  36. bumble/device.py +688 -345
  37. bumble/drivers/__init__.py +2 -2
  38. bumble/drivers/common.py +0 -2
  39. bumble/drivers/intel.py +40 -40
  40. bumble/drivers/rtk.py +28 -35
  41. bumble/gatt.py +7 -9
  42. bumble/gatt_adapters.py +4 -5
  43. bumble/gatt_client.py +31 -34
  44. bumble/gatt_server.py +15 -17
  45. bumble/hci.py +2635 -2878
  46. bumble/helpers.py +4 -5
  47. bumble/hfp.py +76 -57
  48. bumble/hid.py +24 -12
  49. bumble/host.py +117 -34
  50. bumble/keys.py +68 -52
  51. bumble/l2cap.py +329 -403
  52. bumble/link.py +6 -270
  53. bumble/pairing.py +23 -20
  54. bumble/pandora/__init__.py +1 -1
  55. bumble/pandora/config.py +2 -2
  56. bumble/pandora/device.py +6 -6
  57. bumble/pandora/host.py +38 -39
  58. bumble/pandora/l2cap.py +4 -4
  59. bumble/pandora/security.py +73 -57
  60. bumble/pandora/utils.py +3 -3
  61. bumble/profiles/aics.py +3 -5
  62. bumble/profiles/ancs.py +3 -1
  63. bumble/profiles/ascs.py +143 -136
  64. bumble/profiles/asha.py +13 -8
  65. bumble/profiles/bap.py +3 -4
  66. bumble/profiles/csip.py +3 -5
  67. bumble/profiles/device_information_service.py +2 -2
  68. bumble/profiles/gap.py +2 -2
  69. bumble/profiles/gatt_service.py +1 -3
  70. bumble/profiles/hap.py +42 -58
  71. bumble/profiles/le_audio.py +4 -4
  72. bumble/profiles/mcp.py +16 -13
  73. bumble/profiles/vcs.py +8 -10
  74. bumble/profiles/vocs.py +6 -9
  75. bumble/rfcomm.py +27 -18
  76. bumble/rtp.py +1 -2
  77. bumble/sdp.py +2 -2
  78. bumble/smp.py +71 -69
  79. bumble/tools/rtk_util.py +2 -2
  80. bumble/transport/__init__.py +2 -16
  81. bumble/transport/android_netsim.py +5 -5
  82. bumble/transport/common.py +4 -4
  83. bumble/transport/pyusb.py +2 -2
  84. bumble/utils.py +2 -5
  85. bumble/vendor/android/hci.py +118 -200
  86. bumble/vendor/zephyr/hci.py +32 -27
  87. {bumble-0.0.211.dist-info → bumble-0.0.213.dist-info}/METADATA +5 -5
  88. {bumble-0.0.211.dist-info → bumble-0.0.213.dist-info}/RECORD +92 -93
  89. {bumble-0.0.211.dist-info → bumble-0.0.213.dist-info}/WHEEL +1 -1
  90. {bumble-0.0.211.dist-info → bumble-0.0.213.dist-info}/entry_points.txt +0 -1
  91. bumble/apps/link_relay/__init__.py +0 -0
  92. bumble/apps/link_relay/link_relay.py +0 -289
  93. bumble/apps/link_relay/logging.yml +0 -21
  94. {bumble-0.0.211.dist-info → bumble-0.0.213.dist-info}/licenses/LICENSE +0 -0
  95. {bumble-0.0.211.dist-info → bumble-0.0.213.dist-info}/top_level.txt +0 -0
bumble/apps/console.py CHANGED
@@ -55,7 +55,7 @@ from prompt_toolkit.layout import (
55
55
  from bumble import __version__
56
56
  import bumble.core
57
57
  from bumble import colors
58
- from bumble.core import UUID, AdvertisingData, PhysicalTransport
58
+ from bumble.core import UUID, AdvertisingData
59
59
  from bumble.device import (
60
60
  ConnectionParametersPreferences,
61
61
  ConnectionPHY,
@@ -64,7 +64,7 @@ from bumble.device import (
64
64
  Peer,
65
65
  )
66
66
  from bumble.utils import AsyncRunner
67
- from bumble.transport import open_transport_or_link
67
+ from bumble.transport import open_transport
68
68
  from bumble.gatt import Characteristic, Service, CharacteristicDeclaration, Descriptor
69
69
  from bumble.gatt_client import CharacteristicProxy
70
70
  from bumble.hci import (
@@ -291,7 +291,7 @@ class ConsoleApp:
291
291
  async def run_async(self, device_config, transport):
292
292
  rssi_monitoring_task = asyncio.create_task(self.rssi_monitor_loop())
293
293
 
294
- async with await open_transport_or_link(transport) as (hci_source, hci_sink):
294
+ async with await open_transport(transport) as (hci_source, hci_sink):
295
295
  if device_config:
296
296
  self.device = Device.from_config_file_with_hci(
297
297
  device_config, hci_source, hci_sink
@@ -335,9 +335,9 @@ class ConsoleApp:
335
335
  elif self.connected_peer:
336
336
  connection = self.connected_peer.connection
337
337
  connection_parameters = (
338
- f'{connection.parameters.connection_interval}/'
338
+ f'{connection.parameters.connection_interval:.2f}/'
339
339
  f'{connection.parameters.peripheral_latency}/'
340
- f'{connection.parameters.supervision_timeout}'
340
+ f'{connection.parameters.supervision_timeout:.2f}'
341
341
  )
342
342
  if self.connection_phy is not None:
343
343
  phy_state = (
@@ -58,7 +58,7 @@ from bumble.hci import (
58
58
  HCI_Read_Local_Version_Information_Command,
59
59
  )
60
60
  from bumble.host import Host
61
- from bumble.transport import open_transport_or_link
61
+ from bumble.transport import open_transport
62
62
 
63
63
 
64
64
  # -----------------------------------------------------------------------------
@@ -242,28 +242,43 @@ async def get_codecs_info(host: Host) -> None:
242
242
 
243
243
 
244
244
  # -----------------------------------------------------------------------------
245
- async def async_main(latency_probes, transport):
245
+ async def async_main(
246
+ latency_probes, latency_probe_interval, latency_probe_command, transport
247
+ ):
246
248
  print('<<< connecting to HCI...')
247
- async with await open_transport_or_link(transport) as (hci_source, hci_sink):
249
+ async with await open_transport(transport) as (hci_source, hci_sink):
248
250
  print('<<< connected')
249
251
 
250
252
  host = Host(hci_source, hci_sink)
251
253
  await host.reset()
252
254
 
253
255
  # Measure the latency if requested
256
+ # (we add an extra probe at the start, that we ignore, just to ensure that
257
+ # the transport is primed)
254
258
  latencies = []
255
259
  if latency_probes:
256
- for _ in range(latency_probes):
260
+ if latency_probe_command:
261
+ probe_hci_command = HCI_Command.from_bytes(
262
+ bytes.fromhex(latency_probe_command)
263
+ )
264
+ else:
265
+ probe_hci_command = HCI_Read_Local_Version_Information_Command()
266
+
267
+ for iteration in range(1 + latency_probes):
268
+ if latency_probe_interval:
269
+ await asyncio.sleep(latency_probe_interval / 1000)
257
270
  start = time.time()
258
- await host.send_command(HCI_Read_Local_Version_Information_Command())
259
- latencies.append(1000 * (time.time() - start))
271
+ await host.send_command(probe_hci_command)
272
+ if iteration:
273
+ latencies.append(1000 * (time.time() - start))
260
274
  print(
261
275
  color('HCI Command Latency:', 'yellow'),
262
276
  (
263
277
  f'min={min(latencies):.2f}, '
264
278
  f'max={max(latencies):.2f}, '
265
- f'average={sum(latencies)/len(latencies):.2f}'
279
+ f'average={sum(latencies)/len(latencies):.2f},'
266
280
  ),
281
+ [f'{latency:.4}' for latency in latencies],
267
282
  '\n',
268
283
  )
269
284
 
@@ -311,10 +326,32 @@ async def async_main(latency_probes, transport):
311
326
  type=int,
312
327
  help='Send N commands to measure HCI transport latency statistics',
313
328
  )
329
+ @click.option(
330
+ '--latency-probe-interval',
331
+ metavar='INTERVAL',
332
+ type=int,
333
+ help='Interval between latency probes (milliseconds)',
334
+ )
335
+ @click.option(
336
+ '--latency-probe-command',
337
+ metavar='COMMAND_HEX',
338
+ help=(
339
+ 'Probe command (HCI Command packet bytes, in hex. Use 0177FC00 for'
340
+ ' a loopback test with the HCI remote proxy app)'
341
+ ),
342
+ )
314
343
  @click.argument('transport')
315
- def main(latency_probes, transport):
316
- logging.basicConfig(level=os.environ.get('BUMBLE_LOGLEVEL', 'WARNING').upper())
317
- asyncio.run(async_main(latency_probes, transport))
344
+ def main(latency_probes, latency_probe_interval, latency_probe_command, transport):
345
+ logging.basicConfig(
346
+ level=os.environ.get('BUMBLE_LOGLEVEL', 'INFO').upper(),
347
+ format="[%(asctime)s.%(msecs)03d] %(levelname)s:%(name)s:%(message)s",
348
+ datefmt="%H:%M:%S",
349
+ )
350
+ asyncio.run(
351
+ async_main(
352
+ latency_probes, latency_probe_interval, latency_probe_command, transport
353
+ )
354
+ )
318
355
 
319
356
 
320
357
  # -----------------------------------------------------------------------------
@@ -29,7 +29,7 @@ from bumble.hci import (
29
29
  LoopbackMode,
30
30
  )
31
31
  from bumble.host import Host
32
- from bumble.transport import open_transport_or_link
32
+ from bumble.transport import open_transport
33
33
  import click
34
34
 
35
35
 
@@ -88,7 +88,7 @@ class Loopback:
88
88
  async def run(self):
89
89
  """Run a loopback throughput test"""
90
90
  print(color('>>> Connecting to HCI...', 'green'))
91
- async with await open_transport_or_link(self.transport) as (
91
+ async with await open_transport(self.transport) as (
92
92
  hci_source,
93
93
  hci_sink,
94
94
  ):
@@ -194,7 +194,11 @@ class Loopback:
194
194
  )
195
195
  @click.argument('transport')
196
196
  def main(packet_size, packet_count, transport):
197
- logging.basicConfig(level=os.environ.get('BUMBLE_LOGLEVEL', 'WARNING').upper())
197
+ logging.basicConfig(
198
+ level=os.environ.get('BUMBLE_LOGLEVEL', 'INFO').upper(),
199
+ format="[%(asctime)s.%(msecs)03d] %(levelname)s:%(name)s:%(message)s",
200
+ datefmt="%H:%M:%S",
201
+ )
198
202
 
199
203
  loopback = Loopback(packet_size, packet_count, transport)
200
204
  asyncio.run(loopback.run())
@@ -22,7 +22,7 @@ import os
22
22
 
23
23
  from bumble.controller import Controller
24
24
  from bumble.link import LocalLink
25
- from bumble.transport import open_transport_or_link
25
+ from bumble.transport import open_transport
26
26
 
27
27
 
28
28
  # -----------------------------------------------------------------------------
@@ -42,7 +42,7 @@ async def async_main():
42
42
  transports = []
43
43
  controllers = []
44
44
  for index, transport_name in enumerate(sys.argv[1:]):
45
- transport = await open_transport_or_link(transport_name)
45
+ transport = await open_transport(transport_name)
46
46
  transports.append(transport)
47
47
  controller = Controller(
48
48
  f'C{index}',
@@ -32,7 +32,7 @@ from bumble.profiles.gap import GenericAccessServiceProxy
32
32
  from bumble.profiles.pacs import PublishedAudioCapabilitiesServiceProxy
33
33
  from bumble.profiles.tmap import TelephonyAndMediaAudioServiceProxy
34
34
  from bumble.profiles.vcs import VolumeControlServiceProxy
35
- from bumble.transport import open_transport_or_link
35
+ from bumble.transport import open_transport
36
36
 
37
37
 
38
38
  # -----------------------------------------------------------------------------
@@ -215,7 +215,7 @@ async def show_device_info(peer, done: Optional[asyncio.Future]) -> None:
215
215
 
216
216
  # -----------------------------------------------------------------------------
217
217
  async def async_main(device_config, encrypt, transport, address_or_name):
218
- async with await open_transport_or_link(transport) as (hci_source, hci_sink):
218
+ async with await open_transport(transport) as (hci_source, hci_sink):
219
219
 
220
220
  # Create a device
221
221
  if device_config:
bumble/apps/gatt_dump.py CHANGED
@@ -24,7 +24,7 @@ import bumble.core
24
24
  from bumble.colors import color
25
25
  from bumble.device import Device, Peer
26
26
  from bumble.gatt import show_services
27
- from bumble.transport import open_transport_or_link
27
+ from bumble.transport import open_transport
28
28
 
29
29
 
30
30
  # -----------------------------------------------------------------------------
@@ -60,7 +60,7 @@ async def dump_gatt_db(peer, done):
60
60
 
61
61
  # -----------------------------------------------------------------------------
62
62
  async def async_main(device_config, encrypt, transport, address_or_name):
63
- async with await open_transport_or_link(transport) as (hci_source, hci_sink):
63
+ async with await open_transport(transport) as (hci_source, hci_sink):
64
64
 
65
65
  # Create a device
66
66
  if device_config:
bumble/apps/gg_bridge.py CHANGED
@@ -27,7 +27,7 @@ from bumble.device import Device, Peer
27
27
  from bumble.core import AdvertisingData
28
28
  from bumble.gatt import Service, Characteristic, CharacteristicValue
29
29
  from bumble.utils import AsyncRunner
30
- from bumble.transport import open_transport_or_link
30
+ from bumble.transport import open_transport
31
31
  from bumble.hci import HCI_Constant
32
32
 
33
33
 
@@ -325,7 +325,7 @@ async def run(
325
325
  receive_port,
326
326
  ):
327
327
  print('<<< connecting to HCI...')
328
- async with await open_transport_or_link(hci_transport) as (hci_source, hci_sink):
328
+ async with await open_transport(hci_transport) as (hci_source, hci_sink):
329
329
  print('<<< connected')
330
330
 
331
331
  # Instantiate a bridge object
bumble/apps/hci_bridge.py CHANGED
@@ -46,14 +46,14 @@ async def async_main():
46
46
  return
47
47
 
48
48
  print('>>> connecting to HCI...')
49
- async with await transport.open_transport_or_link(sys.argv[1]) as (
49
+ async with await transport.open_transport(sys.argv[1]) as (
50
50
  hci_host_source,
51
51
  hci_host_sink,
52
52
  ):
53
53
  print('>>> connected')
54
54
 
55
55
  print('>>> connecting to HCI...')
56
- async with await transport.open_transport_or_link(sys.argv[2]) as (
56
+ async with await transport.open_transport(sys.argv[2]) as (
57
57
  hci_controller_source,
58
58
  hci_controller_sink,
59
59
  ):
@@ -22,7 +22,7 @@ import click
22
22
 
23
23
  from bumble import l2cap
24
24
  from bumble.colors import color
25
- from bumble.transport import open_transport_or_link
25
+ from bumble.transport import open_transport
26
26
  from bumble.device import Device
27
27
  from bumble.utils import FlowControlAsyncPipe
28
28
  from bumble.hci import HCI_Constant
@@ -258,7 +258,7 @@ class ClientBridge:
258
258
  # -----------------------------------------------------------------------------
259
259
  async def run(device_config, hci_transport, bridge):
260
260
  print('<<< connecting to HCI...')
261
- async with await open_transport_or_link(hci_transport) as (hci_source, hci_sink):
261
+ async with await open_transport(hci_transport) as (hci_source, hci_sink):
262
262
  print('<<< connected')
263
263
 
264
264
  device = Device.from_config_file_with_hci(device_config, hci_source, hci_sink)
@@ -337,7 +337,12 @@ class Speaker:
337
337
  ),
338
338
  (
339
339
  AdvertisingData.FLAGS,
340
- bytes([AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG]),
340
+ bytes(
341
+ [
342
+ AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
343
+ | AdvertisingData.BR_EDR_NOT_SUPPORTED_FLAG
344
+ ]
345
+ ),
341
346
  ),
342
347
  (
343
348
  AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,