bumble 0.0.220__py3-none-any.whl → 0.0.222__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 +5 -5
- bumble/apps/auracast.py +746 -473
- bumble/apps/bench.py +4 -5
- bumble/apps/console.py +5 -10
- bumble/apps/controller_info.py +12 -7
- bumble/apps/controller_loopback.py +1 -2
- bumble/apps/device_info.py +2 -3
- bumble/apps/gatt_dump.py +0 -1
- bumble/apps/lea_unicast/app.py +1 -1
- bumble/apps/pair.py +49 -46
- bumble/apps/pandora_server.py +2 -2
- bumble/apps/player/player.py +10 -12
- bumble/apps/rfcomm_bridge.py +10 -11
- bumble/apps/scan.py +1 -3
- bumble/apps/speaker/speaker.py +3 -4
- bumble/at.py +4 -5
- bumble/att.py +91 -25
- bumble/audio/io.py +5 -3
- bumble/avc.py +1 -2
- bumble/avctp.py +2 -3
- bumble/avdtp.py +53 -57
- bumble/avrcp.py +25 -27
- bumble/codecs.py +15 -15
- bumble/colors.py +7 -8
- bumble/controller.py +663 -391
- bumble/core.py +41 -49
- bumble/crypto/__init__.py +2 -1
- bumble/crypto/builtin.py +2 -8
- bumble/data_types.py +2 -1
- bumble/decoder.py +2 -3
- bumble/device.py +171 -142
- bumble/drivers/__init__.py +3 -2
- bumble/drivers/intel.py +6 -8
- bumble/drivers/rtk.py +1 -1
- bumble/gatt.py +9 -9
- bumble/gatt_adapters.py +6 -6
- bumble/gatt_client.py +110 -60
- bumble/gatt_server.py +209 -139
- bumble/hci.py +87 -74
- bumble/helpers.py +5 -5
- bumble/hfp.py +27 -26
- bumble/hid.py +9 -9
- bumble/host.py +44 -50
- bumble/keys.py +17 -17
- bumble/l2cap.py +1070 -218
- bumble/link.py +26 -159
- bumble/ll.py +200 -0
- bumble/pairing.py +14 -15
- bumble/pandora/__init__.py +2 -2
- bumble/pandora/device.py +6 -4
- bumble/pandora/host.py +19 -10
- bumble/pandora/l2cap.py +8 -9
- bumble/pandora/security.py +18 -16
- bumble/pandora/utils.py +4 -4
- bumble/profiles/aics.py +6 -8
- bumble/profiles/ams.py +3 -5
- bumble/profiles/ancs.py +11 -11
- bumble/profiles/ascs.py +5 -5
- bumble/profiles/asha.py +10 -9
- bumble/profiles/bass.py +9 -3
- bumble/profiles/battery_service.py +1 -2
- bumble/profiles/csip.py +9 -10
- bumble/profiles/device_information_service.py +16 -17
- bumble/profiles/gap.py +3 -4
- bumble/profiles/gatt_service.py +0 -1
- bumble/profiles/gmap.py +12 -13
- bumble/profiles/hap.py +3 -3
- bumble/profiles/heart_rate_service.py +7 -8
- bumble/profiles/le_audio.py +1 -1
- bumble/profiles/mcp.py +28 -28
- bumble/profiles/pacs.py +13 -17
- bumble/profiles/pbp.py +16 -0
- bumble/profiles/vcs.py +2 -2
- bumble/profiles/vocs.py +6 -9
- bumble/rfcomm.py +19 -18
- bumble/sdp.py +12 -11
- bumble/smp.py +20 -30
- bumble/snoop.py +2 -1
- bumble/tools/generate_company_id_list.py +1 -1
- bumble/tools/intel_util.py +2 -2
- bumble/tools/rtk_fw_download.py +1 -1
- bumble/tools/rtk_util.py +1 -1
- bumble/transport/__init__.py +1 -2
- bumble/transport/android_emulator.py +2 -3
- bumble/transport/android_netsim.py +49 -40
- bumble/transport/common.py +9 -9
- bumble/transport/file.py +1 -2
- bumble/transport/hci_socket.py +2 -3
- bumble/transport/pty.py +3 -5
- bumble/transport/pyusb.py +8 -5
- bumble/transport/serial.py +1 -2
- bumble/transport/vhci.py +1 -2
- bumble/transport/ws_server.py +2 -3
- bumble/utils.py +22 -9
- bumble/vendor/android/hci.py +4 -2
- {bumble-0.0.220.dist-info → bumble-0.0.222.dist-info}/METADATA +3 -2
- {bumble-0.0.220.dist-info → bumble-0.0.222.dist-info}/RECORD +102 -101
- {bumble-0.0.220.dist-info → bumble-0.0.222.dist-info}/WHEEL +0 -0
- {bumble-0.0.220.dist-info → bumble-0.0.222.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.220.dist-info → bumble-0.0.222.dist-info}/licenses/LICENSE +0 -0
- {bumble-0.0.220.dist-info → bumble-0.0.222.dist-info}/top_level.txt +0 -0
bumble/controller.py
CHANGED
|
@@ -23,14 +23,14 @@ import itertools
|
|
|
23
23
|
import logging
|
|
24
24
|
import random
|
|
25
25
|
import struct
|
|
26
|
-
from typing import TYPE_CHECKING, Any,
|
|
26
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
27
27
|
|
|
28
|
-
from bumble import hci, lmp
|
|
28
|
+
from bumble import hci, link, ll, lmp
|
|
29
|
+
from bumble import link as bumble_link
|
|
29
30
|
from bumble.colors import color
|
|
30
31
|
from bumble.core import PhysicalTransport
|
|
31
32
|
|
|
32
33
|
if TYPE_CHECKING:
|
|
33
|
-
from bumble.link import LocalLink
|
|
34
34
|
from bumble.transport.common import TransportSink
|
|
35
35
|
|
|
36
36
|
# -----------------------------------------------------------------------------
|
|
@@ -52,10 +52,128 @@ class CisLink:
|
|
|
52
52
|
handle: int
|
|
53
53
|
cis_id: int
|
|
54
54
|
cig_id: int
|
|
55
|
-
acl_connection:
|
|
55
|
+
acl_connection: Connection | None = None
|
|
56
56
|
data_paths: set[int] = dataclasses.field(default_factory=set)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
+
# -----------------------------------------------------------------------------
|
|
60
|
+
@dataclasses.dataclass
|
|
61
|
+
class LegacyAdvertiser:
|
|
62
|
+
controller: Controller
|
|
63
|
+
advertising_interval_min: int = 0
|
|
64
|
+
advertising_interval_max: int = 0
|
|
65
|
+
advertising_type: int = 0
|
|
66
|
+
own_address_type: int = 0
|
|
67
|
+
peer_address_type: int = 0
|
|
68
|
+
peer_address: hci.Address = hci.Address.ANY
|
|
69
|
+
advertising_channel_map: int = 0
|
|
70
|
+
advertising_filter_policy: int = 0
|
|
71
|
+
|
|
72
|
+
advertising_data: bytes = b''
|
|
73
|
+
scan_response_data: bytes = b''
|
|
74
|
+
|
|
75
|
+
enabled: bool = False
|
|
76
|
+
timer_handle: asyncio.Handle | None = None
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def address(self) -> hci.Address:
|
|
80
|
+
'''Address used in advertising PDU.'''
|
|
81
|
+
if self.own_address_type == hci.Address.PUBLIC_DEVICE_ADDRESS:
|
|
82
|
+
return self.controller.public_address
|
|
83
|
+
else:
|
|
84
|
+
return self.controller.random_address
|
|
85
|
+
|
|
86
|
+
def _on_timer_fired(self) -> None:
|
|
87
|
+
self.send_advertising_data()
|
|
88
|
+
self.timer_handle = asyncio.get_running_loop().call_later(
|
|
89
|
+
self.advertising_interval_min / 1000.0, self._on_timer_fired
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def start(self) -> None:
|
|
93
|
+
# Stop any ongoing advertising before we start again
|
|
94
|
+
self.stop()
|
|
95
|
+
self.enabled = True
|
|
96
|
+
|
|
97
|
+
# Advertise now
|
|
98
|
+
self.timer_handle = asyncio.get_running_loop().call_soon(self._on_timer_fired)
|
|
99
|
+
|
|
100
|
+
def stop(self) -> None:
|
|
101
|
+
if self.timer_handle is not None:
|
|
102
|
+
self.timer_handle.cancel()
|
|
103
|
+
self.timer_handle = None
|
|
104
|
+
self.enabled = False
|
|
105
|
+
|
|
106
|
+
def send_advertising_data(self) -> None:
|
|
107
|
+
if not self.enabled:
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
if (
|
|
111
|
+
self.advertising_type
|
|
112
|
+
== hci.HCI_LE_Set_Advertising_Parameters_Command.AdvertisingType.ADV_IND
|
|
113
|
+
):
|
|
114
|
+
self.controller.send_advertising_pdu(
|
|
115
|
+
ll.AdvInd(
|
|
116
|
+
advertiser_address=self.address,
|
|
117
|
+
data=self.advertising_data,
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# -----------------------------------------------------------------------------
|
|
123
|
+
@dataclasses.dataclass
|
|
124
|
+
class AdvertisingSet:
|
|
125
|
+
controller: Controller
|
|
126
|
+
handle: int
|
|
127
|
+
parameters: hci.HCI_LE_Set_Extended_Advertising_Parameters_Command | None = None
|
|
128
|
+
data: bytearray = dataclasses.field(default_factory=bytearray)
|
|
129
|
+
scan_response_data: bytearray = dataclasses.field(default_factory=bytearray)
|
|
130
|
+
enabled: bool = False
|
|
131
|
+
timer_handle: asyncio.Handle | None = None
|
|
132
|
+
random_address: hci.Address | None = None
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def address(self) -> hci.Address | None:
|
|
136
|
+
'''Address used in advertising PDU.'''
|
|
137
|
+
if not self.parameters:
|
|
138
|
+
return None
|
|
139
|
+
if self.parameters.own_address_type == hci.Address.PUBLIC_DEVICE_ADDRESS:
|
|
140
|
+
return self.controller.public_address
|
|
141
|
+
else:
|
|
142
|
+
return self.random_address
|
|
143
|
+
|
|
144
|
+
def _on_extended_advertising_timer_fired(self) -> None:
|
|
145
|
+
if not self.enabled:
|
|
146
|
+
return
|
|
147
|
+
|
|
148
|
+
self.send_extended_advertising_data()
|
|
149
|
+
|
|
150
|
+
interval = (
|
|
151
|
+
self.parameters.primary_advertising_interval_min * 0.625 / 1000.0
|
|
152
|
+
if self.parameters
|
|
153
|
+
else 1.0
|
|
154
|
+
)
|
|
155
|
+
self.timer_handle = asyncio.get_running_loop().call_later(
|
|
156
|
+
interval, self._on_extended_advertising_timer_fired
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def start(self) -> None:
|
|
160
|
+
self.enabled = True
|
|
161
|
+
asyncio.get_running_loop().call_soon(self._on_extended_advertising_timer_fired)
|
|
162
|
+
|
|
163
|
+
def stop(self) -> None:
|
|
164
|
+
self.enabled = False
|
|
165
|
+
if timer_handle := self.timer_handle:
|
|
166
|
+
timer_handle.cancel()
|
|
167
|
+
self.timer_handle = None
|
|
168
|
+
|
|
169
|
+
def send_extended_advertising_data(self) -> None:
|
|
170
|
+
if self.controller.link:
|
|
171
|
+
address = self.address
|
|
172
|
+
assert address
|
|
173
|
+
|
|
174
|
+
self.controller.send_advertising_pdu(ll.AdvInd(address, bytes(self.data)))
|
|
175
|
+
|
|
176
|
+
|
|
59
177
|
# -----------------------------------------------------------------------------
|
|
60
178
|
@dataclasses.dataclass
|
|
61
179
|
class ScoLink:
|
|
@@ -70,9 +188,10 @@ class Connection:
|
|
|
70
188
|
controller: Controller
|
|
71
189
|
handle: int
|
|
72
190
|
role: hci.Role
|
|
191
|
+
self_address: hci.Address
|
|
73
192
|
peer_address: hci.Address
|
|
74
|
-
link:
|
|
75
|
-
transport:
|
|
193
|
+
link: link.LocalLink
|
|
194
|
+
transport: PhysicalTransport
|
|
76
195
|
link_type: int
|
|
77
196
|
classic_allow_role_switch: bool = False
|
|
78
197
|
|
|
@@ -93,22 +212,27 @@ class Connection:
|
|
|
93
212
|
self.controller, self.peer_address, self.transport, pdu
|
|
94
213
|
)
|
|
95
214
|
|
|
215
|
+
def send_ll_control_pdu(self, packet: ll.ControlPdu) -> None:
|
|
216
|
+
if self.link:
|
|
217
|
+
self.link.send_ll_control_pdu(
|
|
218
|
+
sender_address=self.self_address,
|
|
219
|
+
receiver_address=self.peer_address,
|
|
220
|
+
packet=packet,
|
|
221
|
+
)
|
|
222
|
+
|
|
96
223
|
|
|
97
224
|
# -----------------------------------------------------------------------------
|
|
98
225
|
class Controller:
|
|
99
|
-
hci_sink:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
hci.Address, Connection
|
|
103
|
-
] # Connections where this controller is the central
|
|
104
|
-
peripheral_connections: dict[
|
|
105
|
-
hci.Address, Connection
|
|
106
|
-
] # Connections where this controller is the peripheral
|
|
226
|
+
hci_sink: TransportSink | None = None
|
|
227
|
+
|
|
228
|
+
le_connections: dict[hci.Address, Connection] # LE Connections
|
|
107
229
|
classic_connections: dict[hci.Address, Connection] # Connections in BR/EDR
|
|
108
230
|
classic_pending_commands: dict[hci.Address, dict[lmp.Opcode, asyncio.Future[int]]]
|
|
109
231
|
sco_links: dict[hci.Address, ScoLink] # SCO links by address
|
|
110
232
|
central_cis_links: dict[int, CisLink] # CIS links by handle
|
|
111
233
|
peripheral_cis_links: dict[int, CisLink] # CIS links by handle
|
|
234
|
+
advertising_sets: dict[int, AdvertisingSet] # Advertising sets by handle
|
|
235
|
+
le_legacy_advertiser: LegacyAdvertiser
|
|
112
236
|
|
|
113
237
|
hci_version: int = hci.HCI_VERSION_BLUETOOTH_CORE_5_0
|
|
114
238
|
hci_revision: int = 0
|
|
@@ -131,10 +255,20 @@ class Controller:
|
|
|
131
255
|
'30f0f9ff01008004002000000000000000000000000000000000000000000000'
|
|
132
256
|
)
|
|
133
257
|
le_event_mask: int = 0
|
|
134
|
-
|
|
135
|
-
|
|
258
|
+
le_features: hci.LeFeatureMask = (
|
|
259
|
+
hci.LeFeatureMask.LE_ENCRYPTION
|
|
260
|
+
| hci.LeFeatureMask.CONNECTION_PARAMETERS_REQUEST_PROCEDURE
|
|
261
|
+
| hci.LeFeatureMask.EXTENDED_REJECT_INDICATION
|
|
262
|
+
| hci.LeFeatureMask.PERIPHERAL_INITIATED_FEATURE_EXCHANGE
|
|
263
|
+
| hci.LeFeatureMask.LE_PING
|
|
264
|
+
| hci.LeFeatureMask.LE_DATA_PACKET_LENGTH_EXTENSION
|
|
265
|
+
| hci.LeFeatureMask.LL_PRIVACY
|
|
266
|
+
| hci.LeFeatureMask.EXTENDED_SCANNER_FILTER_POLICIES
|
|
267
|
+
| hci.LeFeatureMask.LE_2M_PHY
|
|
268
|
+
| hci.LeFeatureMask.LE_CODED_PHY
|
|
269
|
+
| hci.LeFeatureMask.CHANNEL_SELECTION_ALGORITHM_2
|
|
270
|
+
| hci.LeFeatureMask.MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE
|
|
136
271
|
)
|
|
137
|
-
le_features: bytes = bytes.fromhex('ff49010000000000')
|
|
138
272
|
le_states: bytes = bytes.fromhex('ffff3fffff030000')
|
|
139
273
|
advertising_channel_tx_power: int = 0
|
|
140
274
|
filter_accept_list_size: int = 8
|
|
@@ -150,19 +284,23 @@ class Controller:
|
|
|
150
284
|
le_scan_type: int = 0
|
|
151
285
|
le_scan_interval: int = 0x10
|
|
152
286
|
le_scan_window: int = 0x10
|
|
153
|
-
le_scan_enable:
|
|
287
|
+
le_scan_enable: bool = False
|
|
154
288
|
le_scan_own_address_type: int = hci.Address.RANDOM_DEVICE_ADDRESS
|
|
155
289
|
le_scanning_filter_policy: int = 0
|
|
156
|
-
le_scan_response_data: Optional[bytes] = None
|
|
157
290
|
le_address_resolution: bool = False
|
|
158
291
|
le_rpa_timeout: int = 0
|
|
159
292
|
sync_flow_control: bool = False
|
|
160
293
|
local_name: str = 'Bumble'
|
|
161
294
|
advertising_interval: int = 2000
|
|
162
|
-
advertising_data:
|
|
163
|
-
advertising_timer_handle:
|
|
295
|
+
advertising_data: bytes | None = None
|
|
296
|
+
advertising_timer_handle: asyncio.Handle | None = None
|
|
164
297
|
classic_scan_enable: int = 0
|
|
165
298
|
classic_allow_role_switch: bool = True
|
|
299
|
+
pending_le_connection: (
|
|
300
|
+
hci.HCI_LE_Create_Connection_Command
|
|
301
|
+
| hci.HCI_LE_Extended_Create_Connection_Command
|
|
302
|
+
| None
|
|
303
|
+
) = None
|
|
166
304
|
|
|
167
305
|
_random_address: hci.Address = hci.Address('00:00:00:00:00:00')
|
|
168
306
|
|
|
@@ -170,24 +308,25 @@ class Controller:
|
|
|
170
308
|
self,
|
|
171
309
|
name: str,
|
|
172
310
|
host_source=None,
|
|
173
|
-
host_sink:
|
|
174
|
-
link:
|
|
175
|
-
public_address:
|
|
311
|
+
host_sink: TransportSink | None = None,
|
|
312
|
+
link: link.LocalLink | None = None,
|
|
313
|
+
public_address: bytes | str | hci.Address | None = None,
|
|
176
314
|
) -> None:
|
|
177
315
|
self.name = name
|
|
178
|
-
self.link = link
|
|
179
|
-
self.
|
|
180
|
-
self.peripheral_connections = {}
|
|
316
|
+
self.link = link or bumble_link.LocalLink()
|
|
317
|
+
self.le_connections = {}
|
|
181
318
|
self.classic_connections = {}
|
|
182
319
|
self.sco_links = {}
|
|
183
320
|
self.classic_pending_commands = {}
|
|
184
321
|
self.central_cis_links = {}
|
|
185
322
|
self.peripheral_cis_links = {}
|
|
323
|
+
self.advertising_sets = {}
|
|
186
324
|
self.default_phy = {
|
|
187
325
|
'all_phys': 0,
|
|
188
326
|
'tx_phys': 0,
|
|
189
327
|
'rx_phys': 0,
|
|
190
328
|
}
|
|
329
|
+
self.le_legacy_advertiser = LegacyAdvertiser(self)
|
|
191
330
|
|
|
192
331
|
if isinstance(public_address, hci.Address):
|
|
193
332
|
self._public_address = public_address
|
|
@@ -212,18 +351,18 @@ class Controller:
|
|
|
212
351
|
)
|
|
213
352
|
|
|
214
353
|
@property
|
|
215
|
-
def host(self) ->
|
|
354
|
+
def host(self) -> TransportSink | None:
|
|
216
355
|
return self.hci_sink
|
|
217
356
|
|
|
218
357
|
@host.setter
|
|
219
|
-
def host(self, host:
|
|
358
|
+
def host(self, host: TransportSink | None) -> None:
|
|
220
359
|
'''
|
|
221
360
|
Sets the host (sink) for this controller, and set this controller as the
|
|
222
361
|
controller (sink) for the host
|
|
223
362
|
'''
|
|
224
363
|
self.set_packet_sink(host)
|
|
225
364
|
|
|
226
|
-
def set_packet_sink(self, sink:
|
|
365
|
+
def set_packet_sink(self, sink: TransportSink | None) -> None:
|
|
227
366
|
'''
|
|
228
367
|
Method from the Packet Source interface
|
|
229
368
|
'''
|
|
@@ -234,7 +373,7 @@ class Controller:
|
|
|
234
373
|
return self._public_address
|
|
235
374
|
|
|
236
375
|
@public_address.setter
|
|
237
|
-
def public_address(self, address:
|
|
376
|
+
def public_address(self, address: hci.Address | str) -> None:
|
|
238
377
|
if isinstance(address, str):
|
|
239
378
|
address = hci.Address(address)
|
|
240
379
|
self._public_address = address
|
|
@@ -244,7 +383,7 @@ class Controller:
|
|
|
244
383
|
return self._random_address
|
|
245
384
|
|
|
246
385
|
@random_address.setter
|
|
247
|
-
def random_address(self, address:
|
|
386
|
+
def random_address(self, address: hci.Address | str) -> None:
|
|
248
387
|
if isinstance(address, str):
|
|
249
388
|
address = hci.Address(address)
|
|
250
389
|
self._random_address = address
|
|
@@ -276,7 +415,7 @@ class Controller:
|
|
|
276
415
|
def on_hci_command_packet(self, command: hci.HCI_Command) -> None:
|
|
277
416
|
handler_name = f'on_{command.name.lower()}'
|
|
278
417
|
handler = getattr(self, handler_name, self.on_hci_command)
|
|
279
|
-
result:
|
|
418
|
+
result: bytes | None = handler(command)
|
|
280
419
|
if isinstance(result, bytes):
|
|
281
420
|
self.send_hci_packet(
|
|
282
421
|
hci.HCI_Command_Complete_Event(
|
|
@@ -320,8 +459,7 @@ class Controller:
|
|
|
320
459
|
current_handles = set(
|
|
321
460
|
cast(Connection | CisLink | ScoLink, link).handle
|
|
322
461
|
for link in itertools.chain(
|
|
323
|
-
self.
|
|
324
|
-
self.peripheral_connections.values(),
|
|
462
|
+
self.le_connections.values(),
|
|
325
463
|
self.classic_connections.values(),
|
|
326
464
|
self.sco_links.values(),
|
|
327
465
|
self.central_cis_links.values(),
|
|
@@ -329,82 +467,106 @@ class Controller:
|
|
|
329
467
|
)
|
|
330
468
|
)
|
|
331
469
|
return next(
|
|
332
|
-
handle
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
def find_le_connection_by_address(
|
|
336
|
-
self, address: hci.Address
|
|
337
|
-
) -> Optional[Connection]:
|
|
338
|
-
return self.central_connections.get(address) or self.peripheral_connections.get(
|
|
339
|
-
address
|
|
470
|
+
handle
|
|
471
|
+
for handle in range(0x0001, 0xEFF + 1)
|
|
472
|
+
if handle not in current_handles
|
|
340
473
|
)
|
|
341
474
|
|
|
342
|
-
def
|
|
343
|
-
self, address: hci.Address
|
|
344
|
-
) -> Optional[Connection]:
|
|
345
|
-
return self.classic_connections.get(address)
|
|
346
|
-
|
|
347
|
-
def find_connection_by_handle(self, handle: int) -> Optional[Connection]:
|
|
475
|
+
def find_connection_by_handle(self, handle: int) -> Connection | None:
|
|
348
476
|
for connection in itertools.chain(
|
|
349
|
-
self.
|
|
350
|
-
self.peripheral_connections.values(),
|
|
477
|
+
self.le_connections.values(),
|
|
351
478
|
self.classic_connections.values(),
|
|
352
479
|
):
|
|
353
480
|
if connection.handle == handle:
|
|
354
481
|
return connection
|
|
355
482
|
return None
|
|
356
483
|
|
|
357
|
-
def
|
|
358
|
-
for connection in self.central_connections.values():
|
|
359
|
-
if connection.handle == handle:
|
|
360
|
-
return connection
|
|
361
|
-
return None
|
|
362
|
-
|
|
363
|
-
def find_peripheral_connection_by_handle(self, handle: int) -> Optional[Connection]:
|
|
364
|
-
for connection in self.peripheral_connections.values():
|
|
365
|
-
if connection.handle == handle:
|
|
366
|
-
return connection
|
|
367
|
-
return None
|
|
368
|
-
|
|
369
|
-
def find_classic_connection_by_handle(self, handle: int) -> Optional[Connection]:
|
|
370
|
-
for connection in self.classic_connections.values():
|
|
371
|
-
if connection.handle == handle:
|
|
372
|
-
return connection
|
|
373
|
-
return None
|
|
374
|
-
|
|
375
|
-
def find_classic_sco_link_by_handle(self, handle: int) -> Optional[ScoLink]:
|
|
484
|
+
def find_classic_sco_link_by_handle(self, handle: int) -> ScoLink | None:
|
|
376
485
|
for connection in self.sco_links.values():
|
|
377
486
|
if connection.handle == handle:
|
|
378
487
|
return connection
|
|
379
488
|
return None
|
|
380
489
|
|
|
381
|
-
def find_iso_link_by_handle(self, handle: int) ->
|
|
490
|
+
def find_iso_link_by_handle(self, handle: int) -> CisLink | None:
|
|
382
491
|
return self.central_cis_links.get(handle) or self.peripheral_cis_links.get(
|
|
383
492
|
handle
|
|
384
493
|
)
|
|
385
494
|
|
|
386
|
-
def
|
|
495
|
+
def send_advertising_pdu(self, packet: ll.AdvertisingPdu) -> None:
|
|
496
|
+
logger.debug("[%s] >>> Advertising PDU: %s", self.name, packet)
|
|
497
|
+
if self.link:
|
|
498
|
+
self.link.send_advertising_pdu(self, packet)
|
|
499
|
+
|
|
500
|
+
def on_ll_control_pdu(
|
|
501
|
+
self, sender_address: hci.Address, packet: ll.ControlPdu
|
|
502
|
+
) -> None:
|
|
503
|
+
logger.debug("[%s] >>> LL Control PDU: %s", self.name, packet)
|
|
504
|
+
if not (connection := self.le_connections.get(sender_address)):
|
|
505
|
+
logger.error("Cannot find a connection for %s", sender_address)
|
|
506
|
+
return
|
|
507
|
+
|
|
508
|
+
if isinstance(packet, ll.TerminateInd):
|
|
509
|
+
self.on_le_disconnected(connection, packet.error_code)
|
|
510
|
+
elif isinstance(packet, ll.CisReq):
|
|
511
|
+
self.on_le_cis_request(connection, packet.cig_id, packet.cis_id)
|
|
512
|
+
elif isinstance(packet, ll.CisRsp):
|
|
513
|
+
self.on_le_cis_established(packet.cig_id, packet.cis_id)
|
|
514
|
+
connection.send_ll_control_pdu(ll.CisInd(packet.cig_id, packet.cis_id))
|
|
515
|
+
elif isinstance(packet, ll.CisInd):
|
|
516
|
+
self.on_le_cis_established(packet.cig_id, packet.cis_id)
|
|
517
|
+
elif isinstance(packet, ll.CisTerminateInd):
|
|
518
|
+
self.on_le_cis_disconnected(packet.cig_id, packet.cis_id)
|
|
519
|
+
elif isinstance(packet, ll.EncReq):
|
|
520
|
+
self.on_le_encrypted(connection)
|
|
521
|
+
|
|
522
|
+
def on_ll_advertising_pdu(self, packet: ll.AdvertisingPdu) -> None:
|
|
523
|
+
logger.debug("[%s] <<< Advertising PDU: %s", self.name, packet)
|
|
524
|
+
if isinstance(packet, ll.ConnectInd):
|
|
525
|
+
self.on_le_connect_ind(packet)
|
|
526
|
+
elif isinstance(packet, (ll.AdvInd, ll.AdvExtInd)):
|
|
527
|
+
self.on_advertising_pdu(packet)
|
|
528
|
+
|
|
529
|
+
def on_le_connect_ind(self, packet: ll.ConnectInd) -> None:
|
|
387
530
|
'''
|
|
388
531
|
Called when an incoming connection occurs from a central on the link
|
|
389
532
|
'''
|
|
533
|
+
advertiser: LegacyAdvertiser | AdvertisingSet | None
|
|
534
|
+
if (
|
|
535
|
+
self.le_legacy_advertiser.address == packet.advertiser_address
|
|
536
|
+
and self.le_legacy_advertiser.enabled
|
|
537
|
+
):
|
|
538
|
+
advertiser = self.le_legacy_advertiser
|
|
539
|
+
else:
|
|
540
|
+
advertiser = next(
|
|
541
|
+
(
|
|
542
|
+
advertising_set
|
|
543
|
+
for advertising_set in self.advertising_sets.values()
|
|
544
|
+
if advertising_set.address == packet.advertiser_address
|
|
545
|
+
and advertising_set.enabled
|
|
546
|
+
),
|
|
547
|
+
None,
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
if not advertiser:
|
|
551
|
+
# This is not send to us.
|
|
552
|
+
return
|
|
390
553
|
|
|
391
554
|
# Allocate (or reuse) a connection handle
|
|
392
|
-
peer_address =
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
logger.debug(f'New PERIPHERAL connection handle: 0x{connection_handle:04X}')
|
|
555
|
+
peer_address = packet.initiator_address
|
|
556
|
+
|
|
557
|
+
connection_handle = self.allocate_connection_handle()
|
|
558
|
+
connection = Connection(
|
|
559
|
+
controller=self,
|
|
560
|
+
handle=connection_handle,
|
|
561
|
+
role=hci.Role.PERIPHERAL,
|
|
562
|
+
self_address=packet.advertiser_address,
|
|
563
|
+
peer_address=peer_address,
|
|
564
|
+
link=self.link,
|
|
565
|
+
transport=PhysicalTransport.LE,
|
|
566
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
567
|
+
)
|
|
568
|
+
self.le_connections[peer_address] = connection
|
|
569
|
+
logger.debug(f'New PERIPHERAL connection handle: 0x{connection_handle:04X}')
|
|
408
570
|
|
|
409
571
|
# Then say that the connection has completed
|
|
410
572
|
self.send_hci_packet(
|
|
@@ -412,7 +574,7 @@ class Controller:
|
|
|
412
574
|
status=hci.HCI_SUCCESS,
|
|
413
575
|
connection_handle=connection.handle,
|
|
414
576
|
role=connection.role,
|
|
415
|
-
peer_address_type=
|
|
577
|
+
peer_address_type=peer_address.address_type,
|
|
416
578
|
peer_address=peer_address,
|
|
417
579
|
connection_interval=10, # FIXME
|
|
418
580
|
peripheral_latency=0, # FIXME
|
|
@@ -421,131 +583,113 @@ class Controller:
|
|
|
421
583
|
)
|
|
422
584
|
)
|
|
423
585
|
|
|
424
|
-
|
|
425
|
-
'''
|
|
426
|
-
Called when an active disconnection occurs from a peer
|
|
427
|
-
'''
|
|
428
|
-
|
|
429
|
-
# Send a disconnection complete event
|
|
430
|
-
if connection := self.peripheral_connections.get(peer_address):
|
|
586
|
+
if isinstance(advertiser, AdvertisingSet):
|
|
431
587
|
self.send_hci_packet(
|
|
432
|
-
hci.
|
|
588
|
+
hci.HCI_LE_Advertising_Set_Terminated_Event(
|
|
433
589
|
status=hci.HCI_SUCCESS,
|
|
590
|
+
advertising_handle=advertiser.handle,
|
|
434
591
|
connection_handle=connection.handle,
|
|
435
|
-
|
|
592
|
+
num_completed_extended_advertising_events=0,
|
|
436
593
|
)
|
|
437
594
|
)
|
|
595
|
+
advertiser.stop()
|
|
438
596
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
hci.
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
reason=reason,
|
|
447
|
-
)
|
|
597
|
+
def on_le_disconnected(self, connection: Connection, reason: int) -> None:
|
|
598
|
+
# Send a disconnection complete event
|
|
599
|
+
self.send_hci_packet(
|
|
600
|
+
hci.HCI_Disconnection_Complete_Event(
|
|
601
|
+
status=hci.HCI_SUCCESS,
|
|
602
|
+
connection_handle=connection.handle,
|
|
603
|
+
reason=reason,
|
|
448
604
|
)
|
|
605
|
+
)
|
|
449
606
|
|
|
450
|
-
|
|
451
|
-
del self.central_connections[peer_address]
|
|
452
|
-
else:
|
|
453
|
-
logger.warning(f'!!! No peripheral connection found for {peer_address}')
|
|
454
|
-
|
|
455
|
-
def on_link_peripheral_connection_complete(
|
|
456
|
-
self,
|
|
457
|
-
le_create_connection_command: hci.HCI_LE_Create_Connection_Command,
|
|
458
|
-
status: int,
|
|
459
|
-
) -> None:
|
|
607
|
+
def create_le_connection(self, peer_address: hci.Address) -> None:
|
|
460
608
|
'''
|
|
461
|
-
Called
|
|
609
|
+
Called when we receive advertisement matching connection filter.
|
|
462
610
|
'''
|
|
611
|
+
pending_le_connection = self.pending_le_connection
|
|
612
|
+
assert pending_le_connection
|
|
463
613
|
|
|
464
|
-
if
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
614
|
+
if self.le_connections.get(peer_address):
|
|
615
|
+
logger.error("Connection for %s already exists?", peer_address)
|
|
616
|
+
return
|
|
617
|
+
|
|
618
|
+
self_address = (
|
|
619
|
+
self.public_address
|
|
620
|
+
if pending_le_connection.own_address_type == hci.OwnAddressType.PUBLIC
|
|
621
|
+
else self.random_address
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
# Allocate (or reuse) a connection handle
|
|
625
|
+
peer_address = pending_le_connection.peer_address
|
|
626
|
+
connection_handle = self.allocate_connection_handle()
|
|
627
|
+
connection = Connection(
|
|
628
|
+
controller=self,
|
|
629
|
+
handle=connection_handle,
|
|
630
|
+
role=hci.Role.CENTRAL,
|
|
631
|
+
self_address=self_address,
|
|
632
|
+
peer_address=peer_address,
|
|
633
|
+
link=self.link,
|
|
634
|
+
transport=PhysicalTransport.LE,
|
|
635
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
636
|
+
)
|
|
637
|
+
self.le_connections[peer_address] = connection
|
|
638
|
+
logger.debug(f'New CENTRAL connection handle: 0x{connection_handle:04X}')
|
|
639
|
+
|
|
640
|
+
if isinstance(
|
|
641
|
+
pending_le_connection, hci.HCI_LE_Extended_Create_Connection_Command
|
|
642
|
+
):
|
|
643
|
+
interval = pending_le_connection.connection_interval_mins[0]
|
|
644
|
+
latency = pending_le_connection.max_latencies[0]
|
|
645
|
+
timeout = pending_le_connection.supervision_timeouts[0]
|
|
483
646
|
else:
|
|
484
|
-
|
|
647
|
+
interval = pending_le_connection.connection_interval_min
|
|
648
|
+
latency = pending_le_connection.max_latency
|
|
649
|
+
timeout = pending_le_connection.supervision_timeout
|
|
485
650
|
|
|
651
|
+
self.send_advertising_pdu(
|
|
652
|
+
ll.ConnectInd(
|
|
653
|
+
initiator_address=self_address,
|
|
654
|
+
advertiser_address=peer_address,
|
|
655
|
+
interval=interval,
|
|
656
|
+
latency=latency,
|
|
657
|
+
timeout=timeout,
|
|
658
|
+
)
|
|
659
|
+
)
|
|
486
660
|
# Say that the connection has completed
|
|
487
661
|
self.send_hci_packet(
|
|
488
662
|
# pylint: disable=line-too-long
|
|
489
663
|
hci.HCI_LE_Connection_Complete_Event(
|
|
490
|
-
status=
|
|
664
|
+
status=hci.HCI_SUCCESS,
|
|
491
665
|
connection_handle=connection.handle if connection else 0,
|
|
492
666
|
role=hci.Role.CENTRAL,
|
|
493
|
-
peer_address_type=
|
|
494
|
-
peer_address=
|
|
495
|
-
connection_interval=
|
|
496
|
-
peripheral_latency=
|
|
497
|
-
supervision_timeout=
|
|
667
|
+
peer_address_type=peer_address.address_type,
|
|
668
|
+
peer_address=peer_address,
|
|
669
|
+
connection_interval=interval,
|
|
670
|
+
peripheral_latency=latency,
|
|
671
|
+
supervision_timeout=timeout,
|
|
498
672
|
central_clock_accuracy=0,
|
|
499
673
|
)
|
|
500
674
|
)
|
|
675
|
+
self.pending_le_connection = None
|
|
501
676
|
|
|
502
|
-
def
|
|
503
|
-
|
|
504
|
-
) -> None:
|
|
505
|
-
'''
|
|
506
|
-
Called when a disconnection has been completed
|
|
507
|
-
'''
|
|
508
|
-
|
|
509
|
-
# Send a disconnection complete event
|
|
677
|
+
def on_le_encrypted(self, connection: Connection) -> None:
|
|
678
|
+
# For now, just setup the encryption without asking the host
|
|
510
679
|
self.send_hci_packet(
|
|
511
|
-
hci.
|
|
512
|
-
status=
|
|
513
|
-
connection_handle=disconnection_command.connection_handle,
|
|
514
|
-
reason=disconnection_command.reason,
|
|
680
|
+
hci.HCI_Encryption_Change_Event(
|
|
681
|
+
status=0, connection_handle=connection.handle, encryption_enabled=1
|
|
515
682
|
)
|
|
516
683
|
)
|
|
517
684
|
|
|
518
|
-
# Remove the connection
|
|
519
|
-
if connection := self.find_central_connection_by_handle(
|
|
520
|
-
disconnection_command.connection_handle
|
|
521
|
-
):
|
|
522
|
-
logger.debug(f'CENTRAL Connection removed: {connection}')
|
|
523
|
-
del self.central_connections[connection.peer_address]
|
|
524
|
-
elif connection := self.find_peripheral_connection_by_handle(
|
|
525
|
-
disconnection_command.connection_handle
|
|
526
|
-
):
|
|
527
|
-
logger.debug(f'PERIPHERAL Connection removed: {connection}')
|
|
528
|
-
del self.peripheral_connections[connection.peer_address]
|
|
529
|
-
|
|
530
|
-
def on_link_encrypted(
|
|
531
|
-
self, peer_address: hci.Address, _rand: bytes, _ediv: int, _ltk: bytes
|
|
532
|
-
) -> None:
|
|
533
|
-
# For now, just setup the encryption without asking the host
|
|
534
|
-
if connection := self.find_le_connection_by_address(peer_address):
|
|
535
|
-
self.send_hci_packet(
|
|
536
|
-
hci.HCI_Encryption_Change_Event(
|
|
537
|
-
status=0, connection_handle=connection.handle, encryption_enabled=1
|
|
538
|
-
)
|
|
539
|
-
)
|
|
540
|
-
|
|
541
685
|
def on_link_acl_data(
|
|
542
686
|
self, sender_address: hci.Address, transport: PhysicalTransport, data: bytes
|
|
543
687
|
) -> None:
|
|
544
688
|
# Look for the connection to which this data belongs
|
|
545
689
|
if transport == PhysicalTransport.LE:
|
|
546
|
-
connection = self.
|
|
690
|
+
connection = self.le_connections.get(sender_address)
|
|
547
691
|
else:
|
|
548
|
-
connection = self.
|
|
692
|
+
connection = self.classic_connections.get(sender_address)
|
|
549
693
|
if connection is None:
|
|
550
694
|
logger.warning(f'!!! no connection for {sender_address}')
|
|
551
695
|
return
|
|
@@ -555,43 +699,83 @@ class Controller:
|
|
|
555
699
|
acl_packet = hci.HCI_AclDataPacket(connection.handle, 2, 0, len(data), data)
|
|
556
700
|
self.send_hci_packet(acl_packet)
|
|
557
701
|
|
|
558
|
-
def
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
return
|
|
702
|
+
def on_advertising_pdu(self, pdu: ll.AdvInd | ll.AdvExtInd) -> None:
|
|
703
|
+
if isinstance(pdu, ll.AdvExtInd):
|
|
704
|
+
direct_address = pdu.target_address
|
|
705
|
+
else:
|
|
706
|
+
direct_address = None
|
|
564
707
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
708
|
+
if self.le_scan_enable:
|
|
709
|
+
# Send a scan report
|
|
710
|
+
if self.le_features & hci.LeFeatureMask.LE_EXTENDED_ADVERTISING:
|
|
711
|
+
ext_report = hci.HCI_LE_Extended_Advertising_Report_Event.Report(
|
|
712
|
+
event_type=hci.HCI_LE_Extended_Advertising_Report_Event.EventType.CONNECTABLE_ADVERTISING,
|
|
713
|
+
address_type=pdu.advertiser_address.address_type,
|
|
714
|
+
address=pdu.advertiser_address,
|
|
715
|
+
primary_phy=hci.Phy.LE_1M,
|
|
716
|
+
secondary_phy=hci.Phy.LE_1M,
|
|
717
|
+
advertising_sid=0,
|
|
718
|
+
tx_power=0,
|
|
719
|
+
rssi=-50,
|
|
720
|
+
periodic_advertising_interval=0,
|
|
721
|
+
direct_address_type=(
|
|
722
|
+
direct_address.address_type if direct_address else 0
|
|
723
|
+
),
|
|
724
|
+
direct_address=direct_address or hci.Address.ANY,
|
|
725
|
+
data=pdu.data,
|
|
726
|
+
)
|
|
727
|
+
self.send_hci_packet(
|
|
728
|
+
hci.HCI_LE_Extended_Advertising_Report_Event([ext_report])
|
|
729
|
+
)
|
|
730
|
+
ext_report = hci.HCI_LE_Extended_Advertising_Report_Event.Report(
|
|
731
|
+
event_type=hci.HCI_LE_Extended_Advertising_Report_Event.EventType.SCAN_RESPONSE,
|
|
732
|
+
address_type=pdu.advertiser_address.address_type,
|
|
733
|
+
address=pdu.advertiser_address,
|
|
734
|
+
primary_phy=hci.Phy.LE_1M,
|
|
735
|
+
secondary_phy=hci.Phy.LE_1M,
|
|
736
|
+
advertising_sid=0,
|
|
737
|
+
tx_power=0,
|
|
738
|
+
rssi=-50,
|
|
739
|
+
periodic_advertising_interval=0,
|
|
740
|
+
direct_address_type=(
|
|
741
|
+
direct_address.address_type if direct_address else 0
|
|
742
|
+
),
|
|
743
|
+
direct_address=direct_address or hci.Address.ANY,
|
|
744
|
+
data=pdu.data,
|
|
745
|
+
)
|
|
746
|
+
self.send_hci_packet(
|
|
747
|
+
hci.HCI_LE_Extended_Advertising_Report_Event([ext_report])
|
|
748
|
+
)
|
|
749
|
+
else:
|
|
750
|
+
report = hci.HCI_LE_Advertising_Report_Event.Report(
|
|
751
|
+
event_type=hci.HCI_LE_Advertising_Report_Event.EventType.ADV_IND,
|
|
752
|
+
address_type=pdu.advertiser_address.address_type,
|
|
753
|
+
address=pdu.advertiser_address,
|
|
754
|
+
data=pdu.data,
|
|
755
|
+
rssi=-50,
|
|
756
|
+
)
|
|
757
|
+
self.send_hci_packet(hci.HCI_LE_Advertising_Report_Event([report]))
|
|
758
|
+
report = hci.HCI_LE_Advertising_Report_Event.Report(
|
|
759
|
+
event_type=hci.HCI_LE_Advertising_Report_Event.EventType.SCAN_RSP,
|
|
760
|
+
address_type=pdu.advertiser_address.address_type,
|
|
761
|
+
address=pdu.advertiser_address,
|
|
762
|
+
data=pdu.data,
|
|
763
|
+
rssi=-50,
|
|
764
|
+
)
|
|
765
|
+
self.send_hci_packet(hci.HCI_LE_Advertising_Report_Event([report]))
|
|
574
766
|
|
|
575
|
-
#
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
data=data,
|
|
581
|
-
rssi=-50,
|
|
582
|
-
)
|
|
583
|
-
self.send_hci_packet(hci.HCI_LE_Advertising_Report_Event([report]))
|
|
767
|
+
# Create connection.
|
|
768
|
+
if (
|
|
769
|
+
pending_le_connection := self.pending_le_connection
|
|
770
|
+
) and pending_le_connection.peer_address == pdu.advertiser_address:
|
|
771
|
+
self.create_le_connection(pdu.advertiser_address)
|
|
584
772
|
|
|
585
|
-
def
|
|
586
|
-
self,
|
|
773
|
+
def on_le_cis_request(
|
|
774
|
+
self, connection: Connection, cig_id: int, cis_id: int
|
|
587
775
|
) -> None:
|
|
588
776
|
'''
|
|
589
777
|
Called when an incoming CIS request occurs from a central on the link
|
|
590
778
|
'''
|
|
591
|
-
|
|
592
|
-
connection = self.peripheral_connections.get(central_address)
|
|
593
|
-
assert connection
|
|
594
|
-
|
|
595
779
|
pending_cis_link = CisLink(
|
|
596
780
|
handle=self.allocate_connection_handle(),
|
|
597
781
|
cis_id=cis_id,
|
|
@@ -609,7 +793,7 @@ class Controller:
|
|
|
609
793
|
)
|
|
610
794
|
)
|
|
611
795
|
|
|
612
|
-
def
|
|
796
|
+
def on_le_cis_established(self, cig_id: int, cis_id: int) -> None:
|
|
613
797
|
'''
|
|
614
798
|
Called when an incoming CIS established.
|
|
615
799
|
'''
|
|
@@ -644,7 +828,7 @@ class Controller:
|
|
|
644
828
|
)
|
|
645
829
|
)
|
|
646
830
|
|
|
647
|
-
def
|
|
831
|
+
def on_le_cis_disconnected(self, cig_id: int, cis_id: int) -> None:
|
|
648
832
|
'''
|
|
649
833
|
Called when a CIS disconnected.
|
|
650
834
|
'''
|
|
@@ -750,6 +934,7 @@ class Controller:
|
|
|
750
934
|
controller=self,
|
|
751
935
|
handle=0,
|
|
752
936
|
role=hci.Role.PERIPHERAL,
|
|
937
|
+
self_address=self.public_address,
|
|
753
938
|
peer_address=peer_address,
|
|
754
939
|
link=self.link,
|
|
755
940
|
transport=PhysicalTransport.BR_EDR,
|
|
@@ -784,6 +969,7 @@ class Controller:
|
|
|
784
969
|
controller=self,
|
|
785
970
|
handle=connection_handle,
|
|
786
971
|
role=hci.Role.CENTRAL,
|
|
972
|
+
self_address=self.public_address,
|
|
787
973
|
peer_address=peer_address,
|
|
788
974
|
link=self.link,
|
|
789
975
|
transport=PhysicalTransport.BR_EDR,
|
|
@@ -934,44 +1120,23 @@ class Controller:
|
|
|
934
1120
|
############################################################
|
|
935
1121
|
# Advertising support
|
|
936
1122
|
############################################################
|
|
937
|
-
def on_advertising_timer_fired(self) -> None:
|
|
938
|
-
self.send_advertising_data()
|
|
939
|
-
self.advertising_timer_handle = asyncio.get_running_loop().call_later(
|
|
940
|
-
self.advertising_interval / 1000.0, self.on_advertising_timer_fired
|
|
941
|
-
)
|
|
942
|
-
|
|
943
|
-
def start_advertising(self) -> None:
|
|
944
|
-
# Stop any ongoing advertising before we start again
|
|
945
|
-
self.stop_advertising()
|
|
946
|
-
|
|
947
|
-
# Advertise now
|
|
948
|
-
self.advertising_timer_handle = asyncio.get_running_loop().call_soon(
|
|
949
|
-
self.on_advertising_timer_fired
|
|
950
|
-
)
|
|
951
|
-
|
|
952
|
-
def stop_advertising(self) -> None:
|
|
953
|
-
if self.advertising_timer_handle is not None:
|
|
954
|
-
self.advertising_timer_handle.cancel()
|
|
955
|
-
self.advertising_timer_handle = None
|
|
956
|
-
|
|
957
|
-
def send_advertising_data(self) -> None:
|
|
958
|
-
if self.link and self.advertising_data:
|
|
959
|
-
self.link.send_advertising_data(self.random_address, self.advertising_data)
|
|
960
1123
|
|
|
961
1124
|
@property
|
|
962
1125
|
def is_advertising(self) -> bool:
|
|
963
|
-
return self.
|
|
1126
|
+
return self.le_legacy_advertiser.enabled or any(
|
|
1127
|
+
s.enabled for s in self.advertising_sets.values()
|
|
1128
|
+
)
|
|
964
1129
|
|
|
965
1130
|
############################################################
|
|
966
1131
|
# HCI handlers
|
|
967
1132
|
############################################################
|
|
968
|
-
def on_hci_command(self, command: hci.HCI_Command) ->
|
|
1133
|
+
def on_hci_command(self, command: hci.HCI_Command) -> bytes | None:
|
|
969
1134
|
logger.warning(color(f'--- Unsupported command {command}', 'red'))
|
|
970
1135
|
return bytes([hci.HCI_UNKNOWN_HCI_COMMAND_ERROR])
|
|
971
1136
|
|
|
972
1137
|
def on_hci_create_connection_command(
|
|
973
1138
|
self, command: hci.HCI_Create_Connection_Command
|
|
974
|
-
) ->
|
|
1139
|
+
) -> bytes | None:
|
|
975
1140
|
'''
|
|
976
1141
|
See Bluetooth spec Vol 4, Part E - 7.1.5 Create Connection command
|
|
977
1142
|
'''
|
|
@@ -981,7 +1146,7 @@ class Controller:
|
|
|
981
1146
|
logger.debug(f'Connection request to {command.bd_addr}')
|
|
982
1147
|
|
|
983
1148
|
# Check that we don't already have a pending connection
|
|
984
|
-
if self.
|
|
1149
|
+
if self.pending_le_connection:
|
|
985
1150
|
self.send_hci_packet(
|
|
986
1151
|
hci.HCI_Command_Status_Event(
|
|
987
1152
|
status=hci.HCI_CONTROLLER_BUSY_ERROR,
|
|
@@ -995,6 +1160,7 @@ class Controller:
|
|
|
995
1160
|
controller=self,
|
|
996
1161
|
handle=0,
|
|
997
1162
|
role=hci.Role.CENTRAL,
|
|
1163
|
+
self_address=self.public_address,
|
|
998
1164
|
peer_address=command.bd_addr,
|
|
999
1165
|
link=self.link,
|
|
1000
1166
|
transport=PhysicalTransport.BR_EDR,
|
|
@@ -1020,7 +1186,7 @@ class Controller:
|
|
|
1020
1186
|
|
|
1021
1187
|
def on_hci_disconnect_command(
|
|
1022
1188
|
self, command: hci.HCI_Disconnect_Command
|
|
1023
|
-
) ->
|
|
1189
|
+
) -> bytes | None:
|
|
1024
1190
|
'''
|
|
1025
1191
|
See Bluetooth spec Vol 4, Part E - 7.1.6 Disconnect Command
|
|
1026
1192
|
'''
|
|
@@ -1035,29 +1201,19 @@ class Controller:
|
|
|
1035
1201
|
|
|
1036
1202
|
# Notify the link of the disconnection
|
|
1037
1203
|
handle = command.connection_handle
|
|
1038
|
-
if connection := self.
|
|
1039
|
-
if self.link:
|
|
1040
|
-
self.link.disconnect(
|
|
1041
|
-
self.random_address, connection.peer_address, command
|
|
1042
|
-
)
|
|
1043
|
-
else:
|
|
1044
|
-
# Remove the connection
|
|
1045
|
-
del self.central_connections[connection.peer_address]
|
|
1046
|
-
elif connection := self.find_peripheral_connection_by_handle(handle):
|
|
1204
|
+
if connection := self.find_connection_by_handle(handle):
|
|
1047
1205
|
if self.link:
|
|
1048
|
-
|
|
1049
|
-
self.
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
connection.
|
|
1058
|
-
|
|
1059
|
-
)
|
|
1060
|
-
self.on_classic_disconnected(connection.peer_address, command.reason)
|
|
1206
|
+
if connection.transport == PhysicalTransport.BR_EDR:
|
|
1207
|
+
self.send_lmp_packet(
|
|
1208
|
+
connection.peer_address,
|
|
1209
|
+
lmp.LmpDetach(command.reason),
|
|
1210
|
+
)
|
|
1211
|
+
self.on_classic_disconnected(
|
|
1212
|
+
connection.peer_address, command.reason
|
|
1213
|
+
)
|
|
1214
|
+
else:
|
|
1215
|
+
connection.send_ll_control_pdu(ll.TerminateInd(command.reason))
|
|
1216
|
+
self.on_le_disconnected(connection, command.reason)
|
|
1061
1217
|
else:
|
|
1062
1218
|
# Remove the connection
|
|
1063
1219
|
del self.classic_connections[connection.peer_address]
|
|
@@ -1088,19 +1244,19 @@ class Controller:
|
|
|
1088
1244
|
self.central_cis_links.get(handle) or self.peripheral_cis_links.get(handle)
|
|
1089
1245
|
):
|
|
1090
1246
|
if self.link and cis_link.acl_connection:
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
cis_id=cis_link.cis_id,
|
|
1247
|
+
cis_link.acl_connection.send_ll_control_pdu(
|
|
1248
|
+
ll.CisTerminateInd(
|
|
1249
|
+
cis_link.cig_id, cis_link.cis_id, command.reason
|
|
1250
|
+
),
|
|
1096
1251
|
)
|
|
1252
|
+
self.on_le_cis_disconnected(cis_link.cig_id, cis_link.cis_id)
|
|
1097
1253
|
# Spec requires handle to be kept after disconnection.
|
|
1098
1254
|
|
|
1099
1255
|
return None
|
|
1100
1256
|
|
|
1101
1257
|
def on_hci_accept_connection_request_command(
|
|
1102
1258
|
self, command: hci.HCI_Accept_Connection_Request_Command
|
|
1103
|
-
) ->
|
|
1259
|
+
) -> bytes | None:
|
|
1104
1260
|
'''
|
|
1105
1261
|
See Bluetooth spec Vol 4, Part E - 7.1.8 Accept Connection Request command
|
|
1106
1262
|
'''
|
|
@@ -1158,7 +1314,7 @@ class Controller:
|
|
|
1158
1314
|
|
|
1159
1315
|
def on_hci_remote_name_request_command(
|
|
1160
1316
|
self, command: hci.HCI_Remote_Name_Request_Command
|
|
1161
|
-
) ->
|
|
1317
|
+
) -> bytes | None:
|
|
1162
1318
|
'''
|
|
1163
1319
|
See Bluetooth spec Vol 4, Part E - 7.1.19 Remote Name Request command
|
|
1164
1320
|
'''
|
|
@@ -1176,7 +1332,7 @@ class Controller:
|
|
|
1176
1332
|
|
|
1177
1333
|
def on_hci_enhanced_setup_synchronous_connection_command(
|
|
1178
1334
|
self, command: hci.HCI_Enhanced_Setup_Synchronous_Connection_Command
|
|
1179
|
-
) ->
|
|
1335
|
+
) -> bytes | None:
|
|
1180
1336
|
'''
|
|
1181
1337
|
See Bluetooth spec Vol 4, Part E - 7.1.45 Enhanced Setup Synchronous Connection command
|
|
1182
1338
|
'''
|
|
@@ -1185,9 +1341,7 @@ class Controller:
|
|
|
1185
1341
|
return None
|
|
1186
1342
|
|
|
1187
1343
|
if not (
|
|
1188
|
-
connection := self.
|
|
1189
|
-
command.connection_handle
|
|
1190
|
-
)
|
|
1344
|
+
connection := self.find_connection_by_handle(command.connection_handle)
|
|
1191
1345
|
):
|
|
1192
1346
|
self.send_hci_packet(
|
|
1193
1347
|
hci.HCI_Command_Status_Event(
|
|
@@ -1235,7 +1389,7 @@ class Controller:
|
|
|
1235
1389
|
|
|
1236
1390
|
def on_hci_enhanced_accept_synchronous_connection_request_command(
|
|
1237
1391
|
self, command: hci.HCI_Enhanced_Accept_Synchronous_Connection_Request_Command
|
|
1238
|
-
) ->
|
|
1392
|
+
) -> bytes | None:
|
|
1239
1393
|
'''
|
|
1240
1394
|
See Bluetooth spec Vol 4, Part E - 7.1.46 Enhanced Accept Synchronous Connection Request command
|
|
1241
1395
|
'''
|
|
@@ -1243,7 +1397,7 @@ class Controller:
|
|
|
1243
1397
|
if self.link is None:
|
|
1244
1398
|
return None
|
|
1245
1399
|
|
|
1246
|
-
if not (connection := self.
|
|
1400
|
+
if not (connection := self.classic_connections.get(command.bd_addr)):
|
|
1247
1401
|
self.send_hci_packet(
|
|
1248
1402
|
hci.HCI_Command_Status_Event(
|
|
1249
1403
|
status=hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
@@ -1273,7 +1427,7 @@ class Controller:
|
|
|
1273
1427
|
|
|
1274
1428
|
def on_hci_sniff_mode_command(
|
|
1275
1429
|
self, command: hci.HCI_Sniff_Mode_Command
|
|
1276
|
-
) ->
|
|
1430
|
+
) -> bytes | None:
|
|
1277
1431
|
'''
|
|
1278
1432
|
See Bluetooth spec Vol 4, Part E - 7.2.2 Sniff Mode command
|
|
1279
1433
|
'''
|
|
@@ -1306,7 +1460,7 @@ class Controller:
|
|
|
1306
1460
|
|
|
1307
1461
|
def on_hci_exit_sniff_mode_command(
|
|
1308
1462
|
self, command: hci.HCI_Exit_Sniff_Mode_Command
|
|
1309
|
-
) ->
|
|
1463
|
+
) -> bytes | None:
|
|
1310
1464
|
'''
|
|
1311
1465
|
See Bluetooth spec Vol 4, Part E - 7.2.3 Exit Sniff Mode command
|
|
1312
1466
|
'''
|
|
@@ -1340,7 +1494,7 @@ class Controller:
|
|
|
1340
1494
|
|
|
1341
1495
|
def on_hci_switch_role_command(
|
|
1342
1496
|
self, command: hci.HCI_Switch_Role_Command
|
|
1343
|
-
) ->
|
|
1497
|
+
) -> bytes | None:
|
|
1344
1498
|
'''
|
|
1345
1499
|
See Bluetooth spec Vol 4, Part E - 7.2.8 Switch hci.Role command
|
|
1346
1500
|
'''
|
|
@@ -1397,7 +1551,7 @@ class Controller:
|
|
|
1397
1551
|
|
|
1398
1552
|
def on_hci_set_event_mask_command(
|
|
1399
1553
|
self, command: hci.HCI_Set_Event_Mask_Command
|
|
1400
|
-
) ->
|
|
1554
|
+
) -> bytes | None:
|
|
1401
1555
|
'''
|
|
1402
1556
|
See Bluetooth spec Vol 4, Part E - 7.3.1 Set Event Mask Command
|
|
1403
1557
|
'''
|
|
@@ -1406,7 +1560,7 @@ class Controller:
|
|
|
1406
1560
|
)
|
|
1407
1561
|
return bytes([hci.HCI_SUCCESS])
|
|
1408
1562
|
|
|
1409
|
-
def on_hci_reset_command(self, _command: hci.HCI_Reset_Command) ->
|
|
1563
|
+
def on_hci_reset_command(self, _command: hci.HCI_Reset_Command) -> bytes | None:
|
|
1410
1564
|
'''
|
|
1411
1565
|
See Bluetooth spec Vol 4, Part E - 7.3.2 Reset Command
|
|
1412
1566
|
'''
|
|
@@ -1415,7 +1569,7 @@ class Controller:
|
|
|
1415
1569
|
|
|
1416
1570
|
def on_hci_write_local_name_command(
|
|
1417
1571
|
self, command: hci.HCI_Write_Local_Name_Command
|
|
1418
|
-
) ->
|
|
1572
|
+
) -> bytes | None:
|
|
1419
1573
|
'''
|
|
1420
1574
|
See Bluetooth spec Vol 4, Part E - 7.3.11 Write Local Name Command
|
|
1421
1575
|
'''
|
|
@@ -1432,7 +1586,7 @@ class Controller:
|
|
|
1432
1586
|
|
|
1433
1587
|
def on_hci_read_local_name_command(
|
|
1434
1588
|
self, _command: hci.HCI_Read_Local_Name_Command
|
|
1435
|
-
) ->
|
|
1589
|
+
) -> bytes | None:
|
|
1436
1590
|
'''
|
|
1437
1591
|
See Bluetooth spec Vol 4, Part E - 7.3.12 Read Local Name Command
|
|
1438
1592
|
'''
|
|
@@ -1444,7 +1598,7 @@ class Controller:
|
|
|
1444
1598
|
|
|
1445
1599
|
def on_hci_read_class_of_device_command(
|
|
1446
1600
|
self, _command: hci.HCI_Read_Class_Of_Device_Command
|
|
1447
|
-
) ->
|
|
1601
|
+
) -> bytes | None:
|
|
1448
1602
|
'''
|
|
1449
1603
|
See Bluetooth spec Vol 4, Part E - 7.3.25 Read Class of Device Command
|
|
1450
1604
|
'''
|
|
@@ -1452,7 +1606,7 @@ class Controller:
|
|
|
1452
1606
|
|
|
1453
1607
|
def on_hci_write_class_of_device_command(
|
|
1454
1608
|
self, _command: hci.HCI_Write_Class_Of_Device_Command
|
|
1455
|
-
) ->
|
|
1609
|
+
) -> bytes | None:
|
|
1456
1610
|
'''
|
|
1457
1611
|
See Bluetooth spec Vol 4, Part E - 7.3.26 Write Class of Device Command
|
|
1458
1612
|
'''
|
|
@@ -1460,7 +1614,7 @@ class Controller:
|
|
|
1460
1614
|
|
|
1461
1615
|
def on_hci_read_synchronous_flow_control_enable_command(
|
|
1462
1616
|
self, _command: hci.HCI_Read_Synchronous_Flow_Control_Enable_Command
|
|
1463
|
-
) ->
|
|
1617
|
+
) -> bytes | None:
|
|
1464
1618
|
'''
|
|
1465
1619
|
See Bluetooth spec Vol 4, Part E - 7.3.36 Read Synchronous Flow Control Enable
|
|
1466
1620
|
Command
|
|
@@ -1473,7 +1627,7 @@ class Controller:
|
|
|
1473
1627
|
|
|
1474
1628
|
def on_hci_write_synchronous_flow_control_enable_command(
|
|
1475
1629
|
self, command: hci.HCI_Write_Synchronous_Flow_Control_Enable_Command
|
|
1476
|
-
) ->
|
|
1630
|
+
) -> bytes | None:
|
|
1477
1631
|
'''
|
|
1478
1632
|
See Bluetooth spec Vol 4, Part E - 7.3.37 Write Synchronous Flow Control Enable
|
|
1479
1633
|
Command
|
|
@@ -1489,7 +1643,7 @@ class Controller:
|
|
|
1489
1643
|
|
|
1490
1644
|
def on_hci_set_controller_to_host_flow_control_command(
|
|
1491
1645
|
self, _command: hci.HCI_Set_Controller_To_Host_Flow_Control_Command
|
|
1492
|
-
) ->
|
|
1646
|
+
) -> bytes | None:
|
|
1493
1647
|
'''
|
|
1494
1648
|
See Bluetooth spec Vol 4, Part E - 7.3.38 Set Controller To Host Flow Control
|
|
1495
1649
|
Command
|
|
@@ -1500,7 +1654,7 @@ class Controller:
|
|
|
1500
1654
|
|
|
1501
1655
|
def on_hci_host_buffer_size_command(
|
|
1502
1656
|
self, _command: hci.HCI_Host_Buffer_Size_Command
|
|
1503
|
-
) ->
|
|
1657
|
+
) -> bytes | None:
|
|
1504
1658
|
'''
|
|
1505
1659
|
See Bluetooth spec Vol 4, Part E - 7.3.39 Host Buffer Size Command
|
|
1506
1660
|
'''
|
|
@@ -1510,7 +1664,7 @@ class Controller:
|
|
|
1510
1664
|
|
|
1511
1665
|
def on_hci_write_extended_inquiry_response_command(
|
|
1512
1666
|
self, _command: hci.HCI_Write_Extended_Inquiry_Response_Command
|
|
1513
|
-
) ->
|
|
1667
|
+
) -> bytes | None:
|
|
1514
1668
|
'''
|
|
1515
1669
|
See Bluetooth spec Vol 4, Part E - 7.3.56 Write Extended Inquiry Response
|
|
1516
1670
|
Command
|
|
@@ -1519,7 +1673,7 @@ class Controller:
|
|
|
1519
1673
|
|
|
1520
1674
|
def on_hci_write_simple_pairing_mode_command(
|
|
1521
1675
|
self, _command: hci.HCI_Write_Simple_Pairing_Mode_Command
|
|
1522
|
-
) ->
|
|
1676
|
+
) -> bytes | None:
|
|
1523
1677
|
'''
|
|
1524
1678
|
See Bluetooth spec Vol 4, Part E - 7.3.59 Write Simple Pairing Mode Command
|
|
1525
1679
|
'''
|
|
@@ -1527,7 +1681,7 @@ class Controller:
|
|
|
1527
1681
|
|
|
1528
1682
|
def on_hci_set_event_mask_page_2_command(
|
|
1529
1683
|
self, command: hci.HCI_Set_Event_Mask_Page_2_Command
|
|
1530
|
-
) ->
|
|
1684
|
+
) -> bytes | None:
|
|
1531
1685
|
'''
|
|
1532
1686
|
See Bluetooth spec Vol 4, Part E - 7.3.69 Set Event Mask Page 2 Command
|
|
1533
1687
|
'''
|
|
@@ -1538,7 +1692,7 @@ class Controller:
|
|
|
1538
1692
|
|
|
1539
1693
|
def on_hci_read_le_host_support_command(
|
|
1540
1694
|
self, _command: hci.HCI_Read_LE_Host_Support_Command
|
|
1541
|
-
) ->
|
|
1695
|
+
) -> bytes | None:
|
|
1542
1696
|
'''
|
|
1543
1697
|
See Bluetooth spec Vol 4, Part E - 7.3.78 Write LE Host Support Command
|
|
1544
1698
|
'''
|
|
@@ -1546,7 +1700,7 @@ class Controller:
|
|
|
1546
1700
|
|
|
1547
1701
|
def on_hci_write_le_host_support_command(
|
|
1548
1702
|
self, _command: hci.HCI_Write_LE_Host_Support_Command
|
|
1549
|
-
) ->
|
|
1703
|
+
) -> bytes | None:
|
|
1550
1704
|
'''
|
|
1551
1705
|
See Bluetooth spec Vol 4, Part E - 7.3.79 Write LE Host Support Command
|
|
1552
1706
|
'''
|
|
@@ -1555,7 +1709,7 @@ class Controller:
|
|
|
1555
1709
|
|
|
1556
1710
|
def on_hci_write_authenticated_payload_timeout_command(
|
|
1557
1711
|
self, command: hci.HCI_Write_Authenticated_Payload_Timeout_Command
|
|
1558
|
-
) ->
|
|
1712
|
+
) -> bytes | None:
|
|
1559
1713
|
'''
|
|
1560
1714
|
See Bluetooth spec Vol 4, Part E - 7.3.94 Write Authenticated Payload Timeout
|
|
1561
1715
|
Command
|
|
@@ -1565,7 +1719,7 @@ class Controller:
|
|
|
1565
1719
|
|
|
1566
1720
|
def on_hci_read_local_version_information_command(
|
|
1567
1721
|
self, _command: hci.HCI_Read_Local_Version_Information_Command
|
|
1568
|
-
) ->
|
|
1722
|
+
) -> bytes | None:
|
|
1569
1723
|
'''
|
|
1570
1724
|
See Bluetooth spec Vol 4, Part E - 7.4.1 Read Local Version Information Command
|
|
1571
1725
|
'''
|
|
@@ -1581,7 +1735,7 @@ class Controller:
|
|
|
1581
1735
|
|
|
1582
1736
|
def on_hci_read_local_supported_commands_command(
|
|
1583
1737
|
self, _command: hci.HCI_Read_Local_Supported_Commands_Command
|
|
1584
|
-
) ->
|
|
1738
|
+
) -> bytes | None:
|
|
1585
1739
|
'''
|
|
1586
1740
|
See Bluetooth spec Vol 4, Part E - 7.4.2 Read Local Supported Commands Command
|
|
1587
1741
|
'''
|
|
@@ -1589,7 +1743,7 @@ class Controller:
|
|
|
1589
1743
|
|
|
1590
1744
|
def on_hci_read_local_supported_features_command(
|
|
1591
1745
|
self, _command: hci.HCI_Read_Local_Supported_Features_Command
|
|
1592
|
-
) ->
|
|
1746
|
+
) -> bytes | None:
|
|
1593
1747
|
'''
|
|
1594
1748
|
See Bluetooth spec Vol 4, Part E - 7.4.3 Read Local Supported Features Command
|
|
1595
1749
|
'''
|
|
@@ -1597,7 +1751,7 @@ class Controller:
|
|
|
1597
1751
|
|
|
1598
1752
|
def on_hci_read_local_extended_features_command(
|
|
1599
1753
|
self, command: hci.HCI_Read_Local_Extended_Features_Command
|
|
1600
|
-
) ->
|
|
1754
|
+
) -> bytes | None:
|
|
1601
1755
|
'''
|
|
1602
1756
|
See Bluetooth spec Vol 4, Part E - 7.4.4 Read Local Extended Features Command
|
|
1603
1757
|
'''
|
|
@@ -1620,7 +1774,7 @@ class Controller:
|
|
|
1620
1774
|
|
|
1621
1775
|
def on_hci_read_buffer_size_command(
|
|
1622
1776
|
self, _command: hci.HCI_Read_Buffer_Size_Command
|
|
1623
|
-
) ->
|
|
1777
|
+
) -> bytes | None:
|
|
1624
1778
|
'''
|
|
1625
1779
|
See Bluetooth spec Vol 4, Part E - 7.4.5 Read Buffer Size Command
|
|
1626
1780
|
'''
|
|
@@ -1635,7 +1789,7 @@ class Controller:
|
|
|
1635
1789
|
|
|
1636
1790
|
def on_hci_read_bd_addr_command(
|
|
1637
1791
|
self, _command: hci.HCI_Read_BD_ADDR_Command
|
|
1638
|
-
) ->
|
|
1792
|
+
) -> bytes | None:
|
|
1639
1793
|
'''
|
|
1640
1794
|
See Bluetooth spec Vol 4, Part E - 7.4.6 Read BD_ADDR Command
|
|
1641
1795
|
'''
|
|
@@ -1648,7 +1802,7 @@ class Controller:
|
|
|
1648
1802
|
|
|
1649
1803
|
def on_hci_le_set_default_subrate_command(
|
|
1650
1804
|
self, command: hci.HCI_LE_Set_Default_Subrate_Command
|
|
1651
|
-
) ->
|
|
1805
|
+
) -> bytes | None:
|
|
1652
1806
|
'''
|
|
1653
1807
|
See Bluetooth spec Vol 6, Part E - 7.8.123 LE Set Event Mask Command
|
|
1654
1808
|
'''
|
|
@@ -1664,7 +1818,7 @@ class Controller:
|
|
|
1664
1818
|
|
|
1665
1819
|
def on_hci_le_subrate_request_command(
|
|
1666
1820
|
self, command: hci.HCI_LE_Subrate_Request_Command
|
|
1667
|
-
) ->
|
|
1821
|
+
) -> bytes | None:
|
|
1668
1822
|
'''
|
|
1669
1823
|
See Bluetooth spec Vol 6, Part E - 7.8.124 LE Subrate Request command
|
|
1670
1824
|
'''
|
|
@@ -1698,7 +1852,7 @@ class Controller:
|
|
|
1698
1852
|
|
|
1699
1853
|
def on_hci_le_set_event_mask_command(
|
|
1700
1854
|
self, command: hci.HCI_LE_Set_Event_Mask_Command
|
|
1701
|
-
) ->
|
|
1855
|
+
) -> bytes | None:
|
|
1702
1856
|
'''
|
|
1703
1857
|
See Bluetooth spec Vol 4, Part E - 7.8.1 LE Set Event Mask Command
|
|
1704
1858
|
'''
|
|
@@ -1709,7 +1863,7 @@ class Controller:
|
|
|
1709
1863
|
|
|
1710
1864
|
def on_hci_le_read_buffer_size_command(
|
|
1711
1865
|
self, _command: hci.HCI_LE_Read_Buffer_Size_Command
|
|
1712
|
-
) ->
|
|
1866
|
+
) -> bytes | None:
|
|
1713
1867
|
'''
|
|
1714
1868
|
See Bluetooth spec Vol 4, Part E - 7.8.2 LE Read Buffer Size Command
|
|
1715
1869
|
'''
|
|
@@ -1722,7 +1876,7 @@ class Controller:
|
|
|
1722
1876
|
|
|
1723
1877
|
def on_hci_le_read_buffer_size_v2_command(
|
|
1724
1878
|
self, _command: hci.HCI_LE_Read_Buffer_Size_V2_Command
|
|
1725
|
-
) ->
|
|
1879
|
+
) -> bytes | None:
|
|
1726
1880
|
'''
|
|
1727
1881
|
See Bluetooth spec Vol 4, Part E - 7.8.2 LE Read Buffer Size Command
|
|
1728
1882
|
'''
|
|
@@ -1737,16 +1891,16 @@ class Controller:
|
|
|
1737
1891
|
|
|
1738
1892
|
def on_hci_le_read_local_supported_features_command(
|
|
1739
1893
|
self, _command: hci.HCI_LE_Read_Local_Supported_Features_Command
|
|
1740
|
-
) ->
|
|
1894
|
+
) -> bytes | None:
|
|
1741
1895
|
'''
|
|
1742
1896
|
See Bluetooth spec Vol 4, Part E - 7.8.3 LE Read Local Supported Features
|
|
1743
1897
|
Command
|
|
1744
1898
|
'''
|
|
1745
|
-
return bytes([hci.HCI_SUCCESS]) + self.le_features
|
|
1899
|
+
return bytes([hci.HCI_SUCCESS]) + self.le_features.value.to_bytes(8, 'little')
|
|
1746
1900
|
|
|
1747
1901
|
def on_hci_le_set_random_address_command(
|
|
1748
1902
|
self, command: hci.HCI_LE_Set_Random_Address_Command
|
|
1749
|
-
) ->
|
|
1903
|
+
) -> bytes | None:
|
|
1750
1904
|
'''
|
|
1751
1905
|
See Bluetooth spec Vol 4, Part E - 7.8.4 LE Set Random hci.Address Command
|
|
1752
1906
|
'''
|
|
@@ -1755,16 +1909,31 @@ class Controller:
|
|
|
1755
1909
|
|
|
1756
1910
|
def on_hci_le_set_advertising_parameters_command(
|
|
1757
1911
|
self, command: hci.HCI_LE_Set_Advertising_Parameters_Command
|
|
1758
|
-
) ->
|
|
1912
|
+
) -> bytes | None:
|
|
1759
1913
|
'''
|
|
1760
1914
|
See Bluetooth spec Vol 4, Part E - 7.8.5 LE Set Advertising Parameters Command
|
|
1761
1915
|
'''
|
|
1762
|
-
self.
|
|
1916
|
+
self.le_legacy_advertiser.advertising_interval_min = (
|
|
1917
|
+
command.advertising_interval_min
|
|
1918
|
+
)
|
|
1919
|
+
self.le_legacy_advertiser.advertising_interval_max = (
|
|
1920
|
+
command.advertising_interval_max
|
|
1921
|
+
)
|
|
1922
|
+
self.le_legacy_advertiser.advertising_type = command.advertising_type
|
|
1923
|
+
self.le_legacy_advertiser.own_address_type = command.own_address_type
|
|
1924
|
+
self.le_legacy_advertiser.peer_address_type = command.peer_address_type
|
|
1925
|
+
self.le_legacy_advertiser.peer_address = command.peer_address
|
|
1926
|
+
self.le_legacy_advertiser.advertising_channel_map = (
|
|
1927
|
+
command.advertising_channel_map
|
|
1928
|
+
)
|
|
1929
|
+
self.le_legacy_advertiser.advertising_filter_policy = (
|
|
1930
|
+
command.advertising_filter_policy
|
|
1931
|
+
)
|
|
1763
1932
|
return bytes([hci.HCI_SUCCESS])
|
|
1764
1933
|
|
|
1765
1934
|
def on_hci_le_read_advertising_physical_channel_tx_power_command(
|
|
1766
1935
|
self, _command: hci.HCI_LE_Read_Advertising_Physical_Channel_Tx_Power_Command
|
|
1767
|
-
) ->
|
|
1936
|
+
) -> bytes | None:
|
|
1768
1937
|
'''
|
|
1769
1938
|
See Bluetooth spec Vol 4, Part E - 7.8.6 LE Read Advertising Physical Channel
|
|
1770
1939
|
Tx Power Command
|
|
@@ -1773,38 +1942,39 @@ class Controller:
|
|
|
1773
1942
|
|
|
1774
1943
|
def on_hci_le_set_advertising_data_command(
|
|
1775
1944
|
self, command: hci.HCI_LE_Set_Advertising_Data_Command
|
|
1776
|
-
) ->
|
|
1945
|
+
) -> bytes | None:
|
|
1777
1946
|
'''
|
|
1778
1947
|
See Bluetooth spec Vol 4, Part E - 7.8.7 LE Set Advertising Data Command
|
|
1779
1948
|
'''
|
|
1780
|
-
self.advertising_data = command.advertising_data
|
|
1949
|
+
self.le_legacy_advertiser.advertising_data = command.advertising_data
|
|
1950
|
+
|
|
1781
1951
|
return bytes([hci.HCI_SUCCESS])
|
|
1782
1952
|
|
|
1783
1953
|
def on_hci_le_set_scan_response_data_command(
|
|
1784
1954
|
self, command: hci.HCI_LE_Set_Scan_Response_Data_Command
|
|
1785
|
-
) ->
|
|
1955
|
+
) -> bytes | None:
|
|
1786
1956
|
'''
|
|
1787
1957
|
See Bluetooth spec Vol 4, Part E - 7.8.8 LE Set Scan Response Data Command
|
|
1788
1958
|
'''
|
|
1789
|
-
self.
|
|
1959
|
+
self.le_legacy_advertiser.scan_response_data = command.scan_response_data
|
|
1790
1960
|
return bytes([hci.HCI_SUCCESS])
|
|
1791
1961
|
|
|
1792
1962
|
def on_hci_le_set_advertising_enable_command(
|
|
1793
1963
|
self, command: hci.HCI_LE_Set_Advertising_Enable_Command
|
|
1794
|
-
) ->
|
|
1964
|
+
) -> bytes | None:
|
|
1795
1965
|
'''
|
|
1796
1966
|
See Bluetooth spec Vol 4, Part E - 7.8.9 LE Set Advertising Enable Command
|
|
1797
1967
|
'''
|
|
1798
1968
|
if command.advertising_enable:
|
|
1799
|
-
self.
|
|
1969
|
+
self.le_legacy_advertiser.start()
|
|
1800
1970
|
else:
|
|
1801
|
-
self.
|
|
1971
|
+
self.le_legacy_advertiser.stop()
|
|
1802
1972
|
|
|
1803
1973
|
return bytes([hci.HCI_SUCCESS])
|
|
1804
1974
|
|
|
1805
1975
|
def on_hci_le_set_scan_parameters_command(
|
|
1806
1976
|
self, command: hci.HCI_LE_Set_Scan_Parameters_Command
|
|
1807
|
-
) ->
|
|
1977
|
+
) -> bytes | None:
|
|
1808
1978
|
'''
|
|
1809
1979
|
See Bluetooth spec Vol 4, Part E - 7.8.10 LE Set Scan Parameters Command
|
|
1810
1980
|
'''
|
|
@@ -1820,7 +1990,7 @@ class Controller:
|
|
|
1820
1990
|
|
|
1821
1991
|
def on_hci_le_set_scan_enable_command(
|
|
1822
1992
|
self, command: hci.HCI_LE_Set_Scan_Enable_Command
|
|
1823
|
-
) ->
|
|
1993
|
+
) -> bytes | None:
|
|
1824
1994
|
'''
|
|
1825
1995
|
See Bluetooth spec Vol 4, Part E - 7.8.11 LE Set Scan Enable Command
|
|
1826
1996
|
'''
|
|
@@ -1830,7 +2000,7 @@ class Controller:
|
|
|
1830
2000
|
|
|
1831
2001
|
def on_hci_le_create_connection_command(
|
|
1832
2002
|
self, command: hci.HCI_LE_Create_Connection_Command
|
|
1833
|
-
) ->
|
|
2003
|
+
) -> bytes | None:
|
|
1834
2004
|
'''
|
|
1835
2005
|
See Bluetooth spec Vol 4, Part E - 7.8.12 LE Create Connection Command
|
|
1836
2006
|
'''
|
|
@@ -1841,7 +2011,7 @@ class Controller:
|
|
|
1841
2011
|
logger.debug(f'Connection request to {command.peer_address}')
|
|
1842
2012
|
|
|
1843
2013
|
# Check that we don't already have a pending connection
|
|
1844
|
-
if self.
|
|
2014
|
+
if self.pending_le_connection:
|
|
1845
2015
|
self.send_hci_packet(
|
|
1846
2016
|
hci.HCI_Command_Status_Event(
|
|
1847
2017
|
status=hci.HCI_COMMAND_DISALLOWED_ERROR,
|
|
@@ -1851,8 +2021,7 @@ class Controller:
|
|
|
1851
2021
|
)
|
|
1852
2022
|
return None
|
|
1853
2023
|
|
|
1854
|
-
|
|
1855
|
-
self.link.connect(self.random_address, command)
|
|
2024
|
+
self.pending_le_connection = command
|
|
1856
2025
|
|
|
1857
2026
|
# Say that the connection is pending
|
|
1858
2027
|
self.send_hci_packet(
|
|
@@ -1866,15 +2035,46 @@ class Controller:
|
|
|
1866
2035
|
|
|
1867
2036
|
def on_hci_le_create_connection_cancel_command(
|
|
1868
2037
|
self, _command: hci.HCI_LE_Create_Connection_Cancel_Command
|
|
1869
|
-
) ->
|
|
2038
|
+
) -> bytes | None:
|
|
1870
2039
|
'''
|
|
1871
2040
|
See Bluetooth spec Vol 4, Part E - 7.8.13 LE Create Connection Cancel Command
|
|
1872
2041
|
'''
|
|
1873
2042
|
return bytes([hci.HCI_SUCCESS])
|
|
1874
2043
|
|
|
2044
|
+
def on_hci_le_extended_create_connection_command(
|
|
2045
|
+
self, command: hci.HCI_LE_Extended_Create_Connection_Command
|
|
2046
|
+
) -> bytes | None:
|
|
2047
|
+
'''
|
|
2048
|
+
See Bluetooth spec Vol 4, Part E - 7.8.66 LE Extended Create Connection Command
|
|
2049
|
+
'''
|
|
2050
|
+
if not self.link:
|
|
2051
|
+
return None
|
|
2052
|
+
|
|
2053
|
+
# Check pending
|
|
2054
|
+
if self.pending_le_connection:
|
|
2055
|
+
self.send_hci_packet(
|
|
2056
|
+
hci.HCI_Command_Status_Event(
|
|
2057
|
+
status=hci.HCI_COMMAND_DISALLOWED_ERROR,
|
|
2058
|
+
num_hci_command_packets=1,
|
|
2059
|
+
command_opcode=command.op_code,
|
|
2060
|
+
)
|
|
2061
|
+
)
|
|
2062
|
+
return None
|
|
2063
|
+
|
|
2064
|
+
self.pending_le_connection = command
|
|
2065
|
+
|
|
2066
|
+
self.send_hci_packet(
|
|
2067
|
+
hci.HCI_Command_Status_Event(
|
|
2068
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
2069
|
+
num_hci_command_packets=1,
|
|
2070
|
+
command_opcode=command.op_code,
|
|
2071
|
+
)
|
|
2072
|
+
)
|
|
2073
|
+
return None
|
|
2074
|
+
|
|
1875
2075
|
def on_hci_le_read_filter_accept_list_size_command(
|
|
1876
2076
|
self, _command: hci.HCI_LE_Read_Filter_Accept_List_Size_Command
|
|
1877
|
-
) ->
|
|
2077
|
+
) -> bytes | None:
|
|
1878
2078
|
'''
|
|
1879
2079
|
See Bluetooth spec Vol 4, Part E - 7.8.14 LE Read Filter Accept List Size
|
|
1880
2080
|
Command
|
|
@@ -1883,7 +2083,7 @@ class Controller:
|
|
|
1883
2083
|
|
|
1884
2084
|
def on_hci_le_clear_filter_accept_list_command(
|
|
1885
2085
|
self, _command: hci.HCI_LE_Clear_Filter_Accept_List_Command
|
|
1886
|
-
) ->
|
|
2086
|
+
) -> bytes | None:
|
|
1887
2087
|
'''
|
|
1888
2088
|
See Bluetooth spec Vol 4, Part E - 7.8.15 LE Clear Filter Accept List Command
|
|
1889
2089
|
'''
|
|
@@ -1891,7 +2091,7 @@ class Controller:
|
|
|
1891
2091
|
|
|
1892
2092
|
def on_hci_le_add_device_to_filter_accept_list_command(
|
|
1893
2093
|
self, _command: hci.HCI_LE_Add_Device_To_Filter_Accept_List_Command
|
|
1894
|
-
) ->
|
|
2094
|
+
) -> bytes | None:
|
|
1895
2095
|
'''
|
|
1896
2096
|
See Bluetooth spec Vol 4, Part E - 7.8.16 LE Add Device To Filter Accept List
|
|
1897
2097
|
Command
|
|
@@ -1900,7 +2100,7 @@ class Controller:
|
|
|
1900
2100
|
|
|
1901
2101
|
def on_hci_le_remove_device_from_filter_accept_list_command(
|
|
1902
2102
|
self, _command: hci.HCI_LE_Remove_Device_From_Filter_Accept_List_Command
|
|
1903
|
-
) ->
|
|
2103
|
+
) -> bytes | None:
|
|
1904
2104
|
'''
|
|
1905
2105
|
See Bluetooth spec Vol 4, Part E - 7.8.17 LE Remove Device From Filter Accept
|
|
1906
2106
|
List Command
|
|
@@ -1909,7 +2109,7 @@ class Controller:
|
|
|
1909
2109
|
|
|
1910
2110
|
def on_hci_write_scan_enable_command(
|
|
1911
2111
|
self, command: hci.HCI_Write_Scan_Enable_Command
|
|
1912
|
-
) ->
|
|
2112
|
+
) -> bytes | None:
|
|
1913
2113
|
'''
|
|
1914
2114
|
See Bluetooth spec Vol 4, Part E - 7.3.18 Write Scan Enable Command
|
|
1915
2115
|
'''
|
|
@@ -1918,7 +2118,7 @@ class Controller:
|
|
|
1918
2118
|
|
|
1919
2119
|
def on_hci_le_read_remote_features_command(
|
|
1920
2120
|
self, command: hci.HCI_LE_Read_Remote_Features_Command
|
|
1921
|
-
) ->
|
|
2121
|
+
) -> bytes | None:
|
|
1922
2122
|
'''
|
|
1923
2123
|
See Bluetooth spec Vol 4, Part E - 7.8.21 LE Read Remote Features Command
|
|
1924
2124
|
'''
|
|
@@ -1954,9 +2154,7 @@ class Controller:
|
|
|
1954
2154
|
)
|
|
1955
2155
|
return None
|
|
1956
2156
|
|
|
1957
|
-
def on_hci_le_rand_command(
|
|
1958
|
-
self, _command: hci.HCI_LE_Rand_Command
|
|
1959
|
-
) -> Optional[bytes]:
|
|
2157
|
+
def on_hci_le_rand_command(self, _command: hci.HCI_LE_Rand_Command) -> bytes | None:
|
|
1960
2158
|
'''
|
|
1961
2159
|
See Bluetooth spec Vol 4, Part E - 7.8.23 LE Rand Command
|
|
1962
2160
|
'''
|
|
@@ -1964,7 +2162,7 @@ class Controller:
|
|
|
1964
2162
|
|
|
1965
2163
|
def on_hci_le_enable_encryption_command(
|
|
1966
2164
|
self, command: hci.HCI_LE_Enable_Encryption_Command
|
|
1967
|
-
) ->
|
|
2165
|
+
) -> bytes | None:
|
|
1968
2166
|
'''
|
|
1969
2167
|
See Bluetooth spec Vol 4, Part E - 7.8.24 LE Enable Encryption Command
|
|
1970
2168
|
'''
|
|
@@ -1972,21 +2170,21 @@ class Controller:
|
|
|
1972
2170
|
return None
|
|
1973
2171
|
|
|
1974
2172
|
# Check the parameters
|
|
1975
|
-
if
|
|
1976
|
-
|
|
1977
|
-
command.connection_handle
|
|
2173
|
+
if (
|
|
2174
|
+
not (
|
|
2175
|
+
connection := self.find_connection_by_handle(command.connection_handle)
|
|
1978
2176
|
)
|
|
2177
|
+
or connection.transport != PhysicalTransport.LE
|
|
1979
2178
|
):
|
|
1980
2179
|
logger.warning('connection not found')
|
|
1981
2180
|
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1982
2181
|
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
command.long_term_key,
|
|
2182
|
+
connection.send_ll_control_pdu(
|
|
2183
|
+
ll.EncReq(
|
|
2184
|
+
rand=command.random_number,
|
|
2185
|
+
ediv=command.encrypted_diversifier,
|
|
2186
|
+
ltk=command.long_term_key,
|
|
2187
|
+
),
|
|
1990
2188
|
)
|
|
1991
2189
|
|
|
1992
2190
|
self.send_hci_packet(
|
|
@@ -1997,11 +2195,14 @@ class Controller:
|
|
|
1997
2195
|
)
|
|
1998
2196
|
)
|
|
1999
2197
|
|
|
2198
|
+
# TODO: Handle authentication
|
|
2199
|
+
self.on_le_encrypted(connection)
|
|
2200
|
+
|
|
2000
2201
|
return None
|
|
2001
2202
|
|
|
2002
2203
|
def on_hci_le_read_supported_states_command(
|
|
2003
2204
|
self, _command: hci.HCI_LE_Read_Supported_States_Command
|
|
2004
|
-
) ->
|
|
2205
|
+
) -> bytes | None:
|
|
2005
2206
|
'''
|
|
2006
2207
|
See Bluetooth spec Vol 4, Part E - 7.8.27 LE Read Supported States Command
|
|
2007
2208
|
'''
|
|
@@ -2009,7 +2210,7 @@ class Controller:
|
|
|
2009
2210
|
|
|
2010
2211
|
def on_hci_le_read_suggested_default_data_length_command(
|
|
2011
2212
|
self, _command: hci.HCI_LE_Read_Suggested_Default_Data_Length_Command
|
|
2012
|
-
) ->
|
|
2213
|
+
) -> bytes | None:
|
|
2013
2214
|
'''
|
|
2014
2215
|
See Bluetooth spec Vol 4, Part E - 7.8.34 LE Read Suggested Default Data Length
|
|
2015
2216
|
Command
|
|
@@ -2023,7 +2224,7 @@ class Controller:
|
|
|
2023
2224
|
|
|
2024
2225
|
def on_hci_le_write_suggested_default_data_length_command(
|
|
2025
2226
|
self, command: hci.HCI_LE_Write_Suggested_Default_Data_Length_Command
|
|
2026
|
-
) ->
|
|
2227
|
+
) -> bytes | None:
|
|
2027
2228
|
'''
|
|
2028
2229
|
See Bluetooth spec Vol 4, Part E - 7.8.35 LE Write Suggested Default Data Length
|
|
2029
2230
|
Command
|
|
@@ -2035,7 +2236,7 @@ class Controller:
|
|
|
2035
2236
|
|
|
2036
2237
|
def on_hci_le_read_local_p_256_public_key_command(
|
|
2037
2238
|
self, _command: hci.HCI_LE_Read_Local_P_256_Public_Key_Command
|
|
2038
|
-
) ->
|
|
2239
|
+
) -> bytes | None:
|
|
2039
2240
|
'''
|
|
2040
2241
|
See Bluetooth spec Vol 4, Part E - 7.8.36 LE Read P-256 Public Key Command
|
|
2041
2242
|
'''
|
|
@@ -2044,7 +2245,7 @@ class Controller:
|
|
|
2044
2245
|
|
|
2045
2246
|
def on_hci_le_add_device_to_resolving_list_command(
|
|
2046
2247
|
self, _command: hci.HCI_LE_Add_Device_To_Resolving_List_Command
|
|
2047
|
-
) ->
|
|
2248
|
+
) -> bytes | None:
|
|
2048
2249
|
'''
|
|
2049
2250
|
See Bluetooth spec Vol 4, Part E - 7.8.38 LE Add Device To Resolving List
|
|
2050
2251
|
Command
|
|
@@ -2053,7 +2254,7 @@ class Controller:
|
|
|
2053
2254
|
|
|
2054
2255
|
def on_hci_le_clear_resolving_list_command(
|
|
2055
2256
|
self, _command: hci.HCI_LE_Clear_Resolving_List_Command
|
|
2056
|
-
) ->
|
|
2257
|
+
) -> bytes | None:
|
|
2057
2258
|
'''
|
|
2058
2259
|
See Bluetooth spec Vol 4, Part E - 7.8.40 LE Clear Resolving List Command
|
|
2059
2260
|
'''
|
|
@@ -2061,7 +2262,7 @@ class Controller:
|
|
|
2061
2262
|
|
|
2062
2263
|
def on_hci_le_read_resolving_list_size_command(
|
|
2063
2264
|
self, _command: hci.HCI_LE_Read_Resolving_List_Size_Command
|
|
2064
|
-
) ->
|
|
2265
|
+
) -> bytes | None:
|
|
2065
2266
|
'''
|
|
2066
2267
|
See Bluetooth spec Vol 4, Part E - 7.8.41 LE Read Resolving List Size Command
|
|
2067
2268
|
'''
|
|
@@ -2069,7 +2270,7 @@ class Controller:
|
|
|
2069
2270
|
|
|
2070
2271
|
def on_hci_le_set_address_resolution_enable_command(
|
|
2071
2272
|
self, command: hci.HCI_LE_Set_Address_Resolution_Enable_Command
|
|
2072
|
-
) ->
|
|
2273
|
+
) -> bytes | None:
|
|
2073
2274
|
'''
|
|
2074
2275
|
See Bluetooth spec Vol 4, Part E - 7.8.44 LE Set hci.Address Resolution Enable
|
|
2075
2276
|
Command
|
|
@@ -2085,7 +2286,7 @@ class Controller:
|
|
|
2085
2286
|
|
|
2086
2287
|
def on_hci_le_set_resolvable_private_address_timeout_command(
|
|
2087
2288
|
self, command: hci.HCI_LE_Set_Resolvable_Private_Address_Timeout_Command
|
|
2088
|
-
) ->
|
|
2289
|
+
) -> bytes | None:
|
|
2089
2290
|
'''
|
|
2090
2291
|
See Bluetooth spec Vol 4, Part E - 7.8.45 LE Set Resolvable Private hci.Address
|
|
2091
2292
|
Timeout Command
|
|
@@ -2095,7 +2296,7 @@ class Controller:
|
|
|
2095
2296
|
|
|
2096
2297
|
def on_hci_le_read_maximum_data_length_command(
|
|
2097
2298
|
self, _command: hci.HCI_LE_Read_Maximum_Data_Length_Command
|
|
2098
|
-
) ->
|
|
2299
|
+
) -> bytes | None:
|
|
2099
2300
|
'''
|
|
2100
2301
|
See Bluetooth spec Vol 4, Part E - 7.8.46 LE Read Maximum Data Length Command
|
|
2101
2302
|
'''
|
|
@@ -2110,7 +2311,7 @@ class Controller:
|
|
|
2110
2311
|
|
|
2111
2312
|
def on_hci_le_read_phy_command(
|
|
2112
2313
|
self, command: hci.HCI_LE_Read_PHY_Command
|
|
2113
|
-
) ->
|
|
2314
|
+
) -> bytes | None:
|
|
2114
2315
|
'''
|
|
2115
2316
|
See Bluetooth spec Vol 4, Part E - 7.8.47 LE Read PHY Command
|
|
2116
2317
|
'''
|
|
@@ -2124,7 +2325,7 @@ class Controller:
|
|
|
2124
2325
|
|
|
2125
2326
|
def on_hci_le_set_default_phy_command(
|
|
2126
2327
|
self, command: hci.HCI_LE_Set_Default_PHY_Command
|
|
2127
|
-
) ->
|
|
2328
|
+
) -> bytes | None:
|
|
2128
2329
|
'''
|
|
2129
2330
|
See Bluetooth spec Vol 4, Part E - 7.8.48 LE Set Default PHY Command
|
|
2130
2331
|
'''
|
|
@@ -2134,53 +2335,130 @@ class Controller:
|
|
|
2134
2335
|
return bytes([hci.HCI_SUCCESS])
|
|
2135
2336
|
|
|
2136
2337
|
def on_hci_le_set_advertising_set_random_address_command(
|
|
2137
|
-
self,
|
|
2138
|
-
) ->
|
|
2338
|
+
self, command: hci.HCI_LE_Set_Advertising_Set_Random_Address_Command
|
|
2339
|
+
) -> bytes | None:
|
|
2139
2340
|
'''
|
|
2140
2341
|
See Bluetooth spec Vol 4, Part E - 7.8.52 LE Set Advertising Set Random hci.Address
|
|
2141
2342
|
Command
|
|
2142
2343
|
'''
|
|
2344
|
+
handle = command.advertising_handle
|
|
2345
|
+
if handle not in self.advertising_sets:
|
|
2346
|
+
self.advertising_sets[handle] = AdvertisingSet(
|
|
2347
|
+
controller=self, handle=handle
|
|
2348
|
+
)
|
|
2349
|
+
self.advertising_sets[handle].random_address = command.random_address
|
|
2143
2350
|
return bytes([hci.HCI_SUCCESS])
|
|
2144
2351
|
|
|
2145
2352
|
def on_hci_le_set_extended_advertising_parameters_command(
|
|
2146
|
-
self,
|
|
2147
|
-
) ->
|
|
2353
|
+
self, command: hci.HCI_LE_Set_Extended_Advertising_Parameters_Command
|
|
2354
|
+
) -> bytes | None:
|
|
2148
2355
|
'''
|
|
2149
2356
|
See Bluetooth spec Vol 4, Part E - 7.8.53 LE Set Extended Advertising Parameters
|
|
2150
2357
|
Command
|
|
2151
2358
|
'''
|
|
2359
|
+
handle = command.advertising_handle
|
|
2360
|
+
if handle not in self.advertising_sets:
|
|
2361
|
+
self.advertising_sets[handle] = AdvertisingSet(
|
|
2362
|
+
controller=self, handle=handle
|
|
2363
|
+
)
|
|
2364
|
+
|
|
2365
|
+
self.advertising_sets[handle].parameters = command
|
|
2152
2366
|
return bytes([hci.HCI_SUCCESS, 0])
|
|
2153
2367
|
|
|
2154
2368
|
def on_hci_le_set_extended_advertising_data_command(
|
|
2155
|
-
self,
|
|
2156
|
-
) ->
|
|
2369
|
+
self, command: hci.HCI_LE_Set_Extended_Advertising_Data_Command
|
|
2370
|
+
) -> bytes | None:
|
|
2157
2371
|
'''
|
|
2158
2372
|
See Bluetooth spec Vol 4, Part E - 7.8.54 LE Set Extended Advertising Data
|
|
2159
2373
|
Command
|
|
2160
2374
|
'''
|
|
2375
|
+
handle = command.advertising_handle
|
|
2376
|
+
if not (adv_set := self.advertising_sets.get(handle)):
|
|
2377
|
+
return bytes([hci.HCI_UNKNOWN_ADVERTISING_IDENTIFIER_ERROR])
|
|
2378
|
+
|
|
2379
|
+
if command.operation in (
|
|
2380
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.FIRST_FRAGMENT,
|
|
2381
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.COMPLETE_DATA,
|
|
2382
|
+
):
|
|
2383
|
+
adv_set.data = bytearray(command.advertising_data)
|
|
2384
|
+
elif command.operation in (
|
|
2385
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.INTERMEDIATE_FRAGMENT,
|
|
2386
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.LAST_FRAGMENT,
|
|
2387
|
+
):
|
|
2388
|
+
adv_set.data.extend(command.advertising_data)
|
|
2389
|
+
|
|
2161
2390
|
return bytes([hci.HCI_SUCCESS])
|
|
2162
2391
|
|
|
2163
2392
|
def on_hci_le_set_extended_scan_response_data_command(
|
|
2164
|
-
self,
|
|
2165
|
-
) ->
|
|
2393
|
+
self, command: hci.HCI_LE_Set_Extended_Scan_Response_Data_Command
|
|
2394
|
+
) -> bytes | None:
|
|
2166
2395
|
'''
|
|
2167
2396
|
See Bluetooth spec Vol 4, Part E - 7.8.55 LE Set Extended Scan Response Data
|
|
2168
2397
|
Command
|
|
2169
2398
|
'''
|
|
2399
|
+
handle = command.advertising_handle
|
|
2400
|
+
if not (adv_set := self.advertising_sets.get(handle)):
|
|
2401
|
+
return bytes([hci.HCI_UNKNOWN_ADVERTISING_IDENTIFIER_ERROR])
|
|
2402
|
+
|
|
2403
|
+
if command.operation in (
|
|
2404
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.FIRST_FRAGMENT,
|
|
2405
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.COMPLETE_DATA,
|
|
2406
|
+
):
|
|
2407
|
+
adv_set.scan_response_data = bytearray(command.scan_response_data)
|
|
2408
|
+
elif command.operation in (
|
|
2409
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.INTERMEDIATE_FRAGMENT,
|
|
2410
|
+
hci.HCI_LE_Set_Extended_Advertising_Data_Command.Operation.LAST_FRAGMENT,
|
|
2411
|
+
):
|
|
2412
|
+
adv_set.scan_response_data.extend(command.scan_response_data)
|
|
2413
|
+
|
|
2170
2414
|
return bytes([hci.HCI_SUCCESS])
|
|
2171
2415
|
|
|
2172
2416
|
def on_hci_le_set_extended_advertising_enable_command(
|
|
2173
|
-
self,
|
|
2174
|
-
) ->
|
|
2417
|
+
self, command: hci.HCI_LE_Set_Extended_Advertising_Enable_Command
|
|
2418
|
+
) -> bytes | None:
|
|
2175
2419
|
'''
|
|
2176
2420
|
See Bluetooth spec Vol 4, Part E - 7.8.56 LE Set Extended Advertising Enable
|
|
2177
2421
|
Command
|
|
2178
2422
|
'''
|
|
2423
|
+
if command.enable:
|
|
2424
|
+
for handle in command.advertising_handles:
|
|
2425
|
+
if advertising_set := self.advertising_sets.get(handle):
|
|
2426
|
+
advertising_set.start()
|
|
2427
|
+
else:
|
|
2428
|
+
if not command.advertising_handles:
|
|
2429
|
+
for advertising_set in self.advertising_sets.values():
|
|
2430
|
+
advertising_set.stop()
|
|
2431
|
+
else:
|
|
2432
|
+
for handle in command.advertising_handles:
|
|
2433
|
+
if advertising_set := self.advertising_sets.get(handle):
|
|
2434
|
+
advertising_set.stop()
|
|
2435
|
+
return bytes([hci.HCI_SUCCESS])
|
|
2436
|
+
|
|
2437
|
+
def on_hci_le_remove_advertising_set_command(
|
|
2438
|
+
self, command: hci.HCI_LE_Remove_Advertising_Set_Command
|
|
2439
|
+
) -> bytes | None:
|
|
2440
|
+
'''
|
|
2441
|
+
See Bluetooth spec Vol 4, Part E - 7.8.59 LE Remove Advertising Set Command
|
|
2442
|
+
'''
|
|
2443
|
+
handle = command.advertising_handle
|
|
2444
|
+
if advertising_set := self.advertising_sets.pop(handle, None):
|
|
2445
|
+
advertising_set.stop()
|
|
2446
|
+
return bytes([hci.HCI_SUCCESS])
|
|
2447
|
+
|
|
2448
|
+
def on_hci_le_clear_advertising_sets_command(
|
|
2449
|
+
self, _command: hci.HCI_LE_Clear_Advertising_Sets_Command
|
|
2450
|
+
) -> bytes | None:
|
|
2451
|
+
'''
|
|
2452
|
+
See Bluetooth spec Vol 4, Part E - 7.8.60 LE Clear Advertising Sets Command
|
|
2453
|
+
'''
|
|
2454
|
+
for advertising_set in self.advertising_sets.values():
|
|
2455
|
+
advertising_set.stop()
|
|
2456
|
+
self.advertising_sets.clear()
|
|
2179
2457
|
return bytes([hci.HCI_SUCCESS])
|
|
2180
2458
|
|
|
2181
2459
|
def on_hci_le_read_maximum_advertising_data_length_command(
|
|
2182
2460
|
self, _command: hci.HCI_LE_Read_Maximum_Advertising_Data_Length_Command
|
|
2183
|
-
) ->
|
|
2461
|
+
) -> bytes | None:
|
|
2184
2462
|
'''
|
|
2185
2463
|
See Bluetooth spec Vol 4, Part E - 7.8.57 LE Read Maximum Advertising Data
|
|
2186
2464
|
Length Command
|
|
@@ -2189,7 +2467,7 @@ class Controller:
|
|
|
2189
2467
|
|
|
2190
2468
|
def on_hci_le_read_number_of_supported_advertising_sets_command(
|
|
2191
2469
|
self, _command: hci.HCI_LE_Read_Number_Of_Supported_Advertising_Sets_Command
|
|
2192
|
-
) ->
|
|
2470
|
+
) -> bytes | None:
|
|
2193
2471
|
'''
|
|
2194
2472
|
See Bluetooth spec Vol 4, Part E - 7.8.58 LE Read Number of Supported
|
|
2195
2473
|
Advertising Set Command
|
|
@@ -2198,7 +2476,7 @@ class Controller:
|
|
|
2198
2476
|
|
|
2199
2477
|
def on_hci_le_set_periodic_advertising_parameters_command(
|
|
2200
2478
|
self, _command: hci.HCI_LE_Set_Periodic_Advertising_Parameters_Command
|
|
2201
|
-
) ->
|
|
2479
|
+
) -> bytes | None:
|
|
2202
2480
|
'''
|
|
2203
2481
|
See Bluetooth spec Vol 4, Part E - 7.8.61 LE Set Periodic Advertising Parameters
|
|
2204
2482
|
Command
|
|
@@ -2207,7 +2485,7 @@ class Controller:
|
|
|
2207
2485
|
|
|
2208
2486
|
def on_hci_le_set_periodic_advertising_data_command(
|
|
2209
2487
|
self, _command: hci.HCI_LE_Set_Periodic_Advertising_Data_Command
|
|
2210
|
-
) ->
|
|
2488
|
+
) -> bytes | None:
|
|
2211
2489
|
'''
|
|
2212
2490
|
See Bluetooth spec Vol 4, Part E - 7.8.62 LE Set Periodic Advertising Data
|
|
2213
2491
|
Command
|
|
@@ -2216,7 +2494,7 @@ class Controller:
|
|
|
2216
2494
|
|
|
2217
2495
|
def on_hci_le_set_periodic_advertising_enable_command(
|
|
2218
2496
|
self, _command: hci.HCI_LE_Set_Periodic_Advertising_Enable_Command
|
|
2219
|
-
) ->
|
|
2497
|
+
) -> bytes | None:
|
|
2220
2498
|
'''
|
|
2221
2499
|
See Bluetooth spec Vol 4, Part E - 7.8.63 LE Set Periodic Advertising Enable
|
|
2222
2500
|
Command
|
|
@@ -2225,7 +2503,7 @@ class Controller:
|
|
|
2225
2503
|
|
|
2226
2504
|
def on_hci_le_read_transmit_power_command(
|
|
2227
2505
|
self, _command: hci.HCI_LE_Read_Transmit_Power_Command
|
|
2228
|
-
) ->
|
|
2506
|
+
) -> bytes | None:
|
|
2229
2507
|
'''
|
|
2230
2508
|
See Bluetooth spec Vol 4, Part E - 7.8.74 LE Read Transmit Power Command
|
|
2231
2509
|
'''
|
|
@@ -2233,7 +2511,7 @@ class Controller:
|
|
|
2233
2511
|
|
|
2234
2512
|
def on_hci_le_set_cig_parameters_command(
|
|
2235
2513
|
self, command: hci.HCI_LE_Set_CIG_Parameters_Command
|
|
2236
|
-
) ->
|
|
2514
|
+
) -> bytes | None:
|
|
2237
2515
|
'''
|
|
2238
2516
|
See Bluetooth spec Vol 4, Part E - 7.8.97 LE Set CIG Parameter Command
|
|
2239
2517
|
'''
|
|
@@ -2259,7 +2537,7 @@ class Controller:
|
|
|
2259
2537
|
|
|
2260
2538
|
def on_hci_le_create_cis_command(
|
|
2261
2539
|
self, command: hci.HCI_LE_Create_CIS_Command
|
|
2262
|
-
) ->
|
|
2540
|
+
) -> bytes | None:
|
|
2263
2541
|
'''
|
|
2264
2542
|
See Bluetooth spec Vol 4, Part E - 7.8.99 LE Create CIS Command
|
|
2265
2543
|
'''
|
|
@@ -2279,11 +2557,8 @@ class Controller:
|
|
|
2279
2557
|
|
|
2280
2558
|
cis_link.acl_connection = connection
|
|
2281
2559
|
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
peripheral_address=connection.peer_address,
|
|
2285
|
-
cig_id=cis_link.cig_id,
|
|
2286
|
-
cis_id=cis_link.cis_id,
|
|
2560
|
+
connection.send_ll_control_pdu(
|
|
2561
|
+
ll.CisReq(cig_id=cis_link.cig_id, cis_id=cis_link.cis_id)
|
|
2287
2562
|
)
|
|
2288
2563
|
|
|
2289
2564
|
self.send_hci_packet(
|
|
@@ -2297,7 +2572,7 @@ class Controller:
|
|
|
2297
2572
|
|
|
2298
2573
|
def on_hci_le_remove_cig_command(
|
|
2299
2574
|
self, command: hci.HCI_LE_Remove_CIG_Command
|
|
2300
|
-
) ->
|
|
2575
|
+
) -> bytes | None:
|
|
2301
2576
|
'''
|
|
2302
2577
|
See Bluetooth spec Vol 4, Part E - 7.8.100 LE Remove CIG Command
|
|
2303
2578
|
'''
|
|
@@ -2314,7 +2589,7 @@ class Controller:
|
|
|
2314
2589
|
|
|
2315
2590
|
def on_hci_le_accept_cis_request_command(
|
|
2316
2591
|
self, command: hci.HCI_LE_Accept_CIS_Request_Command
|
|
2317
|
-
) ->
|
|
2592
|
+
) -> bytes | None:
|
|
2318
2593
|
'''
|
|
2319
2594
|
See Bluetooth spec Vol 4, Part E - 7.8.101 LE Accept CIS Request Command
|
|
2320
2595
|
'''
|
|
@@ -2328,11 +2603,8 @@ class Controller:
|
|
|
2328
2603
|
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
2329
2604
|
|
|
2330
2605
|
assert pending_cis_link.acl_connection
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
central_address=pending_cis_link.acl_connection.peer_address,
|
|
2334
|
-
cig_id=pending_cis_link.cig_id,
|
|
2335
|
-
cis_id=pending_cis_link.cis_id,
|
|
2606
|
+
pending_cis_link.acl_connection.send_ll_control_pdu(
|
|
2607
|
+
ll.CisRsp(cig_id=pending_cis_link.cig_id, cis_id=pending_cis_link.cis_id),
|
|
2336
2608
|
)
|
|
2337
2609
|
|
|
2338
2610
|
self.send_hci_packet(
|
|
@@ -2346,7 +2618,7 @@ class Controller:
|
|
|
2346
2618
|
|
|
2347
2619
|
def on_hci_le_setup_iso_data_path_command(
|
|
2348
2620
|
self, command: hci.HCI_LE_Setup_ISO_Data_Path_Command
|
|
2349
|
-
) ->
|
|
2621
|
+
) -> bytes | None:
|
|
2350
2622
|
'''
|
|
2351
2623
|
See Bluetooth spec Vol 4, Part E - 7.8.109 LE Setup ISO Data Path Command
|
|
2352
2624
|
'''
|
|
@@ -2367,7 +2639,7 @@ class Controller:
|
|
|
2367
2639
|
|
|
2368
2640
|
def on_hci_le_remove_iso_data_path_command(
|
|
2369
2641
|
self, command: hci.HCI_LE_Remove_ISO_Data_Path_Command
|
|
2370
|
-
) ->
|
|
2642
|
+
) -> bytes | None:
|
|
2371
2643
|
'''
|
|
2372
2644
|
See Bluetooth spec Vol 4, Part E - 7.8.110 LE Remove ISO Data Path Command
|
|
2373
2645
|
'''
|
|
@@ -2393,7 +2665,7 @@ class Controller:
|
|
|
2393
2665
|
|
|
2394
2666
|
def on_hci_le_set_host_feature_command(
|
|
2395
2667
|
self, _command: hci.HCI_LE_Set_Host_Feature_Command
|
|
2396
|
-
) ->
|
|
2668
|
+
) -> bytes | None:
|
|
2397
2669
|
'''
|
|
2398
2670
|
See Bluetooth spec Vol 4, Part E - 7.8.115 LE Set Host Feature command
|
|
2399
2671
|
'''
|