bumble 0.0.188__py3-none-any.whl → 0.0.190__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/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.0.188'
16
- __version_tuple__ = version_tuple = (0, 0, 188)
15
+ __version__ = version = '0.0.190'
16
+ __version_tuple__ = version_tuple = (0, 0, 190)
bumble/a2dp.py CHANGED
@@ -652,7 +652,9 @@ class SbcPacketSource:
652
652
 
653
653
  # Prepare for next packets
654
654
  sequence_number += 1
655
+ sequence_number &= 0xFFFF
655
656
  timestamp += sum((frame.sample_count for frame in frames))
657
+ timestamp &= 0xFFFFFFFF
656
658
  frames = [frame]
657
659
  frames_size = len(frame.payload)
658
660
  else:
bumble/apps/bench.py CHANGED
@@ -509,9 +509,11 @@ class Ping:
509
509
  packet = struct.pack(
510
510
  '>bbI',
511
511
  PacketType.SEQUENCE,
512
- PACKET_FLAG_LAST
513
- if self.current_packet_index == self.tx_packet_count - 1
514
- else 0,
512
+ (
513
+ PACKET_FLAG_LAST
514
+ if self.current_packet_index == self.tx_packet_count - 1
515
+ else 0
516
+ ),
515
517
  self.current_packet_index,
516
518
  ) + bytes(self.tx_packet_size - 6)
517
519
  logging.info(color(f'Sending packet {self.current_packet_index}', 'yellow'))
@@ -1062,9 +1064,9 @@ class Central(Connection.Listener):
1062
1064
 
1063
1065
  if self.phy not in (None, HCI_LE_1M_PHY):
1064
1066
  # Add an connections parameters entry for this PHY.
1065
- self.connection_parameter_preferences[
1066
- self.phy
1067
- ] = connection_parameter_preferences
1067
+ self.connection_parameter_preferences[self.phy] = (
1068
+ connection_parameter_preferences
1069
+ )
1068
1070
  else:
1069
1071
  self.connection_parameter_preferences = None
1070
1072
 
@@ -1232,6 +1234,7 @@ class Peripheral(Device.Listener, Connection.Listener):
1232
1234
  'cyan',
1233
1235
  )
1234
1236
  )
1237
+
1235
1238
  await self.connected.wait()
1236
1239
  logging.info(color('### Connected', 'cyan'))
1237
1240
 
@@ -1591,8 +1594,8 @@ def central(
1591
1594
  mode_factory = create_mode_factory(ctx, 'gatt-client')
1592
1595
  classic = ctx.obj['classic']
1593
1596
 
1594
- asyncio.run(
1595
- Central(
1597
+ async def run_central():
1598
+ await Central(
1596
1599
  transport,
1597
1600
  peripheral_address,
1598
1601
  classic,
@@ -1604,7 +1607,8 @@ def central(
1604
1607
  encrypt or authenticate,
1605
1608
  ctx.obj['extended_data_length'],
1606
1609
  ).run()
1607
- )
1610
+
1611
+ asyncio.run(run_central())
1608
1612
 
1609
1613
 
1610
1614
  @bench.command()
@@ -1615,15 +1619,16 @@ def peripheral(ctx, transport):
1615
1619
  role_factory = create_role_factory(ctx, 'receiver')
1616
1620
  mode_factory = create_mode_factory(ctx, 'gatt-server')
1617
1621
 
1618
- asyncio.run(
1619
- Peripheral(
1622
+ async def run_peripheral():
1623
+ await Peripheral(
1620
1624
  transport,
1621
1625
  ctx.obj['classic'],
1622
1626
  ctx.obj['extended_data_length'],
1623
1627
  role_factory,
1624
1628
  mode_factory,
1625
1629
  ).run()
1626
- )
1630
+
1631
+ asyncio.run(run_peripheral())
1627
1632
 
1628
1633
 
1629
1634
  def main():
@@ -76,6 +76,7 @@ logger = logging.getLogger(__name__)
76
76
  # -----------------------------------------------------------------------------
77
77
  DEFAULT_UI_PORT = 7654
78
78
 
79
+
79
80
  # -----------------------------------------------------------------------------
80
81
  class AudioExtractor:
81
82
  @staticmethod
bumble/apps/unbond.py CHANGED
@@ -24,6 +24,7 @@ from bumble.device import Device
24
24
  from bumble.keys import JsonKeyStore
25
25
  from bumble.transport import open_transport
26
26
 
27
+
27
28
  # -----------------------------------------------------------------------------
28
29
  async def unbond_with_keystore(keystore, address):
29
30
  if address is None:
bumble/att.py CHANGED
@@ -655,7 +655,7 @@ class ATT_Write_Command(ATT_PDU):
655
655
  @ATT_PDU.subclass(
656
656
  [
657
657
  ('attribute_handle', HANDLE_FIELD_SPEC),
658
- ('attribute_value', '*')
658
+ ('attribute_value', '*'),
659
659
  # ('authentication_signature', 'TODO')
660
660
  ]
661
661
  )
bumble/avdtp.py CHANGED
@@ -325,8 +325,8 @@ class MediaPacket:
325
325
  self.padding = padding
326
326
  self.extension = extension
327
327
  self.marker = marker
328
- self.sequence_number = sequence_number
329
- self.timestamp = timestamp
328
+ self.sequence_number = sequence_number & 0xFFFF
329
+ self.timestamp = timestamp & 0xFFFFFFFF
330
330
  self.ssrc = ssrc
331
331
  self.csrc_list = csrc_list
332
332
  self.payload_type = payload_type
@@ -341,7 +341,12 @@ class MediaPacket:
341
341
  | len(self.csrc_list),
342
342
  self.marker << 7 | self.payload_type,
343
343
  ]
344
- ) + struct.pack('>HII', self.sequence_number, self.timestamp, self.ssrc)
344
+ ) + struct.pack(
345
+ '>HII',
346
+ self.sequence_number,
347
+ self.timestamp,
348
+ self.ssrc,
349
+ )
345
350
  for csrc in self.csrc_list:
346
351
  header += struct.pack('>I', csrc)
347
352
  return header + self.payload
@@ -1545,9 +1550,10 @@ class Protocol(EventEmitter):
1545
1550
 
1546
1551
  assert False # Should never reach this
1547
1552
 
1548
- async def get_capabilities(
1549
- self, seid: int
1550
- ) -> Union[Get_Capabilities_Response, Get_All_Capabilities_Response,]:
1553
+ async def get_capabilities(self, seid: int) -> Union[
1554
+ Get_Capabilities_Response,
1555
+ Get_All_Capabilities_Response,
1556
+ ]:
1551
1557
  if self.version > (1, 2):
1552
1558
  return await self.send_command(Get_All_Capabilities_Command(seid))
1553
1559
 
bumble/avrcp.py CHANGED
@@ -1745,9 +1745,11 @@ class Protocol(pyee.EventEmitter):
1745
1745
  avc.CommandFrame.CommandType.CONTROL,
1746
1746
  avc.Frame.SubunitType.PANEL,
1747
1747
  0,
1748
- avc.PassThroughFrame.StateFlag.PRESSED
1749
- if pressed
1750
- else avc.PassThroughFrame.StateFlag.RELEASED,
1748
+ (
1749
+ avc.PassThroughFrame.StateFlag.PRESSED
1750
+ if pressed
1751
+ else avc.PassThroughFrame.StateFlag.RELEASED
1752
+ ),
1751
1753
  key,
1752
1754
  b'',
1753
1755
  )
bumble/controller.py CHANGED
@@ -134,15 +134,15 @@ class Controller:
134
134
  self.hci_sink = None
135
135
  self.link = link
136
136
 
137
- self.central_connections: Dict[
138
- Address, Connection
139
- ] = {} # Connections where this controller is the central
140
- self.peripheral_connections: Dict[
141
- Address, Connection
142
- ] = {} # Connections where this controller is the peripheral
143
- self.classic_connections: Dict[
144
- Address, Connection
145
- ] = {} # Connections in BR/EDR
137
+ self.central_connections: Dict[Address, Connection] = (
138
+ {}
139
+ ) # Connections where this controller is the central
140
+ self.peripheral_connections: Dict[Address, Connection] = (
141
+ {}
142
+ ) # Connections where this controller is the peripheral
143
+ self.classic_connections: Dict[Address, Connection] = (
144
+ {}
145
+ ) # Connections in BR/EDR
146
146
  self.central_cis_links: Dict[int, CisLink] = {} # CIS links by handle
147
147
  self.peripheral_cis_links: Dict[int, CisLink] = {} # CIS links by handle
148
148
 
bumble/device.py CHANGED
@@ -276,12 +276,12 @@ class Advertisement:
276
276
  data_bytes: bytes = b''
277
277
 
278
278
  # Constants
279
- TX_POWER_NOT_AVAILABLE: ClassVar[
280
- int
281
- ] = HCI_LE_Extended_Advertising_Report_Event.TX_POWER_INFORMATION_NOT_AVAILABLE
282
- RSSI_NOT_AVAILABLE: ClassVar[
283
- int
284
- ] = HCI_LE_Extended_Advertising_Report_Event.RSSI_NOT_AVAILABLE
279
+ TX_POWER_NOT_AVAILABLE: ClassVar[int] = (
280
+ HCI_LE_Extended_Advertising_Report_Event.TX_POWER_INFORMATION_NOT_AVAILABLE
281
+ )
282
+ RSSI_NOT_AVAILABLE: ClassVar[int] = (
283
+ HCI_LE_Extended_Advertising_Report_Event.RSSI_NOT_AVAILABLE
284
+ )
285
285
 
286
286
  def __post_init__(self) -> None:
287
287
  self.data = AdvertisingData.from_bytes(self.data_bytes)
@@ -558,7 +558,9 @@ class AdvertisingParameters:
558
558
  )
559
559
  primary_advertising_interval_min: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
560
560
  primary_advertising_interval_max: int = DEVICE_DEFAULT_ADVERTISING_INTERVAL
561
- primary_advertising_channel_map: HCI_LE_Set_Extended_Advertising_Parameters_Command.ChannelMap = (
561
+ primary_advertising_channel_map: (
562
+ HCI_LE_Set_Extended_Advertising_Parameters_Command.ChannelMap
563
+ ) = (
562
564
  AdvertisingChannelMap.CHANNEL_37
563
565
  | AdvertisingChannelMap.CHANNEL_38
564
566
  | AdvertisingChannelMap.CHANNEL_39
@@ -1138,14 +1140,12 @@ class Connection(CompositeEventEmitter):
1138
1140
  @overload
1139
1141
  async def create_l2cap_channel(
1140
1142
  self, spec: l2cap.ClassicChannelSpec
1141
- ) -> l2cap.ClassicChannel:
1142
- ...
1143
+ ) -> l2cap.ClassicChannel: ...
1143
1144
 
1144
1145
  @overload
1145
1146
  async def create_l2cap_channel(
1146
1147
  self, spec: l2cap.LeCreditBasedChannelSpec
1147
- ) -> l2cap.LeCreditBasedChannel:
1148
- ...
1148
+ ) -> l2cap.LeCreditBasedChannel: ...
1149
1149
 
1150
1150
  async def create_l2cap_channel(
1151
1151
  self, spec: Union[l2cap.ClassicChannelSpec, l2cap.LeCreditBasedChannelSpec]
@@ -1723,16 +1723,14 @@ class Device(CompositeEventEmitter):
1723
1723
  self,
1724
1724
  connection: Connection,
1725
1725
  spec: l2cap.ClassicChannelSpec,
1726
- ) -> l2cap.ClassicChannel:
1727
- ...
1726
+ ) -> l2cap.ClassicChannel: ...
1728
1727
 
1729
1728
  @overload
1730
1729
  async def create_l2cap_channel(
1731
1730
  self,
1732
1731
  connection: Connection,
1733
1732
  spec: l2cap.LeCreditBasedChannelSpec,
1734
- ) -> l2cap.LeCreditBasedChannel:
1735
- ...
1733
+ ) -> l2cap.LeCreditBasedChannel: ...
1736
1734
 
1737
1735
  async def create_l2cap_channel(
1738
1736
  self,
@@ -1753,16 +1751,14 @@ class Device(CompositeEventEmitter):
1753
1751
  self,
1754
1752
  spec: l2cap.ClassicChannelSpec,
1755
1753
  handler: Optional[Callable[[l2cap.ClassicChannel], Any]] = None,
1756
- ) -> l2cap.ClassicChannelServer:
1757
- ...
1754
+ ) -> l2cap.ClassicChannelServer: ...
1758
1755
 
1759
1756
  @overload
1760
1757
  def create_l2cap_server(
1761
1758
  self,
1762
1759
  spec: l2cap.LeCreditBasedChannelSpec,
1763
1760
  handler: Optional[Callable[[l2cap.LeCreditBasedChannel], Any]] = None,
1764
- ) -> l2cap.LeCreditBasedChannelServer:
1765
- ...
1761
+ ) -> l2cap.LeCreditBasedChannelServer: ...
1766
1762
 
1767
1763
  def create_l2cap_server(
1768
1764
  self,
@@ -3289,17 +3285,19 @@ class Device(CompositeEventEmitter):
3289
3285
 
3290
3286
  handler = self.on(
3291
3287
  'remote_name',
3292
- lambda address, remote_name: pending_name.set_result(remote_name)
3293
- if address == peer_address
3294
- else None,
3288
+ lambda address, remote_name: (
3289
+ pending_name.set_result(remote_name)
3290
+ if address == peer_address
3291
+ else None
3292
+ ),
3295
3293
  )
3296
3294
  failure_handler = self.on(
3297
3295
  'remote_name_failure',
3298
- lambda address, error_code: pending_name.set_exception(
3299
- HCI_Error(error_code)
3300
- )
3301
- if address == peer_address
3302
- else None,
3296
+ lambda address, error_code: (
3297
+ pending_name.set_exception(HCI_Error(error_code))
3298
+ if address == peer_address
3299
+ else None
3300
+ ),
3303
3301
  )
3304
3302
 
3305
3303
  try:
@@ -3475,9 +3473,9 @@ class Device(CompositeEventEmitter):
3475
3473
  LE features supported by the remote device.
3476
3474
  """
3477
3475
  with closing(EventWatcher()) as watcher:
3478
- read_feature_future: asyncio.Future[
3479
- LeFeatureMask
3480
- ] = asyncio.get_running_loop().create_future()
3476
+ read_feature_future: asyncio.Future[LeFeatureMask] = (
3477
+ asyncio.get_running_loop().create_future()
3478
+ )
3481
3479
 
3482
3480
  def on_le_remote_features(handle: int, features: int):
3483
3481
  if handle == connection.handle:
bumble/gap.py CHANGED
@@ -36,6 +36,7 @@ logger = logging.getLogger(__name__)
36
36
  # Classes
37
37
  # -----------------------------------------------------------------------------
38
38
 
39
+
39
40
  # -----------------------------------------------------------------------------
40
41
  class GenericAccessService(Service):
41
42
  def __init__(self, device_name, appearance=(0, 0)):
bumble/gatt.py CHANGED
@@ -342,9 +342,11 @@ class Service(Attribute):
342
342
  uuid = UUID(uuid)
343
343
 
344
344
  super().__init__(
345
- GATT_PRIMARY_SERVICE_ATTRIBUTE_TYPE
346
- if primary
347
- else GATT_SECONDARY_SERVICE_ATTRIBUTE_TYPE,
345
+ (
346
+ GATT_PRIMARY_SERVICE_ATTRIBUTE_TYPE
347
+ if primary
348
+ else GATT_SECONDARY_SERVICE_ATTRIBUTE_TYPE
349
+ ),
348
350
  Attribute.READABLE,
349
351
  uuid.to_pdu_bytes(),
350
352
  )
@@ -560,9 +562,9 @@ class CharacteristicAdapter:
560
562
 
561
563
  def __init__(self, characteristic: Union[Characteristic, AttributeProxy]):
562
564
  self.wrapped_characteristic = characteristic
563
- self.subscribers: Dict[
564
- Callable, Callable
565
- ] = {} # Map from subscriber to proxy subscriber
565
+ self.subscribers: Dict[Callable, Callable] = (
566
+ {}
567
+ ) # Map from subscriber to proxy subscriber
566
568
 
567
569
  if isinstance(characteristic, Characteristic):
568
570
  self.read_value = self.read_encoded_value
bumble/gatt_client.py CHANGED
@@ -352,9 +352,7 @@ class Client:
352
352
  if c.uuid == uuid
353
353
  ]
354
354
 
355
- def get_attribute_grouping(
356
- self, attribute_handle: int
357
- ) -> Optional[
355
+ def get_attribute_grouping(self, attribute_handle: int) -> Optional[
358
356
  Union[
359
357
  ServiceProxy,
360
358
  Tuple[ServiceProxy, CharacteristicProxy],
bumble/gatt_server.py CHANGED
@@ -445,9 +445,9 @@ class Server(EventEmitter):
445
445
  assert self.pending_confirmations[connection.handle] is None
446
446
 
447
447
  # Create a future value to hold the eventual response
448
- pending_confirmation = self.pending_confirmations[
449
- connection.handle
450
- ] = asyncio.get_running_loop().create_future()
448
+ pending_confirmation = self.pending_confirmations[connection.handle] = (
449
+ asyncio.get_running_loop().create_future()
450
+ )
451
451
 
452
452
  try:
453
453
  self.send_gatt_pdu(connection.handle, indication.to_bytes())
bumble/hci.py CHANGED
@@ -4249,9 +4249,11 @@ class HCI_LE_Set_Extended_Scan_Parameters_Command(HCI_Command):
4249
4249
  fields.append(
4250
4250
  (
4251
4251
  f'{scanning_phy_str}.scan_type: ',
4252
- 'PASSIVE'
4253
- if self.scan_types[i] == self.PASSIVE_SCANNING
4254
- else 'ACTIVE',
4252
+ (
4253
+ 'PASSIVE'
4254
+ if self.scan_types[i] == self.PASSIVE_SCANNING
4255
+ else 'ACTIVE'
4256
+ ),
4255
4257
  )
4256
4258
  )
4257
4259
  fields.append(
@@ -5010,9 +5012,9 @@ class HCI_LE_Advertising_Report_Event(HCI_LE_Meta_Event):
5010
5012
  return f'{color(self.subevent_name(self.subevent_code), "magenta")}:\n{reports}'
5011
5013
 
5012
5014
 
5013
- HCI_LE_Meta_Event.subevent_classes[
5014
- HCI_LE_ADVERTISING_REPORT_EVENT
5015
- ] = HCI_LE_Advertising_Report_Event
5015
+ HCI_LE_Meta_Event.subevent_classes[HCI_LE_ADVERTISING_REPORT_EVENT] = (
5016
+ HCI_LE_Advertising_Report_Event
5017
+ )
5016
5018
 
5017
5019
 
5018
5020
  # -----------------------------------------------------------------------------
@@ -5264,9 +5266,9 @@ class HCI_LE_Extended_Advertising_Report_Event(HCI_LE_Meta_Event):
5264
5266
  return f'{color(self.subevent_name(self.subevent_code), "magenta")}:\n{reports}'
5265
5267
 
5266
5268
 
5267
- HCI_LE_Meta_Event.subevent_classes[
5268
- HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT
5269
- ] = HCI_LE_Extended_Advertising_Report_Event
5269
+ HCI_LE_Meta_Event.subevent_classes[HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT] = (
5270
+ HCI_LE_Extended_Advertising_Report_Event
5271
+ )
5270
5272
 
5271
5273
 
5272
5274
  # -----------------------------------------------------------------------------
bumble/hfp.py CHANGED
@@ -22,7 +22,8 @@ import dataclasses
22
22
  import enum
23
23
  import traceback
24
24
  import pyee
25
- from typing import Dict, List, Union, Set, Any, Optional, TYPE_CHECKING
25
+ from typing import Dict, List, Union, Set, Any, Optional, Type, TYPE_CHECKING
26
+ from typing_extensions import Self
26
27
 
27
28
  from bumble import at
28
29
  from bumble import rfcomm
@@ -417,17 +418,21 @@ class AtResponseType(enum.Enum):
417
418
  MULTIPLE = 2
418
419
 
419
420
 
421
+ @dataclasses.dataclass
420
422
  class AtResponse:
421
423
  code: str
422
424
  parameters: list
423
425
 
424
- def __init__(self, response: bytearray):
425
- code_and_parameters = response.split(b':')
426
+ @classmethod
427
+ def parse_from(cls: Type[Self], buffer: bytearray) -> Self:
428
+ code_and_parameters = buffer.split(b':')
426
429
  parameters = (
427
430
  code_and_parameters[1] if len(code_and_parameters) > 1 else bytearray()
428
431
  )
429
- self.code = code_and_parameters[0].decode()
430
- self.parameters = at.parse_parameters(parameters)
432
+ return cls(
433
+ code=code_and_parameters[0].decode(),
434
+ parameters=at.parse_parameters(parameters),
435
+ )
431
436
 
432
437
 
433
438
  @dataclasses.dataclass
@@ -530,7 +535,7 @@ class HfProtocol(pyee.EventEmitter):
530
535
 
531
536
  # Isolate the AT response code and parameters.
532
537
  raw_response = self.read_buffer[header + 2 : trailer]
533
- response = AtResponse(raw_response)
538
+ response = AtResponse.parse_from(raw_response)
534
539
  logger.debug(f"<<< {raw_response.decode()}")
535
540
 
536
541
  # Consume the response bytes.
@@ -815,11 +820,11 @@ class HfProtocol(pyee.EventEmitter):
815
820
  return calls
816
821
 
817
822
  async def update_ag_indicator(self, index: int, value: int):
818
- self.ag_indicators[index].current_status = value
819
- self.emit('ag_indicator', self.ag_indicators[index])
820
- logger.info(
821
- f"AG indicator updated: {self.ag_indicators[index].description}, {value}"
822
- )
823
+ # CIEV is in 1-index, while ag_indicators is in 0-index.
824
+ ag_indicator = self.ag_indicators[index - 1]
825
+ ag_indicator.current_status = value
826
+ self.emit('ag_indicator', ag_indicator)
827
+ logger.info(f"AG indicator updated: {ag_indicator.description}, {value}")
823
828
 
824
829
  async def handle_unsolicited(self):
825
830
  """Handle unsolicited result codes sent by the audio gateway."""
@@ -1006,7 +1011,9 @@ class EscoParameters:
1006
1011
  transmit_coding_format: CodingFormat
1007
1012
  receive_coding_format: CodingFormat
1008
1013
  packet_type: HCI_Enhanced_Setup_Synchronous_Connection_Command.PacketType
1009
- retransmission_effort: HCI_Enhanced_Setup_Synchronous_Connection_Command.RetransmissionEffort
1014
+ retransmission_effort: (
1015
+ HCI_Enhanced_Setup_Synchronous_Connection_Command.RetransmissionEffort
1016
+ )
1010
1017
  max_latency: int
1011
1018
 
1012
1019
  # Common
@@ -1014,12 +1021,12 @@ class EscoParameters:
1014
1021
  output_coding_format: CodingFormat = CodingFormat(CodecID.LINEAR_PCM)
1015
1022
  input_coded_data_size: int = 16
1016
1023
  output_coded_data_size: int = 16
1017
- input_pcm_data_format: HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat = (
1018
- HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat.TWOS_COMPLEMENT
1019
- )
1020
- output_pcm_data_format: HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat = (
1021
- HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat.TWOS_COMPLEMENT
1022
- )
1024
+ input_pcm_data_format: (
1025
+ HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat
1026
+ ) = HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat.TWOS_COMPLEMENT
1027
+ output_pcm_data_format: (
1028
+ HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat
1029
+ ) = HCI_Enhanced_Setup_Synchronous_Connection_Command.PcmDataFormat.TWOS_COMPLEMENT
1023
1030
  input_pcm_sample_payload_msb_position: int = 0
1024
1031
  output_pcm_sample_payload_msb_position: int = 0
1025
1032
  input_data_path: HCI_Enhanced_Setup_Synchronous_Connection_Command.DataPath = (
bumble/hid.py CHANGED
@@ -48,6 +48,7 @@ HID_INTERRUPT_PSM = 0x0013
48
48
 
49
49
  class Message:
50
50
  message_type: MessageType
51
+
51
52
  # Report types
52
53
  class ReportType(enum.IntEnum):
53
54
  OTHER_REPORT = 0x00
bumble/keys.py CHANGED
@@ -128,10 +128,10 @@ class PairingKeys:
128
128
 
129
129
  def print(self, prefix=''):
130
130
  keys_dict = self.to_dict()
131
- for (container_property, value) in keys_dict.items():
131
+ for container_property, value in keys_dict.items():
132
132
  if isinstance(value, dict):
133
133
  print(f'{prefix}{color(container_property, "cyan")}:')
134
- for (key_property, key_value) in value.items():
134
+ for key_property, key_value in value.items():
135
135
  print(f'{prefix} {color(key_property, "green")}: {key_value}')
136
136
  else:
137
137
  print(f'{prefix}{color(container_property, "cyan")}: {value}')
@@ -158,7 +158,7 @@ class KeyStore:
158
158
  async def get_resolving_keys(self):
159
159
  all_keys = await self.get_all()
160
160
  resolving_keys = []
161
- for (name, keys) in all_keys:
161
+ for name, keys in all_keys:
162
162
  if keys.irk is not None:
163
163
  if keys.address_type is None:
164
164
  address_type = Address.RANDOM_DEVICE_ADDRESS
@@ -171,7 +171,7 @@ class KeyStore:
171
171
  async def print(self, prefix=''):
172
172
  entries = await self.get_all()
173
173
  separator = ''
174
- for (name, keys) in entries:
174
+ for name, keys in entries:
175
175
  print(separator + prefix + color(name, 'yellow'))
176
176
  keys.print(prefix=prefix + ' ')
177
177
  separator = '\n'
bumble/pandora/host.py CHANGED
@@ -287,9 +287,9 @@ class HostService(HostServicer):
287
287
  self.log.debug(f"WaitDisconnection: {connection_handle}")
288
288
 
289
289
  if connection := self.device.lookup_connection(connection_handle):
290
- disconnection_future: asyncio.Future[
291
- None
292
- ] = asyncio.get_running_loop().create_future()
290
+ disconnection_future: asyncio.Future[None] = (
291
+ asyncio.get_running_loop().create_future()
292
+ )
293
293
 
294
294
  def on_disconnection(_: None) -> None:
295
295
  disconnection_future.set_result(None)
@@ -370,9 +370,9 @@ class HostService(HostServicer):
370
370
  scan_response_data=scan_response_data,
371
371
  )
372
372
 
373
- pending_connection: asyncio.Future[
374
- bumble.device.Connection
375
- ] = asyncio.get_running_loop().create_future()
373
+ pending_connection: asyncio.Future[bumble.device.Connection] = (
374
+ asyncio.get_running_loop().create_future()
375
+ )
376
376
 
377
377
  if request.connectable:
378
378
 
@@ -516,9 +516,9 @@ class HostService(HostServicer):
516
516
  await asyncio.sleep(1)
517
517
  continue
518
518
 
519
- pending_connection: asyncio.Future[
520
- bumble.device.Connection
521
- ] = asyncio.get_running_loop().create_future()
519
+ pending_connection: asyncio.Future[bumble.device.Connection] = (
520
+ asyncio.get_running_loop().create_future()
521
+ )
522
522
 
523
523
  self.log.debug('Wait for LE connection...')
524
524
  connection = await pending_connection
@@ -563,12 +563,14 @@ class HostService(HostServicer):
563
563
  legacy=request.legacy,
564
564
  active=not request.passive,
565
565
  own_address_type=request.own_address_type,
566
- scan_interval=int(request.interval)
567
- if request.interval
568
- else DEVICE_DEFAULT_SCAN_INTERVAL,
569
- scan_window=int(request.window)
570
- if request.window
571
- else DEVICE_DEFAULT_SCAN_WINDOW,
566
+ scan_interval=(
567
+ int(request.interval)
568
+ if request.interval
569
+ else DEVICE_DEFAULT_SCAN_INTERVAL
570
+ ),
571
+ scan_window=(
572
+ int(request.window) if request.window else DEVICE_DEFAULT_SCAN_WINDOW
573
+ ),
572
574
  scanning_phys=scanning_phys,
573
575
  )
574
576
 
@@ -782,9 +784,11 @@ class HostService(HostServicer):
782
784
  *struct.pack('<H', dt.peripheral_connection_interval_min),
783
785
  *struct.pack(
784
786
  '<H',
785
- dt.peripheral_connection_interval_max
786
- if dt.peripheral_connection_interval_max
787
- else dt.peripheral_connection_interval_min,
787
+ (
788
+ dt.peripheral_connection_interval_max
789
+ if dt.peripheral_connection_interval_max
790
+ else dt.peripheral_connection_interval_min
791
+ ),
788
792
  ),
789
793
  ]
790
794
  ),
@@ -383,9 +383,9 @@ class SecurityService(SecurityServicer):
383
383
  connection.transport
384
384
  ] == request.level_variant()
385
385
 
386
- wait_for_security: asyncio.Future[
387
- str
388
- ] = asyncio.get_running_loop().create_future()
386
+ wait_for_security: asyncio.Future[str] = (
387
+ asyncio.get_running_loop().create_future()
388
+ )
389
389
  authenticate_task: Optional[asyncio.Future[None]] = None
390
390
  pair_task: Optional[asyncio.Future[None]] = None
391
391
 
bumble/profiles/bap.py CHANGED
@@ -24,8 +24,9 @@ import enum
24
24
  import struct
25
25
  import functools
26
26
  import logging
27
- from typing import Optional, List, Union, Type, Dict, Any, Tuple, cast
27
+ from typing import Optional, List, Union, Type, Dict, Any, Tuple
28
28
 
29
+ from bumble import core
29
30
  from bumble import colors
30
31
  from bumble import device
31
32
  from bumble import hci
@@ -228,6 +229,14 @@ class SupportedFrameDuration(enum.IntFlag):
228
229
  DURATION_10000_US_PREFERRED = 0b0010
229
230
 
230
231
 
232
+ class AnnouncementType(enum.IntEnum):
233
+ '''Basic Audio Profile, 3.5.3. Additional Audio Stream Control Service requirements'''
234
+
235
+ # fmt: off
236
+ GENERAL = 0x00
237
+ TARGETED = 0x01
238
+
239
+
231
240
  # -----------------------------------------------------------------------------
232
241
  # ASE Operations
233
242
  # -----------------------------------------------------------------------------
@@ -453,6 +462,34 @@ class AudioRole(enum.IntEnum):
453
462
  SOURCE = hci.HCI_LE_Setup_ISO_Data_Path_Command.Direction.HOST_TO_CONTROLLER
454
463
 
455
464
 
465
+ @dataclasses.dataclass
466
+ class UnicastServerAdvertisingData:
467
+ """Advertising Data for ASCS."""
468
+
469
+ announcement_type: AnnouncementType = AnnouncementType.TARGETED
470
+ available_audio_contexts: ContextType = ContextType.MEDIA
471
+ metadata: bytes = b''
472
+
473
+ def __bytes__(self) -> bytes:
474
+ return bytes(
475
+ core.AdvertisingData(
476
+ [
477
+ (
478
+ core.AdvertisingData.SERVICE_DATA_16_BIT_UUID,
479
+ struct.pack(
480
+ '<2sBIB',
481
+ gatt.GATT_AUDIO_STREAM_CONTROL_SERVICE.to_bytes(),
482
+ self.announcement_type,
483
+ self.available_audio_contexts,
484
+ len(self.metadata),
485
+ )
486
+ + self.metadata,
487
+ )
488
+ ]
489
+ )
490
+ )
491
+
492
+
456
493
  # -----------------------------------------------------------------------------
457
494
  # Utils
458
495
  # -----------------------------------------------------------------------------
@@ -59,7 +59,7 @@ class DeviceInformationService(TemplateService):
59
59
  firmware_revision: Optional[str] = None,
60
60
  software_revision: Optional[str] = None,
61
61
  system_id: Optional[Tuple[int, int]] = None, # (OUI, Manufacturer ID)
62
- ieee_regulatory_certification_data_list: Optional[bytes] = None
62
+ ieee_regulatory_certification_data_list: Optional[bytes] = None,
63
63
  # TODO: pnp_id
64
64
  ):
65
65
  characteristics = [
@@ -107,7 +107,7 @@ class DeviceInformationServiceProxy(ProfileServiceProxy):
107
107
  def __init__(self, service_proxy):
108
108
  self.service_proxy = service_proxy
109
109
 
110
- for (field, uuid) in (
110
+ for field, uuid in (
111
111
  ('manufacturer_name', GATT_MANUFACTURER_NAME_STRING_CHARACTERISTIC),
112
112
  ('model_number', GATT_MODEL_NUMBER_STRING_CHARACTERISTIC),
113
113
  ('serial_number', GATT_SERIAL_NUMBER_STRING_CHARACTERISTIC),
bumble/sdp.py CHANGED
@@ -825,11 +825,13 @@ class Client:
825
825
  )
826
826
  attribute_id_list = DataElement.sequence(
827
827
  [
828
- DataElement.unsigned_integer(
829
- attribute_id[0], value_size=attribute_id[1]
828
+ (
829
+ DataElement.unsigned_integer(
830
+ attribute_id[0], value_size=attribute_id[1]
831
+ )
832
+ if isinstance(attribute_id, tuple)
833
+ else DataElement.unsigned_integer_16(attribute_id)
830
834
  )
831
- if isinstance(attribute_id, tuple)
832
- else DataElement.unsigned_integer_16(attribute_id)
833
835
  for attribute_id in attribute_ids
834
836
  ]
835
837
  )
@@ -881,11 +883,13 @@ class Client:
881
883
 
882
884
  attribute_id_list = DataElement.sequence(
883
885
  [
884
- DataElement.unsigned_integer(
885
- attribute_id[0], value_size=attribute_id[1]
886
+ (
887
+ DataElement.unsigned_integer(
888
+ attribute_id[0], value_size=attribute_id[1]
889
+ )
890
+ if isinstance(attribute_id, tuple)
891
+ else DataElement.unsigned_integer_16(attribute_id)
886
892
  )
887
- if isinstance(attribute_id, tuple)
888
- else DataElement.unsigned_integer_16(attribute_id)
889
893
  for attribute_id in attribute_ids
890
894
  ]
891
895
  )
bumble/smp.py CHANGED
@@ -737,9 +737,9 @@ class Session:
737
737
 
738
738
  # Create a future that can be used to wait for the session to complete
739
739
  if self.is_initiator:
740
- self.pairing_result: Optional[
741
- asyncio.Future[None]
742
- ] = asyncio.get_running_loop().create_future()
740
+ self.pairing_result: Optional[asyncio.Future[None]] = (
741
+ asyncio.get_running_loop().create_future()
742
+ )
743
743
  else:
744
744
  self.pairing_result = None
745
745
 
@@ -49,6 +49,7 @@ LINUX_FROM_SCRATCH_SOURCE = (
49
49
  False,
50
50
  )
51
51
 
52
+
52
53
  # -----------------------------------------------------------------------------
53
54
  # Functions
54
55
  # -----------------------------------------------------------------------------
@@ -111,7 +112,7 @@ def main(output_dir, source, single, force, parse):
111
112
  for driver_info in rtk.Driver.DRIVER_INFOS
112
113
  ]
113
114
 
114
- for (fw_name, config_name, config_needed) in images:
115
+ for fw_name, config_name, config_needed in images:
115
116
  print(color("---", "yellow"))
116
117
  fw_image_out = output_dir / fw_name
117
118
  if not force and fw_image_out.exists():
@@ -59,15 +59,13 @@ class TransportLostError(Exception):
59
59
  # Typing Protocols
60
60
  # -----------------------------------------------------------------------------
61
61
  class TransportSink(Protocol):
62
- def on_packet(self, packet: bytes) -> None:
63
- ...
62
+ def on_packet(self, packet: bytes) -> None: ...
64
63
 
65
64
 
66
65
  class TransportSource(Protocol):
67
66
  terminated: asyncio.Future[None]
68
67
 
69
- def set_packet_sink(self, sink: TransportSink) -> None:
70
- ...
68
+ def set_packet_sink(self, sink: TransportSink) -> None: ...
71
69
 
72
70
 
73
71
  # -----------------------------------------------------------------------------
@@ -18,6 +18,7 @@
18
18
  from __future__ import annotations
19
19
  import asyncio
20
20
  import logging
21
+ import socket
21
22
 
22
23
  from .common import Transport, StreamPacketSource
23
24
 
@@ -28,6 +29,12 @@ logger = logging.getLogger(__name__)
28
29
 
29
30
 
30
31
  # -----------------------------------------------------------------------------
32
+
33
+ # A pass-through function to ease mock testing.
34
+ async def _create_server(*args, **kw_args):
35
+ await asyncio.get_running_loop().create_server(*args, **kw_args)
36
+
37
+
31
38
  async def open_tcp_server_transport(spec: str) -> Transport:
32
39
  '''
33
40
  Open a TCP server transport.
@@ -38,7 +45,22 @@ async def open_tcp_server_transport(spec: str) -> Transport:
38
45
 
39
46
  Example: _:9001
40
47
  '''
48
+ local_host, local_port = spec.split(':')
49
+ return await _open_tcp_server_transport_impl(
50
+ host=local_host if local_host != '_' else None, port=int(local_port)
51
+ )
52
+
53
+
54
+ async def open_tcp_server_transport_with_socket(sock: socket.socket) -> Transport:
55
+ '''
56
+ Open a TCP server transport with an existing socket.
57
+
58
+ One reason to use this variant is to let python pick an unused port.
59
+ '''
60
+ return await _open_tcp_server_transport_impl(sock=sock)
61
+
41
62
 
63
+ async def _open_tcp_server_transport_impl(**kwargs) -> Transport:
42
64
  class TcpServerTransport(Transport):
43
65
  async def close(self):
44
66
  await super().close()
@@ -77,13 +99,10 @@ async def open_tcp_server_transport(spec: str) -> Transport:
77
99
  else:
78
100
  logger.debug('no client, dropping packet')
79
101
 
80
- local_host, local_port = spec.split(':')
81
102
  packet_source = StreamPacketSource()
82
103
  packet_sink = TcpServerPacketSink()
83
- await asyncio.get_running_loop().create_server(
84
- lambda: TcpServerProtocol(packet_source, packet_sink),
85
- host=local_host if local_host != '_' else None,
86
- port=int(local_port),
104
+ await _create_server(
105
+ lambda: TcpServerProtocol(packet_source, packet_sink), **kwargs
87
106
  )
88
107
 
89
108
  return TcpServerTransport(packet_source, packet_sink)
bumble/transport/usb.py CHANGED
@@ -449,7 +449,7 @@ async def open_usb_transport(spec: str) -> Transport:
449
449
  # Look for the first interface with the right class and endpoints
450
450
  def find_endpoints(device):
451
451
  # pylint: disable-next=too-many-nested-blocks
452
- for (configuration_index, configuration) in enumerate(device):
452
+ for configuration_index, configuration in enumerate(device):
453
453
  interface = None
454
454
  for interface in configuration:
455
455
  setting = None
bumble/utils.py CHANGED
@@ -117,12 +117,12 @@ class EventWatcher:
117
117
  self.handlers = []
118
118
 
119
119
  @overload
120
- def on(self, emitter: EventEmitter, event: str) -> Callable[[_Handler], _Handler]:
121
- ...
120
+ def on(
121
+ self, emitter: EventEmitter, event: str
122
+ ) -> Callable[[_Handler], _Handler]: ...
122
123
 
123
124
  @overload
124
- def on(self, emitter: EventEmitter, event: str, handler: _Handler) -> _Handler:
125
- ...
125
+ def on(self, emitter: EventEmitter, event: str, handler: _Handler) -> _Handler: ...
126
126
 
127
127
  def on(
128
128
  self, emitter: EventEmitter, event: str, handler: Optional[_Handler] = None
@@ -144,12 +144,14 @@ class EventWatcher:
144
144
  return wrapper if handler is None else wrapper(handler)
145
145
 
146
146
  @overload
147
- def once(self, emitter: EventEmitter, event: str) -> Callable[[_Handler], _Handler]:
148
- ...
147
+ def once(
148
+ self, emitter: EventEmitter, event: str
149
+ ) -> Callable[[_Handler], _Handler]: ...
149
150
 
150
151
  @overload
151
- def once(self, emitter: EventEmitter, event: str, handler: _Handler) -> _Handler:
152
- ...
152
+ def once(
153
+ self, emitter: EventEmitter, event: str, handler: _Handler
154
+ ) -> _Handler: ...
153
155
 
154
156
  def once(
155
157
  self, emitter: EventEmitter, event: str, handler: Optional[_Handler] = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bumble
3
- Version: 0.0.188
3
+ Version: 0.0.190
4
4
  Summary: Bluetooth Stack for Apps, Emulation, Test and Experimentation
5
5
  Home-page: https://github.com/google/bumble
6
6
  Author: Google
@@ -11,14 +11,14 @@ License-File: LICENSE
11
11
  Requires-Dist: pyee >=8.2.2
12
12
  Requires-Dist: aiohttp ~=3.8 ; platform_system != "Emscripten"
13
13
  Requires-Dist: appdirs >=1.4 ; platform_system != "Emscripten"
14
- Requires-Dist: bt-test-interfaces >=0.0.2 ; platform_system != "Emscripten"
15
- Requires-Dist: click ==8.1.3 ; platform_system != "Emscripten"
14
+ Requires-Dist: bt-test-interfaces >=0.0.6 ; platform_system != "Emscripten"
15
+ Requires-Dist: click >=8.1.3 ; platform_system != "Emscripten"
16
16
  Requires-Dist: cryptography ==39 ; platform_system != "Emscripten"
17
- Requires-Dist: grpcio ==1.57.0 ; platform_system != "Emscripten"
17
+ Requires-Dist: grpcio >=1.62.1 ; platform_system != "Emscripten"
18
18
  Requires-Dist: humanize >=4.6.0 ; platform_system != "Emscripten"
19
19
  Requires-Dist: libusb1 >=2.0.1 ; platform_system != "Emscripten"
20
20
  Requires-Dist: libusb-package ==1.0.26.1 ; platform_system != "Emscripten"
21
- Requires-Dist: platformdirs ==3.10.0 ; platform_system != "Emscripten"
21
+ Requires-Dist: platformdirs >=3.10.0 ; platform_system != "Emscripten"
22
22
  Requires-Dist: prompt-toolkit >=3.0.16 ; platform_system != "Emscripten"
23
23
  Requires-Dist: prettytable >=3.6.0 ; platform_system != "Emscripten"
24
24
  Requires-Dist: protobuf >=3.12.4 ; platform_system != "Emscripten"
@@ -28,13 +28,13 @@ Requires-Dist: pyusb >=1.2 ; platform_system != "Emscripten"
28
28
  Requires-Dist: websockets >=12.0 ; platform_system != "Emscripten"
29
29
  Requires-Dist: cryptography >=39.0 ; platform_system == "Emscripten"
30
30
  Provides-Extra: avatar
31
- Requires-Dist: pandora-avatar ==0.0.8 ; extra == 'avatar'
32
- Requires-Dist: rootcanal ==1.9.0 ; (python_version >= "3.10") and extra == 'avatar'
31
+ Requires-Dist: pandora-avatar ==0.0.9 ; extra == 'avatar'
32
+ Requires-Dist: rootcanal ==1.10.0 ; (python_version >= "3.10") and extra == 'avatar'
33
33
  Provides-Extra: build
34
34
  Requires-Dist: build >=0.7 ; extra == 'build'
35
35
  Provides-Extra: development
36
- Requires-Dist: black ==22.10 ; extra == 'development'
37
- Requires-Dist: grpcio-tools >=1.57.0 ; extra == 'development'
36
+ Requires-Dist: black ==24.3 ; extra == 'development'
37
+ Requires-Dist: grpcio-tools >=1.62.1 ; extra == 'development'
38
38
  Requires-Dist: invoke >=1.7.3 ; extra == 'development'
39
39
  Requires-Dist: mypy ==1.8.0 ; extra == 'development'
40
40
  Requires-Dist: nox >=2022 ; extra == 'development'
@@ -49,7 +49,7 @@ Requires-Dist: mkdocs-material >=8.5.6 ; extra == 'documentation'
49
49
  Requires-Dist: mkdocstrings[python] >=0.19.0 ; extra == 'documentation'
50
50
  Provides-Extra: test
51
51
  Requires-Dist: pytest >=8.0 ; extra == 'test'
52
- Requires-Dist: pytest-asyncio ==0.21.1 ; extra == 'test'
52
+ Requires-Dist: pytest-asyncio >=0.21.1 ; extra == 'test'
53
53
  Requires-Dist: pytest-html >=3.2.0 ; extra == 'test'
54
54
  Requires-Dist: coverage >=6.4 ; extra == 'test'
55
55
 
@@ -1,43 +1,43 @@
1
1
  bumble/__init__.py,sha256=Q8jkz6rgl95IMAeInQVt_2GLoJl3DcEP2cxtrQ-ho5c,110
2
- bumble/_version.py,sha256=iguq_-ZmjRMEQMcKKQS8AXaSB60gif-XTbXbRKVaIUk,415
3
- bumble/a2dp.py,sha256=n8_JTJwngPh7ONfAgN9MxvfeYg1Ui5CIveIwlE4B_aE,22585
2
+ bumble/_version.py,sha256=lIV0i6X65UjykL3W2hVxyK2omTPh4jNlE5Ya4uSriLA,415
3
+ bumble/a2dp.py,sha256=VEeAOCfT1ZqpwnEgel6DJ32vxR8jYX3IAaBfCqPdWO8,22675
4
4
  bumble/at.py,sha256=kdrcsx2C8Rg61EWESD2QHwpZntkXkRBJLrPn9auv9K8,2961
5
- bumble/att.py,sha256=_HrhlCl4CXZM9mmBLTCPq5v2OW9eZ0-H6cSu5_jG_5o,32365
5
+ bumble/att.py,sha256=TGzhhBKCQPA_P_eDDSNASJVfa3dCr-QzzrRB3GekrI0,32366
6
6
  bumble/avc.py,sha256=O6ujcmWHMgH821aCLidXN23QFPMAjJ2B50oCu0HxaO0,16188
7
7
  bumble/avctp.py,sha256=W_CgqSRV7Z8xOAz8Q4BZGuuZUHEEJjmioSVg1iDINtM,9881
8
- bumble/avdtp.py,sha256=FOX0bf6k_Cn1pCUNQy8dEPCbj-v65d1gH9sMJfFfg2o,77233
9
- bumble/avrcp.py,sha256=4lY2JeDf1xAJO3S7iG5Bbk6apn_cegWmvPjJb8LCkjA,69279
8
+ bumble/avdtp.py,sha256=RmQiDYeKNitR9jkSXcCzCXacrK_Kbiyt1klO3iylr8Q,77322
9
+ bumble/avrcp.py,sha256=MKyJkyYmL-M1H_Pi4fr8HABXi-E-F9mBOQpbv_Ilysc,69327
10
10
  bumble/bridge.py,sha256=T6es5oS1dy8QgkxQ8iOD-YcZ0SWOv8jaqC7TGxqodk4,3003
11
11
  bumble/codecs.py,sha256=Vc7FOo6d-6VCgDI0ibnLmX8vCZ4-jtX_-0vEUM-yOrI,15343
12
12
  bumble/colors.py,sha256=9H-qzGgMr-YoWdIFpcGPaiRvTvkCzz7FPIkpwqKyKug,3033
13
13
  bumble/company_ids.py,sha256=B68e2QPsDeRYP9jjbGs4GGDwEkGxcXGTsON_CHA0uuI,118528
14
- bumble/controller.py,sha256=ibL9ogENitFtCepewAZdU_tZ1WadY2ugzeNCLTHgXfg,59682
14
+ bumble/controller.py,sha256=XkYTQb2J5MhH_dGfnFkrLXdChFD2s1wSvqXaHQFeo48,59688
15
15
  bumble/core.py,sha256=l71AacyuFijZJH-kBYB41riW9SEsRtlVIPYyhnhPwmc,53132
16
16
  bumble/crypto.py,sha256=L6z3dn9-dgKYRtOM6O3F6n6Ju4PwTM3LAFJtCg_ie78,9382
17
17
  bumble/decoder.py,sha256=N9nMvuVhuwpnfw7EDVuNe9uYY6B6c3RY2dh8RhRPC1U,9608
18
- bumble/device.py,sha256=WbsyDsT6i5JBU-3J2OSshv2eXxtUl-wXBe6v2Bq7PDg,167629
19
- bumble/gap.py,sha256=axlOZIv99357Ehq2vMokeioU85z81qdQvplGn0pF70Q,2137
20
- bumble/gatt.py,sha256=L3RLHiyAKMIZHLfkbH09V9yTNNKymacDtpvwmSoRQRY,38405
21
- bumble/gatt_client.py,sha256=foF8qwWbezN75Lj_7cWBm7DcZ2IrlJPOHbZ-RadZBvs,42537
22
- bumble/gatt_server.py,sha256=nrXyC91blxYwP-fGs5kZI6jaRM1Qr5nl3J34e2PuuhU,37116
23
- bumble/hci.py,sha256=CZH_Gdx0J29PIERx6YcNinv-vHYq6_EVJAEkE1xKeQ4,267263
18
+ bumble/device.py,sha256=XvAdIoGcYZIdlJzJNHRA_4nPYiJF1GRQZAp8HflKe60,167653
19
+ bumble/gap.py,sha256=dRU2_TWvqTDx80hxeSbXlWIeWvptWH4_XbItG5y948Q,2138
20
+ bumble/gatt.py,sha256=W7h8hEyxM8fu3HbAKYJ2HStb8NM7T98UICVnf4G9HDo,38447
21
+ bumble/gatt_client.py,sha256=UUOLszwNBbOG0x2nFuIAK2llAysj0zK4euXJxb2gVSo,42523
22
+ bumble/gatt_server.py,sha256=uPYbn2-y0MLnyR8xxpOf18gPua_Q49pSlMR1zxEnU-Q,37118
23
+ bumble/hci.py,sha256=3MYwWLuuolxY9xMitm5tOHpqvGKqtsReZ6QUfI1DcVA,267323
24
24
  bumble/helpers.py,sha256=m0w4UgFFNDEnXwHrDyfRlcBObdVed2fqXGL0lvR3c8s,12733
25
- bumble/hfp.py,sha256=N5_gO_1Jjk-RC9D8gtujRksPzQQxu6GceMt9sC4u70c,41657
26
- bumble/hid.py,sha256=GLlxOfJeknBX4ccf8qb-Cw3qYR3dZk6K4tCpi7dPdD0,20589
25
+ bumble/hfp.py,sha256=hc7IVZxsb7skfWrxWPyt0BXFQRMh9a7mdv--A9k5aNg,41865
26
+ bumble/hid.py,sha256=Dd4rsmkRxcxt1IjoozJdu9Qd-QWruKJfsiYqTT89NDk,20590
27
27
  bumble/host.py,sha256=tLFay8cdJIHl92UyVTvChKQXUh9QEFI3Ib6unYJLLHw,46909
28
- bumble/keys.py,sha256=_ibaJ4CxM5zyxnTp7wnihIQSsEAEkCiPxx9qHsGA04Q,12601
28
+ bumble/keys.py,sha256=58BMWd8LocY0bazVQ-qw3DKrOxgilhYaKBkmJRcNPp4,12593
29
29
  bumble/l2cap.py,sha256=8m_1Kv6Tk-M-DilkAz_OXx0XsiLUhXycEZjUkICwyj0,81064
30
30
  bumble/link.py,sha256=QiiMSCZ0z0ko2oUEMYg6nbq-h5A_3DLN4pjqAx_E-SA,23980
31
31
  bumble/pairing.py,sha256=tgPUba6xNxMi-2plm3xfRlzHq-uPRNZEIGWaN0qNGCs,9853
32
32
  bumble/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  bumble/rfcomm.py,sha256=rCkYaRNjwQ5HPRTat4CY9ZecU9qWQUi4OCB8_RUKeQc,35685
34
- bumble/sdp.py,sha256=0g5RpnN7_0A3wFWCDPbkv5s-OgMtL3SIKqIb_jvdoR8,45175
35
- bumble/smp.py,sha256=6O4hhqFdfjEsGcOMMxC6dNUEOHisAOnExiKoEYfEe0U,76275
34
+ bumble/sdp.py,sha256=_Jp3Ui7dwIm-1t5vvIDBzPOs_gLmFpnZBnPcYtgu6nY,45287
35
+ bumble/smp.py,sha256=PcQj8mDoM8fBc4gKECHoOs0A2ukUAaSZQGdgLj6YzB0,76277
36
36
  bumble/snoop.py,sha256=_QfF36eylBW6Snd-_KYOwKaGiM8i_Ed-B5XoFIPt3Dg,5631
37
- bumble/utils.py,sha256=fdOllb4SZduxHjnmEeUjKMqLD6L-wPWrya5Qlz0noRs,15089
37
+ bumble/utils.py,sha256=e0i-4d28-9zP3gYcd1rdNd669rkPnRs5oJCERUEDfxo,15099
38
38
  bumble/apps/README.md,sha256=XTwjRAY-EJWDXpl1V8K3Mw8B7kIqzUIUizRjVBVhoIE,1769
39
39
  bumble/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- bumble/apps/bench.py,sha256=4rUsETI73_2PydDAYqvQFyjQbKlN1nqKFy_2yRHuZ9k,52222
40
+ bumble/apps/bench.py,sha256=wwflVPDw_xaN_duZJF2oCrzAlIuJVR7rEKtVVTmzq1s,52359
41
41
  bumble/apps/ble_rpa_tool.py,sha256=ZQtsbfnLPd5qUAkEBPpNgJLRynBBc7q_9cDHKUW2SQ0,1701
42
42
  bumble/apps/console.py,sha256=rVR2jmP6Yd76B4zzGPYnpJFtgeYgq19CL6DMSe2-A1M,46093
43
43
  bumble/apps/controller_info.py,sha256=pgi6leHpwGdi3-kFUc7uFfuyGPTkNEoOws8cWycQVT0,9249
@@ -51,7 +51,7 @@ bumble/apps/pair.py,sha256=COU2D7YAIn4lo5iuM0ClObA1zZqQCdrXOcnsiCm0YlQ,17529
51
51
  bumble/apps/pandora_server.py,sha256=5qaoLCpcZE2KsGO21-7t6Vg4dBjBWbnyOQXwrLhxkuE,1397
52
52
  bumble/apps/scan.py,sha256=b6hIppiJqDfR7VFW2wl3-lkPdFvHLqYZKY8VjjNnhls,8366
53
53
  bumble/apps/show.py,sha256=8w0-8jLtN6IM6_58pOHbEmE1Rmxm71O48ACrXixC2jk,6218
54
- bumble/apps/unbond.py,sha256=P_zqdK_WsQHReqnhcaeeG3Kg6LhGBzCrRAyhcewQ7lU,3175
54
+ bumble/apps/unbond.py,sha256=LDPWpmgKLMGYDdIFGTdGciFDcUliZ0OmseEbGfJ-MAM,3176
55
55
  bumble/apps/usb_probe.py,sha256=zJqrqKSGVYcOntXzgONdluZDE6jfj3IwPNuLqmDPDsU,10351
56
56
  bumble/apps/link_relay/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  bumble/apps/link_relay/link_relay.py,sha256=GOESYPzkMJFrz5VOI_BSmnmgz4Y8EdSLHMWgdA63aDg,10066
@@ -61,7 +61,7 @@ bumble/apps/speaker/logo.svg,sha256=SQ9XXIqhh07BnGaBZ653nJ7vOslm2Dogdqadhg2MdE4,
61
61
  bumble/apps/speaker/speaker.css,sha256=nyM5TjzDYkkLwFzsaIOuTSngzSvgDnkLe0Z-fAn1_t4,1234
62
62
  bumble/apps/speaker/speaker.html,sha256=kfAZ5oZSFc9ygBFIUuZEn5LUNQnHBvrnuHU6VAptyiU,1188
63
63
  bumble/apps/speaker/speaker.js,sha256=DrT831yg3oBXKZ5usnfZjRU9X6Nw3zjIWSkz6sIgVtw,9373
64
- bumble/apps/speaker/speaker.py,sha256=lV4N-M8V95UwioTMfcfsVImvQ-jmMehU6jJhA_16A24,24196
64
+ bumble/apps/speaker/speaker.py,sha256=f7cOyVqD6HOiLPCgdcnwN7sakj2SScybVHVTBR6eFwk,24197
65
65
  bumble/drivers/__init__.py,sha256=lxqJTghh21rQFThRTurwLysZm385TUcn8ZdpHQSWD88,3196
66
66
  bumble/drivers/common.py,sha256=pS783hudolLZAzF8IUWp7g6TXyQsUCEzqCsd1VGeYfQ,1507
67
67
  bumble/drivers/intel.py,sha256=-YcJI4ZC_fhHHxWyE8b4eB8V7suOFH1n9uayckGE9Uw,3231
@@ -69,28 +69,28 @@ bumble/drivers/rtk.py,sha256=MMxmUo85VkRhFuhbc9SJEZVL9dnRjmsU9k8djmbUGcA,21369
69
69
  bumble/pandora/__init__.py,sha256=5NBVmndeTulANawift0jPT9ISp562wyIHTZ-4uP34Mg,3283
70
70
  bumble/pandora/config.py,sha256=KD85n3oRbuvD65sRah2H0gpxEW4YbD7HbYbsxdcpDDA,2388
71
71
  bumble/pandora/device.py,sha256=LFqCWrgYkQWrFUSKArsAABXkge8sB2DhvaQoEsC4Jn0,5344
72
- bumble/pandora/host.py,sha256=JPXAoCSONUCf7xpxmurNRqgK0wtwmPk9W4a5My0zWus,39055
72
+ bumble/pandora/host.py,sha256=d0qGQ769K9SSfBftEJcktTBebXZU6M8MMbh0xLYKwGk,39189
73
73
  bumble/pandora/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
- bumble/pandora/security.py,sha256=-YJvEGKAQfx6gAUOfiuaj6x80UqNSaG3kMZVuZJNY5E,21944
74
+ bumble/pandora/security.py,sha256=YErueKNLsnmcRe6dKo724Ht-buOqmZl2Gauswcc8FW0,21946
75
75
  bumble/pandora/utils.py,sha256=Fq4glL0T5cJ2FODoDotmDNdYFOkTOR7DyyL8vkcxp20,3949
76
76
  bumble/profiles/__init__.py,sha256=yBGC8Ti5LvZuoh1F42XtfrBilb39T77_yuxESZeX2yI,581
77
77
  bumble/profiles/asha_service.py,sha256=J4i5jkJciZWMtTWJ1zGJkEx65DlAEIADqjCRYf_CWNs,7220
78
- bumble/profiles/bap.py,sha256=GJOn1t7ZGcm-woFnI4JFx4I4Z_rnv5GQIB4dnrwULlY,44900
78
+ bumble/profiles/bap.py,sha256=jY0wHBIlc_Qxv6j-3rF_4nI4uM2z4I8WT99Teu4o0S8,46006
79
79
  bumble/profiles/battery_service.py,sha256=w-uF4jLoDozJOoykimb2RkrKjVyCke6ts2-h-F1PYyc,2292
80
80
  bumble/profiles/cap.py,sha256=6gH7oOnUKjOggMPuB7rtbwj0AneoNmnWzQ_iR3io8e0,1945
81
81
  bumble/profiles/csip.py,sha256=wzSpNRCOMWtKw2Yd9OTAzPoFDoQWG-KYwWdA6sUkwiI,10102
82
- bumble/profiles/device_information_service.py,sha256=H1Db4BAOnsC-rRtfpoAIsDETYT4F9yM_WgByn_3LfRQ,5658
82
+ bumble/profiles/device_information_service.py,sha256=MOMEY9AaMMNOJppJyniaHS-OeuXUdMNd4O9EE5gWd8Y,5657
83
83
  bumble/profiles/heart_rate_service.py,sha256=7V2LGcWLp6RurjWxsVgMWr3wPDt5aS9qjNxTbHcOK6o,8575
84
84
  bumble/profiles/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
85
  bumble/profiles/vcp.py,sha256=wkbTf2NRCbBtvpXplpNJq4dzXp6JGeaEHeeC1kHqW7s,7897
86
86
  bumble/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
87
  bumble/tools/generate_company_id_list.py,sha256=ysbPb3zmxKFBiSQ_MBG2r15-sqR5P_GWT6i0YUTTXOM,1736
88
- bumble/tools/rtk_fw_download.py,sha256=kTxR9UaNiD8VtzWVAVxsCx5c_tkfz9OKe-vxdlfKQRY,5454
88
+ bumble/tools/rtk_fw_download.py,sha256=KEPG-rDrdPGKBzZ78P4s3udLRYT3p7vesGhXvJTWTic,5453
89
89
  bumble/tools/rtk_util.py,sha256=TwZhupHQrQYsYHLdRGyzXKd24pwCk8kkzqK1Rj2guco,5087
90
90
  bumble/transport/__init__.py,sha256=W_IjqBehWCvjyTghgRYvbbLqDlh2xh7ZRDRvun5iYB0,6830
91
91
  bumble/transport/android_emulator.py,sha256=eH8H1aB7MvQ8lpdwVG6SGKg5uwCRb_aPJk8pPwoTXSY,4321
92
92
  bumble/transport/android_netsim.py,sha256=SVh-IUZ2bhcIESZFGzOsofybsi4H0qoBRwBieeqUINE,16215
93
- bumble/transport/common.py,sha256=gGjUOSS4qImh4rV9ZkcPqSOzXxNEVr1Vb-sPbaNuadY,15713
93
+ bumble/transport/common.py,sha256=1W8p2dMAlEhmmcS9DFtuM01BNl-LRsNQWcqjq6PfMPc,15697
94
94
  bumble/transport/file.py,sha256=eVM2V6Nk2nDAFdE7Rt01ZI3JdTovsH9OEU1gKYPJjpE,2010
95
95
  bumble/transport/hci_socket.py,sha256=EdgWi3-O5yvYcH4R4BkPtG79pnUo7GQtXWawuUHDoDQ,6331
96
96
  bumble/transport/pty.py,sha256=grTl-yvjMWHflNwuME4ccVqDbk6NIEgQMgH6Y9lf1fU,2732
@@ -98,9 +98,9 @@ bumble/transport/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
98
  bumble/transport/pyusb.py,sha256=RV42LSRlMhLx1LOdaF8TY4qePPGlONFaPqta7I5mYTw,11987
99
99
  bumble/transport/serial.py,sha256=loQxkeG7uE09enXWg2uGbxi6CeG70wn3kzPbEwULKw4,2446
100
100
  bumble/transport/tcp_client.py,sha256=deyUJYpj04QE00Mw_PTU5PHPA6mr1Nui3f5-QCy2zOw,1854
101
- bumble/transport/tcp_server.py,sha256=hixsSzB-fmzR1yuiHDWd1WhqAia3UA4Cog1Wu6DCLeg,3211
101
+ bumble/transport/tcp_server.py,sha256=qcpTeLFSkDWvqHEjYxtZ75wYvAKxa3LiwHJwT5bhn88,3778
102
102
  bumble/transport/udp.py,sha256=di8I6HHACgBx3un-dzAahz9lTIUrh4LdeuYpeoifQEM,2239
103
- bumble/transport/usb.py,sha256=tP5vV0ts8xh3EDnfgejCBWpqh53aximLJ4Hn0nDYncg,21401
103
+ bumble/transport/usb.py,sha256=dFNN-kGI3pMTXeT5Amwu2H6e4J48WAJotG_D18W3RBM,21399
104
104
  bumble/transport/vhci.py,sha256=iI2WpighnvIP5zeyJUFSbjEdmCo24CWMdICamIcyJck,2250
105
105
  bumble/transport/ws_client.py,sha256=9gqm5jlVT_H6LfwsQwPpky07CINhgOK96ef53SMAxms,1757
106
106
  bumble/transport/ws_server.py,sha256=goe4xx7OnZiJy1a00Bg0CXM8uJhsGXbsijMYq2n62bI,3328
@@ -137,9 +137,9 @@ bumble/vendor/android/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
137
137
  bumble/vendor/android/hci.py,sha256=GZrkhaWmcMt1JpnRhv0NoySGkf2H4lNUV2f_omRZW0I,10741
138
138
  bumble/vendor/zephyr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
139
  bumble/vendor/zephyr/hci.py,sha256=d83bC0TvT947eN4roFjLkQefWtHOoNsr4xib2ctSkvA,3195
140
- bumble-0.0.188.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
141
- bumble-0.0.188.dist-info/METADATA,sha256=PEkVrU3sS9sge_Kh9Z4rMt78J5ukWiET5IEcj7dImOI,5684
142
- bumble-0.0.188.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
143
- bumble-0.0.188.dist-info/entry_points.txt,sha256=UkNj1KMZDhzOb7O4OU7Jn4YI5KaxJZgQF2GF64BwOlQ,883
144
- bumble-0.0.188.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
145
- bumble-0.0.188.dist-info/RECORD,,
140
+ bumble-0.0.190.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
141
+ bumble-0.0.190.dist-info/METADATA,sha256=3toWetMEz1r3wfytRfmK4DjkdzspHLbhVbagGQxyJBk,5684
142
+ bumble-0.0.190.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
143
+ bumble-0.0.190.dist-info/entry_points.txt,sha256=UkNj1KMZDhzOb7O4OU7Jn4YI5KaxJZgQF2GF64BwOlQ,883
144
+ bumble-0.0.190.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
145
+ bumble-0.0.190.dist-info/RECORD,,