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