bumble 0.0.219__py3-none-any.whl → 0.0.220__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/apps/auracast.py +7 -13
- bumble/audio/io.py +3 -3
- bumble/controller.py +588 -302
- bumble/device.py +107 -183
- bumble/link.py +68 -165
- bumble/lmp.py +324 -0
- bumble/snoop.py +10 -4
- bumble/utils.py +1 -5
- {bumble-0.0.219.dist-info → bumble-0.0.220.dist-info}/METADATA +2 -2
- {bumble-0.0.219.dist-info → bumble-0.0.220.dist-info}/RECORD +15 -14
- {bumble-0.0.219.dist-info → bumble-0.0.220.dist-info}/WHEEL +0 -0
- {bumble-0.0.219.dist-info → bumble-0.0.220.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.219.dist-info → bumble-0.0.220.dist-info}/licenses/LICENSE +0 -0
- {bumble-0.0.219.dist-info → bumble-0.0.220.dist-info}/top_level.txt +0 -0
bumble/controller.py
CHANGED
|
@@ -23,45 +23,11 @@ import itertools
|
|
|
23
23
|
import logging
|
|
24
24
|
import random
|
|
25
25
|
import struct
|
|
26
|
-
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
26
|
+
from typing import TYPE_CHECKING, Any, Optional, Union, cast
|
|
27
27
|
|
|
28
|
-
from bumble import hci
|
|
28
|
+
from bumble import hci, lmp
|
|
29
29
|
from bumble.colors import color
|
|
30
30
|
from bumble.core import PhysicalTransport
|
|
31
|
-
from bumble.hci import (
|
|
32
|
-
HCI_ACL_DATA_PACKET,
|
|
33
|
-
HCI_COMMAND_DISALLOWED_ERROR,
|
|
34
|
-
HCI_COMMAND_PACKET,
|
|
35
|
-
HCI_COMMAND_STATUS_PENDING,
|
|
36
|
-
HCI_CONTROLLER_BUSY_ERROR,
|
|
37
|
-
HCI_EVENT_PACKET,
|
|
38
|
-
HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR,
|
|
39
|
-
HCI_LE_1M_PHY,
|
|
40
|
-
HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR,
|
|
41
|
-
HCI_SUCCESS,
|
|
42
|
-
HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
43
|
-
HCI_UNKNOWN_HCI_COMMAND_ERROR,
|
|
44
|
-
HCI_VERSION_BLUETOOTH_CORE_5_0,
|
|
45
|
-
Address,
|
|
46
|
-
HCI_AclDataPacket,
|
|
47
|
-
HCI_AclDataPacketAssembler,
|
|
48
|
-
HCI_Command_Complete_Event,
|
|
49
|
-
HCI_Command_Status_Event,
|
|
50
|
-
HCI_Connection_Complete_Event,
|
|
51
|
-
HCI_Connection_Request_Event,
|
|
52
|
-
HCI_Disconnection_Complete_Event,
|
|
53
|
-
HCI_Encryption_Change_Event,
|
|
54
|
-
HCI_LE_Advertising_Report_Event,
|
|
55
|
-
HCI_LE_CIS_Established_Event,
|
|
56
|
-
HCI_LE_CIS_Request_Event,
|
|
57
|
-
HCI_LE_Connection_Complete_Event,
|
|
58
|
-
HCI_LE_Read_Remote_Features_Complete_Event,
|
|
59
|
-
HCI_Number_Of_Completed_Packets_Event,
|
|
60
|
-
HCI_Packet,
|
|
61
|
-
HCI_Role_Change_Event,
|
|
62
|
-
HCI_Synchronous_Connection_Complete_Event,
|
|
63
|
-
Role,
|
|
64
|
-
)
|
|
65
31
|
|
|
66
32
|
if TYPE_CHECKING:
|
|
67
33
|
from bumble.link import LocalLink
|
|
@@ -90,24 +56,33 @@ class CisLink:
|
|
|
90
56
|
data_paths: set[int] = dataclasses.field(default_factory=set)
|
|
91
57
|
|
|
92
58
|
|
|
59
|
+
# -----------------------------------------------------------------------------
|
|
60
|
+
@dataclasses.dataclass
|
|
61
|
+
class ScoLink:
|
|
62
|
+
handle: int
|
|
63
|
+
link_type: int
|
|
64
|
+
peer_address: hci.Address
|
|
65
|
+
|
|
66
|
+
|
|
93
67
|
# -----------------------------------------------------------------------------
|
|
94
68
|
@dataclasses.dataclass
|
|
95
69
|
class Connection:
|
|
96
70
|
controller: Controller
|
|
97
71
|
handle: int
|
|
98
|
-
role: Role
|
|
99
|
-
peer_address: Address
|
|
72
|
+
role: hci.Role
|
|
73
|
+
peer_address: hci.Address
|
|
100
74
|
link: Any
|
|
101
75
|
transport: int
|
|
102
76
|
link_type: int
|
|
77
|
+
classic_allow_role_switch: bool = False
|
|
103
78
|
|
|
104
79
|
def __post_init__(self) -> None:
|
|
105
|
-
self.assembler = HCI_AclDataPacketAssembler(self.on_acl_pdu)
|
|
80
|
+
self.assembler = hci.HCI_AclDataPacketAssembler(self.on_acl_pdu)
|
|
106
81
|
|
|
107
82
|
def on_hci_acl_data_packet(self, packet: hci.HCI_AclDataPacket) -> None:
|
|
108
83
|
self.assembler.feed_packet(packet)
|
|
109
84
|
self.controller.send_hci_packet(
|
|
110
|
-
HCI_Number_Of_Completed_Packets_Event(
|
|
85
|
+
hci.HCI_Number_Of_Completed_Packets_Event(
|
|
111
86
|
connection_handles=[self.handle], num_completed_packets=[1]
|
|
112
87
|
)
|
|
113
88
|
)
|
|
@@ -124,18 +99,20 @@ class Controller:
|
|
|
124
99
|
hci_sink: Optional[TransportSink] = None
|
|
125
100
|
|
|
126
101
|
central_connections: dict[
|
|
127
|
-
Address, Connection
|
|
102
|
+
hci.Address, Connection
|
|
128
103
|
] # Connections where this controller is the central
|
|
129
104
|
peripheral_connections: dict[
|
|
130
|
-
Address, Connection
|
|
105
|
+
hci.Address, Connection
|
|
131
106
|
] # Connections where this controller is the peripheral
|
|
132
|
-
classic_connections: dict[Address, Connection] # Connections in BR/EDR
|
|
107
|
+
classic_connections: dict[hci.Address, Connection] # Connections in BR/EDR
|
|
108
|
+
classic_pending_commands: dict[hci.Address, dict[lmp.Opcode, asyncio.Future[int]]]
|
|
109
|
+
sco_links: dict[hci.Address, ScoLink] # SCO links by address
|
|
133
110
|
central_cis_links: dict[int, CisLink] # CIS links by handle
|
|
134
111
|
peripheral_cis_links: dict[int, CisLink] # CIS links by handle
|
|
135
112
|
|
|
136
|
-
hci_version: int = HCI_VERSION_BLUETOOTH_CORE_5_0
|
|
113
|
+
hci_version: int = hci.HCI_VERSION_BLUETOOTH_CORE_5_0
|
|
137
114
|
hci_revision: int = 0
|
|
138
|
-
lmp_version: int = HCI_VERSION_BLUETOOTH_CORE_5_0
|
|
115
|
+
lmp_version: int = hci.HCI_VERSION_BLUETOOTH_CORE_5_0
|
|
139
116
|
lmp_subversion: int = 0
|
|
140
117
|
lmp_features: bytes = bytes.fromhex(
|
|
141
118
|
'0000000060000000'
|
|
@@ -174,7 +151,7 @@ class Controller:
|
|
|
174
151
|
le_scan_interval: int = 0x10
|
|
175
152
|
le_scan_window: int = 0x10
|
|
176
153
|
le_scan_enable: int = 0
|
|
177
|
-
le_scan_own_address_type: int = Address.RANDOM_DEVICE_ADDRESS
|
|
154
|
+
le_scan_own_address_type: int = hci.Address.RANDOM_DEVICE_ADDRESS
|
|
178
155
|
le_scanning_filter_policy: int = 0
|
|
179
156
|
le_scan_response_data: Optional[bytes] = None
|
|
180
157
|
le_address_resolution: bool = False
|
|
@@ -184,8 +161,10 @@ class Controller:
|
|
|
184
161
|
advertising_interval: int = 2000
|
|
185
162
|
advertising_data: Optional[bytes] = None
|
|
186
163
|
advertising_timer_handle: Optional[asyncio.Handle] = None
|
|
164
|
+
classic_scan_enable: int = 0
|
|
165
|
+
classic_allow_role_switch: bool = True
|
|
187
166
|
|
|
188
|
-
_random_address:
|
|
167
|
+
_random_address: hci.Address = hci.Address('00:00:00:00:00:00')
|
|
189
168
|
|
|
190
169
|
def __init__(
|
|
191
170
|
self,
|
|
@@ -193,13 +172,15 @@ class Controller:
|
|
|
193
172
|
host_source=None,
|
|
194
173
|
host_sink: Optional[TransportSink] = None,
|
|
195
174
|
link: Optional[LocalLink] = None,
|
|
196
|
-
public_address: Optional[Union[bytes, str, Address]] = None,
|
|
175
|
+
public_address: Optional[Union[bytes, str, hci.Address]] = None,
|
|
197
176
|
) -> None:
|
|
198
177
|
self.name = name
|
|
199
178
|
self.link = link
|
|
200
179
|
self.central_connections = {}
|
|
201
180
|
self.peripheral_connections = {}
|
|
202
181
|
self.classic_connections = {}
|
|
182
|
+
self.sco_links = {}
|
|
183
|
+
self.classic_pending_commands = {}
|
|
203
184
|
self.central_cis_links = {}
|
|
204
185
|
self.peripheral_cis_links = {}
|
|
205
186
|
self.default_phy = {
|
|
@@ -208,14 +189,14 @@ class Controller:
|
|
|
208
189
|
'rx_phys': 0,
|
|
209
190
|
}
|
|
210
191
|
|
|
211
|
-
if isinstance(public_address, Address):
|
|
192
|
+
if isinstance(public_address, hci.Address):
|
|
212
193
|
self._public_address = public_address
|
|
213
194
|
elif public_address is not None:
|
|
214
|
-
self._public_address = Address(
|
|
215
|
-
public_address, Address.PUBLIC_DEVICE_ADDRESS
|
|
195
|
+
self._public_address = hci.Address(
|
|
196
|
+
public_address, hci.Address.PUBLIC_DEVICE_ADDRESS
|
|
216
197
|
)
|
|
217
198
|
else:
|
|
218
|
-
self._public_address = Address('00:00:00:00:00:00')
|
|
199
|
+
self._public_address = hci.Address('00:00:00:00:00:00')
|
|
219
200
|
|
|
220
201
|
# Set the source and sink interfaces
|
|
221
202
|
if host_source:
|
|
@@ -249,23 +230,23 @@ class Controller:
|
|
|
249
230
|
self.hci_sink = sink
|
|
250
231
|
|
|
251
232
|
@property
|
|
252
|
-
def public_address(self) -> Address:
|
|
233
|
+
def public_address(self) -> hci.Address:
|
|
253
234
|
return self._public_address
|
|
254
235
|
|
|
255
236
|
@public_address.setter
|
|
256
|
-
def public_address(self, address: Union[Address, str]) -> None:
|
|
237
|
+
def public_address(self, address: Union[hci.Address, str]) -> None:
|
|
257
238
|
if isinstance(address, str):
|
|
258
|
-
address = Address(address)
|
|
239
|
+
address = hci.Address(address)
|
|
259
240
|
self._public_address = address
|
|
260
241
|
|
|
261
242
|
@property
|
|
262
|
-
def random_address(self) -> Address:
|
|
243
|
+
def random_address(self) -> hci.Address:
|
|
263
244
|
return self._random_address
|
|
264
245
|
|
|
265
246
|
@random_address.setter
|
|
266
|
-
def random_address(self, address: Union[Address, str]) -> None:
|
|
247
|
+
def random_address(self, address: Union[hci.Address, str]) -> None:
|
|
267
248
|
if isinstance(address, str):
|
|
268
|
-
address = Address(address)
|
|
249
|
+
address = hci.Address(address)
|
|
269
250
|
self._random_address = address
|
|
270
251
|
logger.debug(f'new random address: {address}')
|
|
271
252
|
|
|
@@ -274,9 +255,9 @@ class Controller:
|
|
|
274
255
|
|
|
275
256
|
# Packet Sink protocol (packets coming from the host via HCI)
|
|
276
257
|
def on_packet(self, packet: bytes) -> None:
|
|
277
|
-
self.on_hci_packet(HCI_Packet.from_bytes(packet))
|
|
258
|
+
self.on_hci_packet(hci.HCI_Packet.from_bytes(packet))
|
|
278
259
|
|
|
279
|
-
def on_hci_packet(self, packet: HCI_Packet) -> None:
|
|
260
|
+
def on_hci_packet(self, packet: hci.HCI_Packet) -> None:
|
|
280
261
|
logger.debug(
|
|
281
262
|
f'{color("<<<", "blue")} [{self.name}] '
|
|
282
263
|
f'{color("HOST -> CONTROLLER", "blue")}: {packet}'
|
|
@@ -298,14 +279,14 @@ class Controller:
|
|
|
298
279
|
result: Optional[bytes] = handler(command)
|
|
299
280
|
if isinstance(result, bytes):
|
|
300
281
|
self.send_hci_packet(
|
|
301
|
-
HCI_Command_Complete_Event(
|
|
282
|
+
hci.HCI_Command_Complete_Event(
|
|
302
283
|
num_hci_command_packets=1,
|
|
303
284
|
command_opcode=command.op_code,
|
|
304
285
|
return_parameters=result,
|
|
305
286
|
)
|
|
306
287
|
)
|
|
307
288
|
|
|
308
|
-
def on_hci_event_packet(self, _event: HCI_Packet) -> None:
|
|
289
|
+
def on_hci_event_packet(self, _event: hci.HCI_Packet) -> None:
|
|
309
290
|
logger.warning('!!! unexpected event packet')
|
|
310
291
|
|
|
311
292
|
def on_hci_acl_data_packet(self, packet: hci.HCI_AclDataPacket) -> None:
|
|
@@ -320,13 +301,13 @@ class Controller:
|
|
|
320
301
|
# Pass the packet to the connection
|
|
321
302
|
connection.on_hci_acl_data_packet(packet)
|
|
322
303
|
|
|
323
|
-
def send_hci_packet(self, packet: HCI_Packet) -> None:
|
|
304
|
+
def send_hci_packet(self, packet: hci.HCI_Packet) -> None:
|
|
324
305
|
logger.debug(
|
|
325
306
|
f'{color(">>>", "green")} [{self.name}] '
|
|
326
307
|
f'{color("CONTROLLER -> HOST", "green")}: {packet}'
|
|
327
308
|
)
|
|
328
309
|
if self.host:
|
|
329
|
-
self.host.on_packet
|
|
310
|
+
asyncio.get_running_loop().call_soon(self.host.on_packet, bytes(packet))
|
|
330
311
|
|
|
331
312
|
# This method allows the controller to emulate the same API as a transport source
|
|
332
313
|
async def wait_for_termination(self) -> None:
|
|
@@ -336,33 +317,30 @@ class Controller:
|
|
|
336
317
|
# Link connections
|
|
337
318
|
############################################################
|
|
338
319
|
def allocate_connection_handle(self) -> int:
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
)
|
|
353
|
-
max_handle = max(max_handle, cis_handle)
|
|
354
|
-
if cis_handle == handle:
|
|
355
|
-
# Already used, continue searching after the current max
|
|
356
|
-
handle = max_handle + 1
|
|
357
|
-
return handle
|
|
320
|
+
current_handles = set(
|
|
321
|
+
cast(Connection | CisLink | ScoLink, link).handle
|
|
322
|
+
for link in itertools.chain(
|
|
323
|
+
self.central_connections.values(),
|
|
324
|
+
self.peripheral_connections.values(),
|
|
325
|
+
self.classic_connections.values(),
|
|
326
|
+
self.sco_links.values(),
|
|
327
|
+
self.central_cis_links.values(),
|
|
328
|
+
self.peripheral_cis_links.values(),
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
return next(
|
|
332
|
+
handle for handle in range(0xEFF + 1) if handle not in current_handles
|
|
333
|
+
)
|
|
358
334
|
|
|
359
|
-
def find_le_connection_by_address(
|
|
335
|
+
def find_le_connection_by_address(
|
|
336
|
+
self, address: hci.Address
|
|
337
|
+
) -> Optional[Connection]:
|
|
360
338
|
return self.central_connections.get(address) or self.peripheral_connections.get(
|
|
361
339
|
address
|
|
362
340
|
)
|
|
363
341
|
|
|
364
342
|
def find_classic_connection_by_address(
|
|
365
|
-
self, address: Address
|
|
343
|
+
self, address: hci.Address
|
|
366
344
|
) -> Optional[Connection]:
|
|
367
345
|
return self.classic_connections.get(address)
|
|
368
346
|
|
|
@@ -394,12 +372,18 @@ class Controller:
|
|
|
394
372
|
return connection
|
|
395
373
|
return None
|
|
396
374
|
|
|
375
|
+
def find_classic_sco_link_by_handle(self, handle: int) -> Optional[ScoLink]:
|
|
376
|
+
for connection in self.sco_links.values():
|
|
377
|
+
if connection.handle == handle:
|
|
378
|
+
return connection
|
|
379
|
+
return None
|
|
380
|
+
|
|
397
381
|
def find_iso_link_by_handle(self, handle: int) -> Optional[CisLink]:
|
|
398
382
|
return self.central_cis_links.get(handle) or self.peripheral_cis_links.get(
|
|
399
383
|
handle
|
|
400
384
|
)
|
|
401
385
|
|
|
402
|
-
def on_link_central_connected(self, central_address: Address) -> None:
|
|
386
|
+
def on_link_central_connected(self, central_address: hci.Address) -> None:
|
|
403
387
|
'''
|
|
404
388
|
Called when an incoming connection occurs from a central on the link
|
|
405
389
|
'''
|
|
@@ -413,19 +397,19 @@ class Controller:
|
|
|
413
397
|
connection = Connection(
|
|
414
398
|
controller=self,
|
|
415
399
|
handle=connection_handle,
|
|
416
|
-
role=Role.PERIPHERAL,
|
|
400
|
+
role=hci.Role.PERIPHERAL,
|
|
417
401
|
peer_address=peer_address,
|
|
418
402
|
link=self.link,
|
|
419
403
|
transport=PhysicalTransport.LE,
|
|
420
|
-
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
404
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
421
405
|
)
|
|
422
406
|
self.peripheral_connections[peer_address] = connection
|
|
423
407
|
logger.debug(f'New PERIPHERAL connection handle: 0x{connection_handle:04X}')
|
|
424
408
|
|
|
425
409
|
# Then say that the connection has completed
|
|
426
410
|
self.send_hci_packet(
|
|
427
|
-
HCI_LE_Connection_Complete_Event(
|
|
428
|
-
status=HCI_SUCCESS,
|
|
411
|
+
hci.HCI_LE_Connection_Complete_Event(
|
|
412
|
+
status=hci.HCI_SUCCESS,
|
|
429
413
|
connection_handle=connection.handle,
|
|
430
414
|
role=connection.role,
|
|
431
415
|
peer_address_type=peer_address_type,
|
|
@@ -437,7 +421,7 @@ class Controller:
|
|
|
437
421
|
)
|
|
438
422
|
)
|
|
439
423
|
|
|
440
|
-
def on_link_disconnected(self, peer_address: Address, reason: int) -> None:
|
|
424
|
+
def on_link_disconnected(self, peer_address: hci.Address, reason: int) -> None:
|
|
441
425
|
'''
|
|
442
426
|
Called when an active disconnection occurs from a peer
|
|
443
427
|
'''
|
|
@@ -445,8 +429,8 @@ class Controller:
|
|
|
445
429
|
# Send a disconnection complete event
|
|
446
430
|
if connection := self.peripheral_connections.get(peer_address):
|
|
447
431
|
self.send_hci_packet(
|
|
448
|
-
HCI_Disconnection_Complete_Event(
|
|
449
|
-
status=HCI_SUCCESS,
|
|
432
|
+
hci.HCI_Disconnection_Complete_Event(
|
|
433
|
+
status=hci.HCI_SUCCESS,
|
|
450
434
|
connection_handle=connection.handle,
|
|
451
435
|
reason=reason,
|
|
452
436
|
)
|
|
@@ -456,8 +440,8 @@ class Controller:
|
|
|
456
440
|
del self.peripheral_connections[peer_address]
|
|
457
441
|
elif connection := self.central_connections.get(peer_address):
|
|
458
442
|
self.send_hci_packet(
|
|
459
|
-
HCI_Disconnection_Complete_Event(
|
|
460
|
-
status=HCI_SUCCESS,
|
|
443
|
+
hci.HCI_Disconnection_Complete_Event(
|
|
444
|
+
status=hci.HCI_SUCCESS,
|
|
461
445
|
connection_handle=connection.handle,
|
|
462
446
|
reason=reason,
|
|
463
447
|
)
|
|
@@ -477,7 +461,7 @@ class Controller:
|
|
|
477
461
|
Called by the link when a connection has been made or has failed to be made
|
|
478
462
|
'''
|
|
479
463
|
|
|
480
|
-
if status == HCI_SUCCESS:
|
|
464
|
+
if status == hci.HCI_SUCCESS:
|
|
481
465
|
# Allocate (or reuse) a connection handle
|
|
482
466
|
peer_address = le_create_connection_command.peer_address
|
|
483
467
|
connection = self.central_connections.get(peer_address)
|
|
@@ -486,11 +470,11 @@ class Controller:
|
|
|
486
470
|
connection = Connection(
|
|
487
471
|
controller=self,
|
|
488
472
|
handle=connection_handle,
|
|
489
|
-
role=Role.CENTRAL,
|
|
473
|
+
role=hci.Role.CENTRAL,
|
|
490
474
|
peer_address=peer_address,
|
|
491
475
|
link=self.link,
|
|
492
476
|
transport=PhysicalTransport.LE,
|
|
493
|
-
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
477
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
494
478
|
)
|
|
495
479
|
self.central_connections[peer_address] = connection
|
|
496
480
|
logger.debug(
|
|
@@ -502,10 +486,10 @@ class Controller:
|
|
|
502
486
|
# Say that the connection has completed
|
|
503
487
|
self.send_hci_packet(
|
|
504
488
|
# pylint: disable=line-too-long
|
|
505
|
-
HCI_LE_Connection_Complete_Event(
|
|
489
|
+
hci.HCI_LE_Connection_Complete_Event(
|
|
506
490
|
status=status,
|
|
507
491
|
connection_handle=connection.handle if connection else 0,
|
|
508
|
-
role=Role.CENTRAL,
|
|
492
|
+
role=hci.Role.CENTRAL,
|
|
509
493
|
peer_address_type=le_create_connection_command.peer_address_type,
|
|
510
494
|
peer_address=le_create_connection_command.peer_address,
|
|
511
495
|
connection_interval=le_create_connection_command.connection_interval_min,
|
|
@@ -524,7 +508,7 @@ class Controller:
|
|
|
524
508
|
|
|
525
509
|
# Send a disconnection complete event
|
|
526
510
|
self.send_hci_packet(
|
|
527
|
-
HCI_Disconnection_Complete_Event(
|
|
511
|
+
hci.HCI_Disconnection_Complete_Event(
|
|
528
512
|
status=status,
|
|
529
513
|
connection_handle=disconnection_command.connection_handle,
|
|
530
514
|
reason=disconnection_command.reason,
|
|
@@ -544,18 +528,18 @@ class Controller:
|
|
|
544
528
|
del self.peripheral_connections[connection.peer_address]
|
|
545
529
|
|
|
546
530
|
def on_link_encrypted(
|
|
547
|
-
self, peer_address: Address, _rand:
|
|
531
|
+
self, peer_address: hci.Address, _rand: bytes, _ediv: int, _ltk: bytes
|
|
548
532
|
) -> None:
|
|
549
533
|
# For now, just setup the encryption without asking the host
|
|
550
534
|
if connection := self.find_le_connection_by_address(peer_address):
|
|
551
535
|
self.send_hci_packet(
|
|
552
|
-
HCI_Encryption_Change_Event(
|
|
536
|
+
hci.HCI_Encryption_Change_Event(
|
|
553
537
|
status=0, connection_handle=connection.handle, encryption_enabled=1
|
|
554
538
|
)
|
|
555
539
|
)
|
|
556
540
|
|
|
557
541
|
def on_link_acl_data(
|
|
558
|
-
self, sender_address: Address, transport: PhysicalTransport, data: bytes
|
|
542
|
+
self, sender_address: hci.Address, transport: PhysicalTransport, data: bytes
|
|
559
543
|
) -> None:
|
|
560
544
|
# Look for the connection to which this data belongs
|
|
561
545
|
if transport == PhysicalTransport.LE:
|
|
@@ -568,36 +552,38 @@ class Controller:
|
|
|
568
552
|
|
|
569
553
|
# Send the data to the host
|
|
570
554
|
# TODO: should fragment
|
|
571
|
-
acl_packet = HCI_AclDataPacket(connection.handle, 2, 0, len(data), data)
|
|
555
|
+
acl_packet = hci.HCI_AclDataPacket(connection.handle, 2, 0, len(data), data)
|
|
572
556
|
self.send_hci_packet(acl_packet)
|
|
573
557
|
|
|
574
|
-
def on_link_advertising_data(
|
|
558
|
+
def on_link_advertising_data(
|
|
559
|
+
self, sender_address: hci.Address, data: bytes
|
|
560
|
+
) -> None:
|
|
575
561
|
# Ignore if we're not scanning
|
|
576
562
|
if self.le_scan_enable == 0:
|
|
577
563
|
return
|
|
578
564
|
|
|
579
565
|
# Send a scan report
|
|
580
|
-
report = HCI_LE_Advertising_Report_Event.Report(
|
|
581
|
-
event_type=HCI_LE_Advertising_Report_Event.EventType.ADV_IND,
|
|
566
|
+
report = hci.HCI_LE_Advertising_Report_Event.Report(
|
|
567
|
+
event_type=hci.HCI_LE_Advertising_Report_Event.EventType.ADV_IND,
|
|
582
568
|
address_type=sender_address.address_type,
|
|
583
569
|
address=sender_address,
|
|
584
570
|
data=data,
|
|
585
571
|
rssi=-50,
|
|
586
572
|
)
|
|
587
|
-
self.send_hci_packet(HCI_LE_Advertising_Report_Event([report]))
|
|
573
|
+
self.send_hci_packet(hci.HCI_LE_Advertising_Report_Event([report]))
|
|
588
574
|
|
|
589
575
|
# Simulate a scan response
|
|
590
|
-
report = HCI_LE_Advertising_Report_Event.Report(
|
|
591
|
-
event_type=HCI_LE_Advertising_Report_Event.EventType.SCAN_RSP,
|
|
576
|
+
report = hci.HCI_LE_Advertising_Report_Event.Report(
|
|
577
|
+
event_type=hci.HCI_LE_Advertising_Report_Event.EventType.SCAN_RSP,
|
|
592
578
|
address_type=sender_address.address_type,
|
|
593
579
|
address=sender_address,
|
|
594
580
|
data=data,
|
|
595
581
|
rssi=-50,
|
|
596
582
|
)
|
|
597
|
-
self.send_hci_packet(HCI_LE_Advertising_Report_Event([report]))
|
|
583
|
+
self.send_hci_packet(hci.HCI_LE_Advertising_Report_Event([report]))
|
|
598
584
|
|
|
599
585
|
def on_link_cis_request(
|
|
600
|
-
self, central_address: Address, cig_id: int, cis_id: int
|
|
586
|
+
self, central_address: hci.Address, cig_id: int, cis_id: int
|
|
601
587
|
) -> None:
|
|
602
588
|
'''
|
|
603
589
|
Called when an incoming CIS request occurs from a central on the link
|
|
@@ -615,7 +601,7 @@ class Controller:
|
|
|
615
601
|
self.peripheral_cis_links[pending_cis_link.handle] = pending_cis_link
|
|
616
602
|
|
|
617
603
|
self.send_hci_packet(
|
|
618
|
-
HCI_LE_CIS_Request_Event(
|
|
604
|
+
hci.HCI_LE_CIS_Request_Event(
|
|
619
605
|
acl_connection_handle=connection.handle,
|
|
620
606
|
cis_connection_handle=pending_cis_link.handle,
|
|
621
607
|
cig_id=cig_id,
|
|
@@ -637,8 +623,8 @@ class Controller:
|
|
|
637
623
|
)
|
|
638
624
|
|
|
639
625
|
self.send_hci_packet(
|
|
640
|
-
HCI_LE_CIS_Established_Event(
|
|
641
|
-
status=HCI_SUCCESS,
|
|
626
|
+
hci.HCI_LE_CIS_Established_Event(
|
|
627
|
+
status=hci.HCI_SUCCESS,
|
|
642
628
|
connection_handle=cis_link.handle,
|
|
643
629
|
# CIS parameters are ignored.
|
|
644
630
|
cig_sync_delay=0,
|
|
@@ -681,16 +667,16 @@ class Controller:
|
|
|
681
667
|
),
|
|
682
668
|
None,
|
|
683
669
|
):
|
|
684
|
-
# Keep central CIS on disconnection. They should be removed by HCI_LE_Remove_CIG_Command.
|
|
670
|
+
# Keep central CIS on disconnection. They should be removed by hci.HCI_LE_Remove_CIG_Command.
|
|
685
671
|
cis_link.acl_connection = None
|
|
686
672
|
else:
|
|
687
673
|
return
|
|
688
674
|
|
|
689
675
|
self.send_hci_packet(
|
|
690
|
-
HCI_Disconnection_Complete_Event(
|
|
691
|
-
status=HCI_SUCCESS,
|
|
676
|
+
hci.HCI_Disconnection_Complete_Event(
|
|
677
|
+
status=hci.HCI_SUCCESS,
|
|
692
678
|
connection_handle=cis_link.handle,
|
|
693
|
-
reason=HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR,
|
|
679
|
+
reason=hci.HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR,
|
|
694
680
|
)
|
|
695
681
|
)
|
|
696
682
|
|
|
@@ -698,11 +684,86 @@ class Controller:
|
|
|
698
684
|
# Classic link connections
|
|
699
685
|
############################################################
|
|
700
686
|
|
|
687
|
+
def send_lmp_packet(
|
|
688
|
+
self, receiver_address: hci.Address, packet: lmp.Packet
|
|
689
|
+
) -> asyncio.Future[int]:
|
|
690
|
+
loop = asyncio.get_running_loop()
|
|
691
|
+
assert self.link
|
|
692
|
+
self.link.send_lmp_packet(self, receiver_address, packet)
|
|
693
|
+
future = self.classic_pending_commands.setdefault(receiver_address, {})[
|
|
694
|
+
packet.opcode
|
|
695
|
+
] = loop.create_future()
|
|
696
|
+
return future
|
|
697
|
+
|
|
698
|
+
def on_lmp_packet(self, sender_address: hci.Address, packet: lmp.Packet):
|
|
699
|
+
if isinstance(packet, (lmp.LmpAccepted, lmp.LmpAcceptedExt)):
|
|
700
|
+
if future := self.classic_pending_commands.setdefault(
|
|
701
|
+
sender_address, {}
|
|
702
|
+
).get(packet.response_opcode):
|
|
703
|
+
future.set_result(hci.HCI_SUCCESS)
|
|
704
|
+
else:
|
|
705
|
+
logger.error("!!! Unhandled packet: %s", packet)
|
|
706
|
+
elif isinstance(packet, (lmp.LmpNotAccepted, lmp.LmpNotAcceptedExt)):
|
|
707
|
+
if future := self.classic_pending_commands.setdefault(
|
|
708
|
+
sender_address, {}
|
|
709
|
+
).get(packet.response_opcode):
|
|
710
|
+
future.set_result(packet.error_code)
|
|
711
|
+
else:
|
|
712
|
+
logger.error("!!! Unhandled packet: %s", packet)
|
|
713
|
+
elif isinstance(packet, (lmp.LmpHostConnectionReq)):
|
|
714
|
+
self.on_classic_connection_request(
|
|
715
|
+
sender_address, hci.HCI_Connection_Complete_Event.LinkType.ACL
|
|
716
|
+
)
|
|
717
|
+
elif isinstance(packet, (lmp.LmpScoLinkReq)):
|
|
718
|
+
self.on_classic_connection_request(
|
|
719
|
+
sender_address, hci.HCI_Connection_Complete_Event.LinkType.SCO
|
|
720
|
+
)
|
|
721
|
+
elif isinstance(packet, (lmp.LmpEscoLinkReq)):
|
|
722
|
+
self.on_classic_connection_request(
|
|
723
|
+
sender_address, hci.HCI_Connection_Complete_Event.LinkType.ESCO
|
|
724
|
+
)
|
|
725
|
+
elif isinstance(packet, (lmp.LmpDetach)):
|
|
726
|
+
self.on_classic_disconnected(
|
|
727
|
+
sender_address, hci.HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR
|
|
728
|
+
)
|
|
729
|
+
elif isinstance(packet, (lmp.LmpSwitchReq)):
|
|
730
|
+
self.on_classic_role_change_request(sender_address)
|
|
731
|
+
elif isinstance(packet, (lmp.LmpRemoveScoLinkReq, lmp.LmpRemoveEscoLinkReq)):
|
|
732
|
+
self.on_classic_sco_disconnected(sender_address, packet.error_code)
|
|
733
|
+
elif isinstance(packet, lmp.LmpNameReq):
|
|
734
|
+
self.on_classic_remote_name_request(sender_address, packet.name_offset)
|
|
735
|
+
elif isinstance(packet, lmp.LmpNameRes):
|
|
736
|
+
self.on_classic_remote_name_response(
|
|
737
|
+
sender_address,
|
|
738
|
+
packet.name_offset,
|
|
739
|
+
packet.name_length,
|
|
740
|
+
packet.name_fregment,
|
|
741
|
+
)
|
|
742
|
+
else:
|
|
743
|
+
logger.error("!!! Unhandled packet: %s", packet)
|
|
744
|
+
|
|
701
745
|
def on_classic_connection_request(
|
|
702
|
-
self, peer_address: Address, link_type: int
|
|
746
|
+
self, peer_address: hci.Address, link_type: int
|
|
703
747
|
) -> None:
|
|
748
|
+
if link_type == hci.HCI_Connection_Complete_Event.LinkType.ACL:
|
|
749
|
+
self.classic_connections[peer_address] = Connection(
|
|
750
|
+
controller=self,
|
|
751
|
+
handle=0,
|
|
752
|
+
role=hci.Role.PERIPHERAL,
|
|
753
|
+
peer_address=peer_address,
|
|
754
|
+
link=self.link,
|
|
755
|
+
transport=PhysicalTransport.BR_EDR,
|
|
756
|
+
link_type=link_type,
|
|
757
|
+
classic_allow_role_switch=self.classic_allow_role_switch,
|
|
758
|
+
)
|
|
759
|
+
else:
|
|
760
|
+
self.sco_links[peer_address] = ScoLink(
|
|
761
|
+
handle=0,
|
|
762
|
+
link_type=link_type,
|
|
763
|
+
peer_address=peer_address,
|
|
764
|
+
)
|
|
704
765
|
self.send_hci_packet(
|
|
705
|
-
HCI_Connection_Request_Event(
|
|
766
|
+
hci.HCI_Connection_Request_Event(
|
|
706
767
|
bd_addr=peer_address,
|
|
707
768
|
class_of_device=0,
|
|
708
769
|
link_type=link_type,
|
|
@@ -710,99 +771,126 @@ class Controller:
|
|
|
710
771
|
)
|
|
711
772
|
|
|
712
773
|
def on_classic_connection_complete(
|
|
713
|
-
self, peer_address: Address, status: int
|
|
774
|
+
self, peer_address: hci.Address, status: int
|
|
714
775
|
) -> None:
|
|
715
|
-
if status == HCI_SUCCESS:
|
|
776
|
+
if status == hci.HCI_SUCCESS:
|
|
716
777
|
# Allocate (or reuse) a connection handle
|
|
717
778
|
peer_address = peer_address
|
|
718
|
-
|
|
719
|
-
if connection
|
|
720
|
-
|
|
779
|
+
connection_handle = self.allocate_connection_handle()
|
|
780
|
+
if connection := self.classic_connections.get(peer_address):
|
|
781
|
+
connection.handle = connection_handle
|
|
782
|
+
else:
|
|
721
783
|
connection = Connection(
|
|
722
784
|
controller=self,
|
|
723
785
|
handle=connection_handle,
|
|
724
|
-
|
|
725
|
-
role=Role.CENTRAL,
|
|
786
|
+
role=hci.Role.CENTRAL,
|
|
726
787
|
peer_address=peer_address,
|
|
727
788
|
link=self.link,
|
|
728
789
|
transport=PhysicalTransport.BR_EDR,
|
|
729
|
-
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
790
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
730
791
|
)
|
|
731
792
|
self.classic_connections[peer_address] = connection
|
|
732
793
|
logger.debug(
|
|
733
794
|
f'New CLASSIC connection handle: 0x{connection_handle:04X}'
|
|
734
795
|
)
|
|
735
|
-
else:
|
|
736
|
-
connection_handle = connection.handle
|
|
737
796
|
self.send_hci_packet(
|
|
738
|
-
HCI_Connection_Complete_Event(
|
|
797
|
+
hci.HCI_Connection_Complete_Event(
|
|
739
798
|
status=status,
|
|
740
799
|
connection_handle=connection_handle,
|
|
741
800
|
bd_addr=peer_address,
|
|
742
801
|
encryption_enabled=False,
|
|
743
|
-
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
802
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
744
803
|
)
|
|
745
804
|
)
|
|
746
805
|
else:
|
|
747
806
|
connection = None
|
|
748
807
|
self.send_hci_packet(
|
|
749
|
-
HCI_Connection_Complete_Event(
|
|
808
|
+
hci.HCI_Connection_Complete_Event(
|
|
750
809
|
status=status,
|
|
751
810
|
connection_handle=0,
|
|
752
811
|
bd_addr=peer_address,
|
|
753
812
|
encryption_enabled=False,
|
|
754
|
-
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
813
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
755
814
|
)
|
|
756
815
|
)
|
|
757
816
|
|
|
758
|
-
def on_classic_disconnected(self, peer_address: Address, reason: int) -> None:
|
|
817
|
+
def on_classic_disconnected(self, peer_address: hci.Address, reason: int) -> None:
|
|
759
818
|
# Send a disconnection complete event
|
|
760
|
-
if connection := self.classic_connections.
|
|
819
|
+
if connection := self.classic_connections.pop(peer_address, None):
|
|
761
820
|
self.send_hci_packet(
|
|
762
|
-
HCI_Disconnection_Complete_Event(
|
|
763
|
-
status=HCI_SUCCESS,
|
|
821
|
+
hci.HCI_Disconnection_Complete_Event(
|
|
822
|
+
status=hci.HCI_SUCCESS,
|
|
764
823
|
connection_handle=connection.handle,
|
|
765
824
|
reason=reason,
|
|
766
825
|
)
|
|
767
826
|
)
|
|
827
|
+
else:
|
|
828
|
+
logger.warning(f'!!! No classic connection found for {peer_address}')
|
|
768
829
|
|
|
769
|
-
|
|
770
|
-
|
|
830
|
+
def on_classic_sco_disconnected(
|
|
831
|
+
self, peer_address: hci.Address, reason: int
|
|
832
|
+
) -> None:
|
|
833
|
+
# Send a disconnection complete event
|
|
834
|
+
if sco_link := self.sco_links.pop(peer_address, None):
|
|
835
|
+
self.send_hci_packet(
|
|
836
|
+
hci.HCI_Disconnection_Complete_Event(
|
|
837
|
+
status=hci.HCI_SUCCESS,
|
|
838
|
+
connection_handle=sco_link.handle,
|
|
839
|
+
reason=reason,
|
|
840
|
+
)
|
|
841
|
+
)
|
|
771
842
|
else:
|
|
772
843
|
logger.warning(f'!!! No classic connection found for {peer_address}')
|
|
773
844
|
|
|
774
|
-
def
|
|
845
|
+
def on_classic_role_change_request(self, peer_address: hci.Address) -> None:
|
|
846
|
+
assert (connection := self.classic_connections.get(peer_address))
|
|
847
|
+
if not connection.classic_allow_role_switch:
|
|
848
|
+
self.send_lmp_packet(
|
|
849
|
+
peer_address,
|
|
850
|
+
lmp.LmpNotAccepted(
|
|
851
|
+
lmp.Opcode.LMP_SWITCH_REQ, hci.HCI_ROLE_CHANGE_NOT_ALLOWED_ERROR
|
|
852
|
+
),
|
|
853
|
+
)
|
|
854
|
+
else:
|
|
855
|
+
self.send_lmp_packet(
|
|
856
|
+
peer_address,
|
|
857
|
+
lmp.LmpAccepted(lmp.Opcode.LMP_SWITCH_REQ),
|
|
858
|
+
)
|
|
859
|
+
self.classic_role_change(connection)
|
|
860
|
+
|
|
861
|
+
def classic_role_change(self, connection: Connection) -> None:
|
|
862
|
+
new_role = (
|
|
863
|
+
hci.Role.CENTRAL
|
|
864
|
+
if connection.role == hci.Role.PERIPHERAL
|
|
865
|
+
else hci.Role.PERIPHERAL
|
|
866
|
+
)
|
|
867
|
+
connection.role = new_role
|
|
775
868
|
self.send_hci_packet(
|
|
776
|
-
HCI_Role_Change_Event(
|
|
777
|
-
status=HCI_SUCCESS,
|
|
778
|
-
bd_addr=peer_address,
|
|
869
|
+
hci.HCI_Role_Change_Event(
|
|
870
|
+
status=hci.HCI_SUCCESS,
|
|
871
|
+
bd_addr=connection.peer_address,
|
|
779
872
|
new_role=new_role,
|
|
780
873
|
)
|
|
781
874
|
)
|
|
782
875
|
|
|
783
876
|
def on_classic_sco_connection_complete(
|
|
784
|
-
self, peer_address: Address, status: int, link_type: int
|
|
877
|
+
self, peer_address: hci.Address, status: int, link_type: int
|
|
785
878
|
) -> None:
|
|
786
|
-
if status == HCI_SUCCESS:
|
|
879
|
+
if status == hci.HCI_SUCCESS:
|
|
787
880
|
# Allocate (or reuse) a connection handle
|
|
788
881
|
connection_handle = self.allocate_connection_handle()
|
|
789
|
-
|
|
790
|
-
controller=self,
|
|
882
|
+
sco_link = ScoLink(
|
|
791
883
|
handle=connection_handle,
|
|
792
|
-
# Role doesn't matter in SCO.
|
|
793
|
-
role=Role.CENTRAL,
|
|
794
|
-
peer_address=peer_address,
|
|
795
|
-
link=self.link,
|
|
796
|
-
transport=PhysicalTransport.BR_EDR,
|
|
797
884
|
link_type=link_type,
|
|
885
|
+
peer_address=peer_address,
|
|
798
886
|
)
|
|
799
|
-
self.
|
|
887
|
+
self.sco_links[peer_address] = sco_link
|
|
800
888
|
logger.debug(f'New SCO connection handle: 0x{connection_handle:04X}')
|
|
801
889
|
else:
|
|
802
890
|
connection_handle = 0
|
|
803
891
|
|
|
804
892
|
self.send_hci_packet(
|
|
805
|
-
HCI_Synchronous_Connection_Complete_Event(
|
|
893
|
+
hci.HCI_Synchronous_Connection_Complete_Event(
|
|
806
894
|
status=status,
|
|
807
895
|
connection_handle=connection_handle,
|
|
808
896
|
bd_addr=peer_address,
|
|
@@ -816,6 +904,33 @@ class Controller:
|
|
|
816
904
|
)
|
|
817
905
|
)
|
|
818
906
|
|
|
907
|
+
def on_classic_remote_name_request(
|
|
908
|
+
self, peer_address: hci.Address, name_offset: int
|
|
909
|
+
):
|
|
910
|
+
self.send_lmp_packet(
|
|
911
|
+
peer_address,
|
|
912
|
+
lmp.LmpNameRes(
|
|
913
|
+
name_offset=name_offset,
|
|
914
|
+
name_length=len(self.local_name),
|
|
915
|
+
name_fregment=self.local_name.encode('utf-8'),
|
|
916
|
+
),
|
|
917
|
+
)
|
|
918
|
+
|
|
919
|
+
def on_classic_remote_name_response(
|
|
920
|
+
self,
|
|
921
|
+
peer_address: hci.Address,
|
|
922
|
+
name_offset: int,
|
|
923
|
+
name_length: int,
|
|
924
|
+
name_fregment: bytes,
|
|
925
|
+
):
|
|
926
|
+
self.send_hci_packet(
|
|
927
|
+
hci.HCI_Remote_Name_Request_Complete_Event(
|
|
928
|
+
status=hci.HCI_SUCCESS,
|
|
929
|
+
bd_addr=peer_address,
|
|
930
|
+
remote_name=name_fregment,
|
|
931
|
+
)
|
|
932
|
+
)
|
|
933
|
+
|
|
819
934
|
############################################################
|
|
820
935
|
# Advertising support
|
|
821
936
|
############################################################
|
|
@@ -852,7 +967,7 @@ class Controller:
|
|
|
852
967
|
############################################################
|
|
853
968
|
def on_hci_command(self, command: hci.HCI_Command) -> Optional[bytes]:
|
|
854
969
|
logger.warning(color(f'--- Unsupported command {command}', 'red'))
|
|
855
|
-
return bytes([HCI_UNKNOWN_HCI_COMMAND_ERROR])
|
|
970
|
+
return bytes([hci.HCI_UNKNOWN_HCI_COMMAND_ERROR])
|
|
856
971
|
|
|
857
972
|
def on_hci_create_connection_command(
|
|
858
973
|
self, command: hci.HCI_Create_Connection_Command
|
|
@@ -868,24 +983,39 @@ class Controller:
|
|
|
868
983
|
# Check that we don't already have a pending connection
|
|
869
984
|
if self.link.get_pending_connection():
|
|
870
985
|
self.send_hci_packet(
|
|
871
|
-
HCI_Command_Status_Event(
|
|
872
|
-
status=HCI_CONTROLLER_BUSY_ERROR,
|
|
986
|
+
hci.HCI_Command_Status_Event(
|
|
987
|
+
status=hci.HCI_CONTROLLER_BUSY_ERROR,
|
|
873
988
|
num_hci_command_packets=1,
|
|
874
989
|
command_opcode=command.op_code,
|
|
875
990
|
)
|
|
876
991
|
)
|
|
877
992
|
return None
|
|
878
993
|
|
|
879
|
-
self.
|
|
994
|
+
self.classic_connections[command.bd_addr] = Connection(
|
|
995
|
+
controller=self,
|
|
996
|
+
handle=0,
|
|
997
|
+
role=hci.Role.CENTRAL,
|
|
998
|
+
peer_address=command.bd_addr,
|
|
999
|
+
link=self.link,
|
|
1000
|
+
transport=PhysicalTransport.BR_EDR,
|
|
1001
|
+
link_type=hci.HCI_Connection_Complete_Event.LinkType.ACL,
|
|
1002
|
+
classic_allow_role_switch=bool(command.allow_role_switch),
|
|
1003
|
+
)
|
|
880
1004
|
|
|
881
1005
|
# Say that the connection is pending
|
|
882
1006
|
self.send_hci_packet(
|
|
883
|
-
HCI_Command_Status_Event(
|
|
884
|
-
status=HCI_COMMAND_STATUS_PENDING,
|
|
1007
|
+
hci.HCI_Command_Status_Event(
|
|
1008
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
885
1009
|
num_hci_command_packets=1,
|
|
886
1010
|
command_opcode=command.op_code,
|
|
887
1011
|
)
|
|
888
1012
|
)
|
|
1013
|
+
future = self.send_lmp_packet(command.bd_addr, lmp.LmpHostConnectionReq())
|
|
1014
|
+
|
|
1015
|
+
def on_response(future: asyncio.Future[int]):
|
|
1016
|
+
self.on_classic_connection_complete(command.bd_addr, future.result())
|
|
1017
|
+
|
|
1018
|
+
future.add_done_callback(on_response)
|
|
889
1019
|
return None
|
|
890
1020
|
|
|
891
1021
|
def on_hci_disconnect_command(
|
|
@@ -896,8 +1026,8 @@ class Controller:
|
|
|
896
1026
|
'''
|
|
897
1027
|
# First, say that the disconnection is pending
|
|
898
1028
|
self.send_hci_packet(
|
|
899
|
-
HCI_Command_Status_Event(
|
|
900
|
-
status=HCI_COMMAND_STATUS_PENDING,
|
|
1029
|
+
hci.HCI_Command_Status_Event(
|
|
1030
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
901
1031
|
num_hci_command_packets=1,
|
|
902
1032
|
command_opcode=command.op_code,
|
|
903
1033
|
)
|
|
@@ -923,14 +1053,37 @@ class Controller:
|
|
|
923
1053
|
del self.peripheral_connections[connection.peer_address]
|
|
924
1054
|
elif connection := self.find_classic_connection_by_handle(handle):
|
|
925
1055
|
if self.link:
|
|
926
|
-
self.
|
|
927
|
-
self,
|
|
1056
|
+
self.send_lmp_packet(
|
|
928
1057
|
connection.peer_address,
|
|
929
|
-
|
|
1058
|
+
lmp.LmpDetach(command.reason),
|
|
930
1059
|
)
|
|
1060
|
+
self.on_classic_disconnected(connection.peer_address, command.reason)
|
|
931
1061
|
else:
|
|
932
1062
|
# Remove the connection
|
|
933
1063
|
del self.classic_connections[connection.peer_address]
|
|
1064
|
+
elif sco_link := self.find_classic_sco_link_by_handle(handle):
|
|
1065
|
+
if self.link:
|
|
1066
|
+
if (
|
|
1067
|
+
sco_link.link_type
|
|
1068
|
+
== hci.HCI_Connection_Complete_Event.LinkType.ESCO
|
|
1069
|
+
):
|
|
1070
|
+
self.send_lmp_packet(
|
|
1071
|
+
sco_link.peer_address,
|
|
1072
|
+
lmp.LmpRemoveScoLinkReq(
|
|
1073
|
+
sco_handle=0, error_code=command.reason
|
|
1074
|
+
),
|
|
1075
|
+
)
|
|
1076
|
+
else:
|
|
1077
|
+
self.send_lmp_packet(
|
|
1078
|
+
sco_link.peer_address,
|
|
1079
|
+
lmp.LmpRemoveEscoLinkReq(
|
|
1080
|
+
esco_handle=0, error_code=command.reason
|
|
1081
|
+
),
|
|
1082
|
+
)
|
|
1083
|
+
self.on_classic_sco_disconnected(sco_link.peer_address, command.reason)
|
|
1084
|
+
else:
|
|
1085
|
+
# Remove the connection
|
|
1086
|
+
del self.sco_links[sco_link.peer_address]
|
|
934
1087
|
elif cis_link := (
|
|
935
1088
|
self.central_cis_links.get(handle) or self.peripheral_cis_links.get(handle)
|
|
936
1089
|
):
|
|
@@ -954,14 +1107,71 @@ class Controller:
|
|
|
954
1107
|
|
|
955
1108
|
if self.link is None:
|
|
956
1109
|
return None
|
|
1110
|
+
|
|
1111
|
+
if not (connection := self.classic_connections.get(command.bd_addr)):
|
|
1112
|
+
self.send_hci_packet(
|
|
1113
|
+
hci.HCI_Command_Status_Event(
|
|
1114
|
+
status=hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
1115
|
+
num_hci_command_packets=1,
|
|
1116
|
+
command_opcode=command.op_code,
|
|
1117
|
+
)
|
|
1118
|
+
)
|
|
1119
|
+
return None
|
|
957
1120
|
self.send_hci_packet(
|
|
958
|
-
HCI_Command_Status_Event(
|
|
959
|
-
status=HCI_SUCCESS,
|
|
1121
|
+
hci.HCI_Command_Status_Event(
|
|
1122
|
+
status=hci.HCI_SUCCESS,
|
|
960
1123
|
num_hci_command_packets=1,
|
|
961
1124
|
command_opcode=command.op_code,
|
|
962
1125
|
)
|
|
963
1126
|
)
|
|
964
|
-
|
|
1127
|
+
|
|
1128
|
+
if command.role == hci.Role.CENTRAL:
|
|
1129
|
+
# Perform role switching before accept.
|
|
1130
|
+
future = self.send_lmp_packet(command.bd_addr, lmp.LmpSwitchReq())
|
|
1131
|
+
|
|
1132
|
+
def on_response(future: asyncio.Future[int]):
|
|
1133
|
+
if (status := future.result()) == hci.HCI_SUCCESS:
|
|
1134
|
+
self.classic_role_change(connection)
|
|
1135
|
+
# Continue connection setup.
|
|
1136
|
+
self.send_lmp_packet(
|
|
1137
|
+
command.bd_addr,
|
|
1138
|
+
lmp.LmpAccepted(lmp.Opcode.LMP_HOST_CONNECTION_REQ),
|
|
1139
|
+
)
|
|
1140
|
+
else:
|
|
1141
|
+
# Abort connection setup.
|
|
1142
|
+
self.send_lmp_packet(
|
|
1143
|
+
command.bd_addr,
|
|
1144
|
+
lmp.LmpNotAccepted(lmp.Opcode.LMP_HOST_CONNECTION_REQ, status),
|
|
1145
|
+
)
|
|
1146
|
+
self.on_classic_connection_complete(command.bd_addr, status)
|
|
1147
|
+
|
|
1148
|
+
future.add_done_callback(on_response)
|
|
1149
|
+
|
|
1150
|
+
else:
|
|
1151
|
+
# Simply accept connection.
|
|
1152
|
+
self.send_lmp_packet(
|
|
1153
|
+
command.bd_addr,
|
|
1154
|
+
lmp.LmpAccepted(lmp.Opcode.LMP_HOST_CONNECTION_REQ),
|
|
1155
|
+
)
|
|
1156
|
+
self.on_classic_connection_complete(command.bd_addr, hci.HCI_SUCCESS)
|
|
1157
|
+
return None
|
|
1158
|
+
|
|
1159
|
+
def on_hci_remote_name_request_command(
|
|
1160
|
+
self, command: hci.HCI_Remote_Name_Request_Command
|
|
1161
|
+
) -> Optional[bytes]:
|
|
1162
|
+
'''
|
|
1163
|
+
See Bluetooth spec Vol 4, Part E - 7.1.19 Remote Name Request command
|
|
1164
|
+
'''
|
|
1165
|
+
self.send_hci_packet(
|
|
1166
|
+
hci.HCI_Command_Status_Event(
|
|
1167
|
+
status=hci.HCI_SUCCESS,
|
|
1168
|
+
num_hci_command_packets=1,
|
|
1169
|
+
command_opcode=command.op_code,
|
|
1170
|
+
)
|
|
1171
|
+
)
|
|
1172
|
+
|
|
1173
|
+
self.send_lmp_packet(command.bd_addr, lmp.LmpNameReq(0))
|
|
1174
|
+
|
|
965
1175
|
return None
|
|
966
1176
|
|
|
967
1177
|
def on_hci_enhanced_setup_synchronous_connection_command(
|
|
@@ -980,8 +1190,8 @@ class Controller:
|
|
|
980
1190
|
)
|
|
981
1191
|
):
|
|
982
1192
|
self.send_hci_packet(
|
|
983
|
-
HCI_Command_Status_Event(
|
|
984
|
-
status=HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
1193
|
+
hci.HCI_Command_Status_Event(
|
|
1194
|
+
status=hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
985
1195
|
num_hci_command_packets=1,
|
|
986
1196
|
command_opcode=command.op_code,
|
|
987
1197
|
)
|
|
@@ -989,15 +1199,38 @@ class Controller:
|
|
|
989
1199
|
return None
|
|
990
1200
|
|
|
991
1201
|
self.send_hci_packet(
|
|
992
|
-
HCI_Command_Status_Event(
|
|
993
|
-
status=HCI_SUCCESS,
|
|
1202
|
+
hci.HCI_Command_Status_Event(
|
|
1203
|
+
status=hci.HCI_SUCCESS,
|
|
994
1204
|
num_hci_command_packets=1,
|
|
995
1205
|
command_opcode=command.op_code,
|
|
996
1206
|
)
|
|
997
1207
|
)
|
|
998
|
-
self.
|
|
999
|
-
|
|
1208
|
+
future = self.send_lmp_packet(
|
|
1209
|
+
connection.peer_address,
|
|
1210
|
+
lmp.LmpEscoLinkReq(
|
|
1211
|
+
esco_handle=0,
|
|
1212
|
+
esco_lt_addr=0,
|
|
1213
|
+
timing_control_flags=0,
|
|
1214
|
+
d_esco=0,
|
|
1215
|
+
t_esco=0,
|
|
1216
|
+
w_esco=0,
|
|
1217
|
+
esco_packet_type_c_to_p=0,
|
|
1218
|
+
esco_packet_type_p_to_c=0,
|
|
1219
|
+
packet_length_c_to_p=0,
|
|
1220
|
+
packet_length_p_to_c=0,
|
|
1221
|
+
air_mode=0,
|
|
1222
|
+
negotiation_state=0,
|
|
1223
|
+
),
|
|
1000
1224
|
)
|
|
1225
|
+
|
|
1226
|
+
def on_response(future: asyncio.Future[int]):
|
|
1227
|
+
self.on_classic_sco_connection_complete(
|
|
1228
|
+
connection.peer_address,
|
|
1229
|
+
future.result(),
|
|
1230
|
+
hci.HCI_Connection_Complete_Event.LinkType.ESCO,
|
|
1231
|
+
)
|
|
1232
|
+
|
|
1233
|
+
future.add_done_callback(on_response)
|
|
1001
1234
|
return None
|
|
1002
1235
|
|
|
1003
1236
|
def on_hci_enhanced_accept_synchronous_connection_request_command(
|
|
@@ -1012,8 +1245,8 @@ class Controller:
|
|
|
1012
1245
|
|
|
1013
1246
|
if not (connection := self.find_classic_connection_by_address(command.bd_addr)):
|
|
1014
1247
|
self.send_hci_packet(
|
|
1015
|
-
HCI_Command_Status_Event(
|
|
1016
|
-
status=HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
1248
|
+
hci.HCI_Command_Status_Event(
|
|
1249
|
+
status=hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
1017
1250
|
num_hci_command_packets=1,
|
|
1018
1251
|
command_opcode=command.op_code,
|
|
1019
1252
|
)
|
|
@@ -1021,14 +1254,20 @@ class Controller:
|
|
|
1021
1254
|
return None
|
|
1022
1255
|
|
|
1023
1256
|
self.send_hci_packet(
|
|
1024
|
-
HCI_Command_Status_Event(
|
|
1025
|
-
status=HCI_SUCCESS,
|
|
1257
|
+
hci.HCI_Command_Status_Event(
|
|
1258
|
+
status=hci.HCI_SUCCESS,
|
|
1026
1259
|
num_hci_command_packets=1,
|
|
1027
1260
|
command_opcode=command.op_code,
|
|
1028
1261
|
)
|
|
1029
1262
|
)
|
|
1030
|
-
self.
|
|
1031
|
-
|
|
1263
|
+
self.send_lmp_packet(
|
|
1264
|
+
connection.peer_address,
|
|
1265
|
+
lmp.LmpAcceptedExt(lmp.Opcode.LMP_ESCO_LINK_REQ),
|
|
1266
|
+
)
|
|
1267
|
+
self.on_classic_sco_connection_complete(
|
|
1268
|
+
connection.peer_address,
|
|
1269
|
+
hci.HCI_SUCCESS,
|
|
1270
|
+
hci.HCI_Connection_Complete_Event.LinkType.ESCO,
|
|
1032
1271
|
)
|
|
1033
1272
|
return None
|
|
1034
1273
|
|
|
@@ -1050,14 +1289,14 @@ class Controller:
|
|
|
1050
1289
|
|
|
1051
1290
|
self.send_hci_packet(
|
|
1052
1291
|
hci.HCI_Command_Status_Event(
|
|
1053
|
-
status=HCI_SUCCESS,
|
|
1292
|
+
status=hci.HCI_SUCCESS,
|
|
1054
1293
|
num_hci_command_packets=1,
|
|
1055
1294
|
command_opcode=command.op_code,
|
|
1056
1295
|
)
|
|
1057
1296
|
)
|
|
1058
1297
|
self.send_hci_packet(
|
|
1059
1298
|
hci.HCI_Mode_Change_Event(
|
|
1060
|
-
status=HCI_SUCCESS,
|
|
1299
|
+
status=hci.HCI_SUCCESS,
|
|
1061
1300
|
connection_handle=command.connection_handle,
|
|
1062
1301
|
current_mode=hci.HCI_Mode_Change_Event.Mode.SNIFF,
|
|
1063
1302
|
interval=2,
|
|
@@ -1084,14 +1323,14 @@ class Controller:
|
|
|
1084
1323
|
|
|
1085
1324
|
self.send_hci_packet(
|
|
1086
1325
|
hci.HCI_Command_Status_Event(
|
|
1087
|
-
status=HCI_SUCCESS,
|
|
1326
|
+
status=hci.HCI_SUCCESS,
|
|
1088
1327
|
num_hci_command_packets=1,
|
|
1089
1328
|
command_opcode=command.op_code,
|
|
1090
1329
|
)
|
|
1091
1330
|
)
|
|
1092
1331
|
self.send_hci_packet(
|
|
1093
1332
|
hci.HCI_Mode_Change_Event(
|
|
1094
|
-
status=HCI_SUCCESS,
|
|
1333
|
+
status=hci.HCI_SUCCESS,
|
|
1095
1334
|
connection_handle=command.connection_handle,
|
|
1096
1335
|
current_mode=hci.HCI_Mode_Change_Event.Mode.ACTIVE,
|
|
1097
1336
|
interval=2,
|
|
@@ -1103,19 +1342,57 @@ class Controller:
|
|
|
1103
1342
|
self, command: hci.HCI_Switch_Role_Command
|
|
1104
1343
|
) -> Optional[bytes]:
|
|
1105
1344
|
'''
|
|
1106
|
-
See Bluetooth spec Vol 4, Part E - 7.2.8 Switch Role command
|
|
1345
|
+
See Bluetooth spec Vol 4, Part E - 7.2.8 Switch hci.Role command
|
|
1107
1346
|
'''
|
|
1108
1347
|
|
|
1109
1348
|
if self.link is None:
|
|
1110
1349
|
return None
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1350
|
+
|
|
1351
|
+
if connection := self.classic_connections.get(command.bd_addr):
|
|
1352
|
+
current_role = connection.role
|
|
1353
|
+
self.send_hci_packet(
|
|
1354
|
+
hci.HCI_Command_Status_Event(
|
|
1355
|
+
status=hci.HCI_SUCCESS,
|
|
1356
|
+
num_hci_command_packets=1,
|
|
1357
|
+
command_opcode=command.op_code,
|
|
1358
|
+
)
|
|
1116
1359
|
)
|
|
1117
|
-
|
|
1118
|
-
|
|
1360
|
+
else:
|
|
1361
|
+
# Connection doesn't exist, reject.
|
|
1362
|
+
self.send_hci_packet(
|
|
1363
|
+
hci.HCI_Command_Status_Event(
|
|
1364
|
+
status=hci.HCI_COMMAND_DISALLOWED_ERROR,
|
|
1365
|
+
num_hci_command_packets=1,
|
|
1366
|
+
command_opcode=command.op_code,
|
|
1367
|
+
)
|
|
1368
|
+
)
|
|
1369
|
+
return None
|
|
1370
|
+
|
|
1371
|
+
# If role doesn't change, only send event to local host.
|
|
1372
|
+
if current_role == command.role:
|
|
1373
|
+
self.send_hci_packet(
|
|
1374
|
+
hci.HCI_Role_Change_Event(
|
|
1375
|
+
status=hci.HCI_SUCCESS,
|
|
1376
|
+
bd_addr=command.bd_addr,
|
|
1377
|
+
new_role=current_role,
|
|
1378
|
+
)
|
|
1379
|
+
)
|
|
1380
|
+
else:
|
|
1381
|
+
future = self.send_lmp_packet(command.bd_addr, lmp.LmpSwitchReq())
|
|
1382
|
+
|
|
1383
|
+
def on_response(future: asyncio.Future[int]):
|
|
1384
|
+
if (status := future.result()) == hci.HCI_SUCCESS:
|
|
1385
|
+
connection.role = hci.Role(command.role)
|
|
1386
|
+
self.send_hci_packet(
|
|
1387
|
+
hci.HCI_Role_Change_Event(
|
|
1388
|
+
status=status,
|
|
1389
|
+
bd_addr=command.bd_addr,
|
|
1390
|
+
new_role=connection.role,
|
|
1391
|
+
)
|
|
1392
|
+
)
|
|
1393
|
+
|
|
1394
|
+
future.add_done_callback(on_response)
|
|
1395
|
+
|
|
1119
1396
|
return None
|
|
1120
1397
|
|
|
1121
1398
|
def on_hci_set_event_mask_command(
|
|
@@ -1127,14 +1404,14 @@ class Controller:
|
|
|
1127
1404
|
self.event_mask = int.from_bytes(
|
|
1128
1405
|
command.event_mask, byteorder='little', signed=False
|
|
1129
1406
|
)
|
|
1130
|
-
return bytes([HCI_SUCCESS])
|
|
1407
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1131
1408
|
|
|
1132
1409
|
def on_hci_reset_command(self, _command: hci.HCI_Reset_Command) -> Optional[bytes]:
|
|
1133
1410
|
'''
|
|
1134
1411
|
See Bluetooth spec Vol 4, Part E - 7.3.2 Reset Command
|
|
1135
1412
|
'''
|
|
1136
1413
|
# TODO: cleanup what needs to be reset
|
|
1137
|
-
return bytes([HCI_SUCCESS])
|
|
1414
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1138
1415
|
|
|
1139
1416
|
def on_hci_write_local_name_command(
|
|
1140
1417
|
self, command: hci.HCI_Write_Local_Name_Command
|
|
@@ -1151,7 +1428,7 @@ class Controller:
|
|
|
1151
1428
|
self.local_name = str(local_name, 'utf-8')
|
|
1152
1429
|
except UnicodeDecodeError:
|
|
1153
1430
|
pass
|
|
1154
|
-
return bytes([HCI_SUCCESS])
|
|
1431
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1155
1432
|
|
|
1156
1433
|
def on_hci_read_local_name_command(
|
|
1157
1434
|
self, _command: hci.HCI_Read_Local_Name_Command
|
|
@@ -1163,7 +1440,7 @@ class Controller:
|
|
|
1163
1440
|
if len(local_name) < 248:
|
|
1164
1441
|
local_name = local_name + bytes(248 - len(local_name))
|
|
1165
1442
|
|
|
1166
|
-
return bytes([HCI_SUCCESS]) + local_name
|
|
1443
|
+
return bytes([hci.HCI_SUCCESS]) + local_name
|
|
1167
1444
|
|
|
1168
1445
|
def on_hci_read_class_of_device_command(
|
|
1169
1446
|
self, _command: hci.HCI_Read_Class_Of_Device_Command
|
|
@@ -1171,7 +1448,7 @@ class Controller:
|
|
|
1171
1448
|
'''
|
|
1172
1449
|
See Bluetooth spec Vol 4, Part E - 7.3.25 Read Class of Device Command
|
|
1173
1450
|
'''
|
|
1174
|
-
return bytes([HCI_SUCCESS, 0, 0, 0])
|
|
1451
|
+
return bytes([hci.HCI_SUCCESS, 0, 0, 0])
|
|
1175
1452
|
|
|
1176
1453
|
def on_hci_write_class_of_device_command(
|
|
1177
1454
|
self, _command: hci.HCI_Write_Class_Of_Device_Command
|
|
@@ -1179,7 +1456,7 @@ class Controller:
|
|
|
1179
1456
|
'''
|
|
1180
1457
|
See Bluetooth spec Vol 4, Part E - 7.3.26 Write Class of Device Command
|
|
1181
1458
|
'''
|
|
1182
|
-
return bytes([HCI_SUCCESS])
|
|
1459
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1183
1460
|
|
|
1184
1461
|
def on_hci_read_synchronous_flow_control_enable_command(
|
|
1185
1462
|
self, _command: hci.HCI_Read_Synchronous_Flow_Control_Enable_Command
|
|
@@ -1192,7 +1469,7 @@ class Controller:
|
|
|
1192
1469
|
ret = 1
|
|
1193
1470
|
else:
|
|
1194
1471
|
ret = 0
|
|
1195
|
-
return bytes([HCI_SUCCESS, ret])
|
|
1472
|
+
return bytes([hci.HCI_SUCCESS, ret])
|
|
1196
1473
|
|
|
1197
1474
|
def on_hci_write_synchronous_flow_control_enable_command(
|
|
1198
1475
|
self, command: hci.HCI_Write_Synchronous_Flow_Control_Enable_Command
|
|
@@ -1201,13 +1478,13 @@ class Controller:
|
|
|
1201
1478
|
See Bluetooth spec Vol 4, Part E - 7.3.37 Write Synchronous Flow Control Enable
|
|
1202
1479
|
Command
|
|
1203
1480
|
'''
|
|
1204
|
-
ret = HCI_SUCCESS
|
|
1481
|
+
ret = hci.HCI_SUCCESS
|
|
1205
1482
|
if command.synchronous_flow_control_enable == 1:
|
|
1206
1483
|
self.sync_flow_control = True
|
|
1207
1484
|
elif command.synchronous_flow_control_enable == 0:
|
|
1208
1485
|
self.sync_flow_control = False
|
|
1209
1486
|
else:
|
|
1210
|
-
ret = HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR
|
|
1487
|
+
ret = hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR
|
|
1211
1488
|
return bytes([ret])
|
|
1212
1489
|
|
|
1213
1490
|
def on_hci_set_controller_to_host_flow_control_command(
|
|
@@ -1219,7 +1496,7 @@ class Controller:
|
|
|
1219
1496
|
'''
|
|
1220
1497
|
# For now we just accept the command but ignore the values.
|
|
1221
1498
|
# TODO: respect the passed in values.
|
|
1222
|
-
return bytes([HCI_SUCCESS])
|
|
1499
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1223
1500
|
|
|
1224
1501
|
def on_hci_host_buffer_size_command(
|
|
1225
1502
|
self, _command: hci.HCI_Host_Buffer_Size_Command
|
|
@@ -1229,7 +1506,7 @@ class Controller:
|
|
|
1229
1506
|
'''
|
|
1230
1507
|
# For now we just accept the command but ignore the values.
|
|
1231
1508
|
# TODO: respect the passed in values.
|
|
1232
|
-
return bytes([HCI_SUCCESS])
|
|
1509
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1233
1510
|
|
|
1234
1511
|
def on_hci_write_extended_inquiry_response_command(
|
|
1235
1512
|
self, _command: hci.HCI_Write_Extended_Inquiry_Response_Command
|
|
@@ -1238,7 +1515,7 @@ class Controller:
|
|
|
1238
1515
|
See Bluetooth spec Vol 4, Part E - 7.3.56 Write Extended Inquiry Response
|
|
1239
1516
|
Command
|
|
1240
1517
|
'''
|
|
1241
|
-
return bytes([HCI_SUCCESS])
|
|
1518
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1242
1519
|
|
|
1243
1520
|
def on_hci_write_simple_pairing_mode_command(
|
|
1244
1521
|
self, _command: hci.HCI_Write_Simple_Pairing_Mode_Command
|
|
@@ -1246,7 +1523,7 @@ class Controller:
|
|
|
1246
1523
|
'''
|
|
1247
1524
|
See Bluetooth spec Vol 4, Part E - 7.3.59 Write Simple Pairing Mode Command
|
|
1248
1525
|
'''
|
|
1249
|
-
return bytes([HCI_SUCCESS])
|
|
1526
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1250
1527
|
|
|
1251
1528
|
def on_hci_set_event_mask_page_2_command(
|
|
1252
1529
|
self, command: hci.HCI_Set_Event_Mask_Page_2_Command
|
|
@@ -1257,7 +1534,7 @@ class Controller:
|
|
|
1257
1534
|
self.event_mask_page_2 = int.from_bytes(
|
|
1258
1535
|
command.event_mask_page_2, byteorder='little', signed=False
|
|
1259
1536
|
)
|
|
1260
|
-
return bytes([HCI_SUCCESS])
|
|
1537
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1261
1538
|
|
|
1262
1539
|
def on_hci_read_le_host_support_command(
|
|
1263
1540
|
self, _command: hci.HCI_Read_LE_Host_Support_Command
|
|
@@ -1265,7 +1542,7 @@ class Controller:
|
|
|
1265
1542
|
'''
|
|
1266
1543
|
See Bluetooth spec Vol 4, Part E - 7.3.78 Write LE Host Support Command
|
|
1267
1544
|
'''
|
|
1268
|
-
return bytes([HCI_SUCCESS, 1, 0])
|
|
1545
|
+
return bytes([hci.HCI_SUCCESS, 1, 0])
|
|
1269
1546
|
|
|
1270
1547
|
def on_hci_write_le_host_support_command(
|
|
1271
1548
|
self, _command: hci.HCI_Write_LE_Host_Support_Command
|
|
@@ -1274,7 +1551,7 @@ class Controller:
|
|
|
1274
1551
|
See Bluetooth spec Vol 4, Part E - 7.3.79 Write LE Host Support Command
|
|
1275
1552
|
'''
|
|
1276
1553
|
# TODO / Just ignore for now
|
|
1277
|
-
return bytes([HCI_SUCCESS])
|
|
1554
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1278
1555
|
|
|
1279
1556
|
def on_hci_write_authenticated_payload_timeout_command(
|
|
1280
1557
|
self, command: hci.HCI_Write_Authenticated_Payload_Timeout_Command
|
|
@@ -1284,7 +1561,7 @@ class Controller:
|
|
|
1284
1561
|
Command
|
|
1285
1562
|
'''
|
|
1286
1563
|
# TODO
|
|
1287
|
-
return struct.pack('<BH', HCI_SUCCESS, command.connection_handle)
|
|
1564
|
+
return struct.pack('<BH', hci.HCI_SUCCESS, command.connection_handle)
|
|
1288
1565
|
|
|
1289
1566
|
def on_hci_read_local_version_information_command(
|
|
1290
1567
|
self, _command: hci.HCI_Read_Local_Version_Information_Command
|
|
@@ -1294,7 +1571,7 @@ class Controller:
|
|
|
1294
1571
|
'''
|
|
1295
1572
|
return struct.pack(
|
|
1296
1573
|
'<BBHBHH',
|
|
1297
|
-
HCI_SUCCESS,
|
|
1574
|
+
hci.HCI_SUCCESS,
|
|
1298
1575
|
self.hci_version,
|
|
1299
1576
|
self.hci_revision,
|
|
1300
1577
|
self.lmp_version,
|
|
@@ -1308,7 +1585,7 @@ class Controller:
|
|
|
1308
1585
|
'''
|
|
1309
1586
|
See Bluetooth spec Vol 4, Part E - 7.4.2 Read Local Supported Commands Command
|
|
1310
1587
|
'''
|
|
1311
|
-
return bytes([HCI_SUCCESS]) + self.supported_commands
|
|
1588
|
+
return bytes([hci.HCI_SUCCESS]) + self.supported_commands
|
|
1312
1589
|
|
|
1313
1590
|
def on_hci_read_local_supported_features_command(
|
|
1314
1591
|
self, _command: hci.HCI_Read_Local_Supported_Features_Command
|
|
@@ -1316,7 +1593,7 @@ class Controller:
|
|
|
1316
1593
|
'''
|
|
1317
1594
|
See Bluetooth spec Vol 4, Part E - 7.4.3 Read Local Supported Features Command
|
|
1318
1595
|
'''
|
|
1319
|
-
return bytes([HCI_SUCCESS]) + self.lmp_features[:8]
|
|
1596
|
+
return bytes([hci.HCI_SUCCESS]) + self.lmp_features[:8]
|
|
1320
1597
|
|
|
1321
1598
|
def on_hci_read_local_extended_features_command(
|
|
1322
1599
|
self, command: hci.HCI_Read_Local_Extended_Features_Command
|
|
@@ -1325,12 +1602,12 @@ class Controller:
|
|
|
1325
1602
|
See Bluetooth spec Vol 4, Part E - 7.4.4 Read Local Extended Features Command
|
|
1326
1603
|
'''
|
|
1327
1604
|
if command.page_number * 8 > len(self.lmp_features):
|
|
1328
|
-
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1605
|
+
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1329
1606
|
return (
|
|
1330
1607
|
bytes(
|
|
1331
1608
|
[
|
|
1332
1609
|
# Status
|
|
1333
|
-
HCI_SUCCESS,
|
|
1610
|
+
hci.HCI_SUCCESS,
|
|
1334
1611
|
# Page number
|
|
1335
1612
|
command.page_number,
|
|
1336
1613
|
# Max page number
|
|
@@ -1349,7 +1626,7 @@ class Controller:
|
|
|
1349
1626
|
'''
|
|
1350
1627
|
return struct.pack(
|
|
1351
1628
|
'<BHBHH',
|
|
1352
|
-
HCI_SUCCESS,
|
|
1629
|
+
hci.HCI_SUCCESS,
|
|
1353
1630
|
self.acl_data_packet_length,
|
|
1354
1631
|
0,
|
|
1355
1632
|
self.total_num_acl_data_packets,
|
|
@@ -1367,7 +1644,7 @@ class Controller:
|
|
|
1367
1644
|
if self._public_address is not None
|
|
1368
1645
|
else bytes(6)
|
|
1369
1646
|
)
|
|
1370
|
-
return bytes([HCI_SUCCESS]) + bd_addr
|
|
1647
|
+
return bytes([hci.HCI_SUCCESS]) + bd_addr
|
|
1371
1648
|
|
|
1372
1649
|
def on_hci_le_set_default_subrate_command(
|
|
1373
1650
|
self, command: hci.HCI_LE_Set_Default_Subrate_Command
|
|
@@ -1381,9 +1658,9 @@ class Controller:
|
|
|
1381
1658
|
or command.subrate_max < command.subrate_min
|
|
1382
1659
|
or command.continuation_number >= command.subrate_max
|
|
1383
1660
|
):
|
|
1384
|
-
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1661
|
+
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1385
1662
|
|
|
1386
|
-
return bytes([HCI_SUCCESS])
|
|
1663
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1387
1664
|
|
|
1388
1665
|
def on_hci_le_subrate_request_command(
|
|
1389
1666
|
self, command: hci.HCI_LE_Subrate_Request_Command
|
|
@@ -1397,7 +1674,7 @@ class Controller:
|
|
|
1397
1674
|
or command.subrate_max < command.subrate_min
|
|
1398
1675
|
or command.continuation_number >= command.subrate_max
|
|
1399
1676
|
):
|
|
1400
|
-
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1677
|
+
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1401
1678
|
|
|
1402
1679
|
self.send_hci_packet(
|
|
1403
1680
|
hci.HCI_Command_Status_Event(
|
|
@@ -1428,7 +1705,7 @@ class Controller:
|
|
|
1428
1705
|
self.le_event_mask = int.from_bytes(
|
|
1429
1706
|
command.le_event_mask, byteorder='little', signed=False
|
|
1430
1707
|
)
|
|
1431
|
-
return bytes([HCI_SUCCESS])
|
|
1708
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1432
1709
|
|
|
1433
1710
|
def on_hci_le_read_buffer_size_command(
|
|
1434
1711
|
self, _command: hci.HCI_LE_Read_Buffer_Size_Command
|
|
@@ -1438,7 +1715,7 @@ class Controller:
|
|
|
1438
1715
|
'''
|
|
1439
1716
|
return struct.pack(
|
|
1440
1717
|
'<BHB',
|
|
1441
|
-
HCI_SUCCESS,
|
|
1718
|
+
hci.HCI_SUCCESS,
|
|
1442
1719
|
self.le_acl_data_packet_length,
|
|
1443
1720
|
self.total_num_le_acl_data_packets,
|
|
1444
1721
|
)
|
|
@@ -1451,7 +1728,7 @@ class Controller:
|
|
|
1451
1728
|
'''
|
|
1452
1729
|
return struct.pack(
|
|
1453
1730
|
'<BHBHB',
|
|
1454
|
-
HCI_SUCCESS,
|
|
1731
|
+
hci.HCI_SUCCESS,
|
|
1455
1732
|
self.le_acl_data_packet_length,
|
|
1456
1733
|
self.total_num_le_acl_data_packets,
|
|
1457
1734
|
self.iso_data_packet_length,
|
|
@@ -1465,16 +1742,16 @@ class Controller:
|
|
|
1465
1742
|
See Bluetooth spec Vol 4, Part E - 7.8.3 LE Read Local Supported Features
|
|
1466
1743
|
Command
|
|
1467
1744
|
'''
|
|
1468
|
-
return bytes([HCI_SUCCESS]) + self.le_features
|
|
1745
|
+
return bytes([hci.HCI_SUCCESS]) + self.le_features
|
|
1469
1746
|
|
|
1470
1747
|
def on_hci_le_set_random_address_command(
|
|
1471
1748
|
self, command: hci.HCI_LE_Set_Random_Address_Command
|
|
1472
1749
|
) -> Optional[bytes]:
|
|
1473
1750
|
'''
|
|
1474
|
-
See Bluetooth spec Vol 4, Part E - 7.8.4 LE Set Random Address Command
|
|
1751
|
+
See Bluetooth spec Vol 4, Part E - 7.8.4 LE Set Random hci.Address Command
|
|
1475
1752
|
'''
|
|
1476
1753
|
self.random_address = command.random_address
|
|
1477
|
-
return bytes([HCI_SUCCESS])
|
|
1754
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1478
1755
|
|
|
1479
1756
|
def on_hci_le_set_advertising_parameters_command(
|
|
1480
1757
|
self, command: hci.HCI_LE_Set_Advertising_Parameters_Command
|
|
@@ -1483,7 +1760,7 @@ class Controller:
|
|
|
1483
1760
|
See Bluetooth spec Vol 4, Part E - 7.8.5 LE Set Advertising Parameters Command
|
|
1484
1761
|
'''
|
|
1485
1762
|
self.advertising_parameters = command
|
|
1486
|
-
return bytes([HCI_SUCCESS])
|
|
1763
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1487
1764
|
|
|
1488
1765
|
def on_hci_le_read_advertising_physical_channel_tx_power_command(
|
|
1489
1766
|
self, _command: hci.HCI_LE_Read_Advertising_Physical_Channel_Tx_Power_Command
|
|
@@ -1492,7 +1769,7 @@ class Controller:
|
|
|
1492
1769
|
See Bluetooth spec Vol 4, Part E - 7.8.6 LE Read Advertising Physical Channel
|
|
1493
1770
|
Tx Power Command
|
|
1494
1771
|
'''
|
|
1495
|
-
return bytes([HCI_SUCCESS, self.advertising_channel_tx_power])
|
|
1772
|
+
return bytes([hci.HCI_SUCCESS, self.advertising_channel_tx_power])
|
|
1496
1773
|
|
|
1497
1774
|
def on_hci_le_set_advertising_data_command(
|
|
1498
1775
|
self, command: hci.HCI_LE_Set_Advertising_Data_Command
|
|
@@ -1501,7 +1778,7 @@ class Controller:
|
|
|
1501
1778
|
See Bluetooth spec Vol 4, Part E - 7.8.7 LE Set Advertising Data Command
|
|
1502
1779
|
'''
|
|
1503
1780
|
self.advertising_data = command.advertising_data
|
|
1504
|
-
return bytes([HCI_SUCCESS])
|
|
1781
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1505
1782
|
|
|
1506
1783
|
def on_hci_le_set_scan_response_data_command(
|
|
1507
1784
|
self, command: hci.HCI_LE_Set_Scan_Response_Data_Command
|
|
@@ -1510,7 +1787,7 @@ class Controller:
|
|
|
1510
1787
|
See Bluetooth spec Vol 4, Part E - 7.8.8 LE Set Scan Response Data Command
|
|
1511
1788
|
'''
|
|
1512
1789
|
self.le_scan_response_data = command.scan_response_data
|
|
1513
|
-
return bytes([HCI_SUCCESS])
|
|
1790
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1514
1791
|
|
|
1515
1792
|
def on_hci_le_set_advertising_enable_command(
|
|
1516
1793
|
self, command: hci.HCI_LE_Set_Advertising_Enable_Command
|
|
@@ -1523,7 +1800,7 @@ class Controller:
|
|
|
1523
1800
|
else:
|
|
1524
1801
|
self.stop_advertising()
|
|
1525
1802
|
|
|
1526
|
-
return bytes([HCI_SUCCESS])
|
|
1803
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1527
1804
|
|
|
1528
1805
|
def on_hci_le_set_scan_parameters_command(
|
|
1529
1806
|
self, command: hci.HCI_LE_Set_Scan_Parameters_Command
|
|
@@ -1532,14 +1809,14 @@ class Controller:
|
|
|
1532
1809
|
See Bluetooth spec Vol 4, Part E - 7.8.10 LE Set Scan Parameters Command
|
|
1533
1810
|
'''
|
|
1534
1811
|
if self.le_scan_enable:
|
|
1535
|
-
return bytes([HCI_COMMAND_DISALLOWED_ERROR])
|
|
1812
|
+
return bytes([hci.HCI_COMMAND_DISALLOWED_ERROR])
|
|
1536
1813
|
|
|
1537
1814
|
self.le_scan_type = command.le_scan_type
|
|
1538
1815
|
self.le_scan_interval = command.le_scan_interval
|
|
1539
1816
|
self.le_scan_window = command.le_scan_window
|
|
1540
1817
|
self.le_scan_own_address_type = hci.AddressType(command.own_address_type)
|
|
1541
1818
|
self.le_scanning_filter_policy = command.scanning_filter_policy
|
|
1542
|
-
return bytes([HCI_SUCCESS])
|
|
1819
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1543
1820
|
|
|
1544
1821
|
def on_hci_le_set_scan_enable_command(
|
|
1545
1822
|
self, command: hci.HCI_LE_Set_Scan_Enable_Command
|
|
@@ -1549,7 +1826,7 @@ class Controller:
|
|
|
1549
1826
|
'''
|
|
1550
1827
|
self.le_scan_enable = bool(command.le_scan_enable)
|
|
1551
1828
|
self.filter_duplicates = bool(command.filter_duplicates)
|
|
1552
|
-
return bytes([HCI_SUCCESS])
|
|
1829
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1553
1830
|
|
|
1554
1831
|
def on_hci_le_create_connection_command(
|
|
1555
1832
|
self, command: hci.HCI_LE_Create_Connection_Command
|
|
@@ -1566,8 +1843,8 @@ class Controller:
|
|
|
1566
1843
|
# Check that we don't already have a pending connection
|
|
1567
1844
|
if self.link.get_pending_connection():
|
|
1568
1845
|
self.send_hci_packet(
|
|
1569
|
-
HCI_Command_Status_Event(
|
|
1570
|
-
status=HCI_COMMAND_DISALLOWED_ERROR,
|
|
1846
|
+
hci.HCI_Command_Status_Event(
|
|
1847
|
+
status=hci.HCI_COMMAND_DISALLOWED_ERROR,
|
|
1571
1848
|
num_hci_command_packets=1,
|
|
1572
1849
|
command_opcode=command.op_code,
|
|
1573
1850
|
)
|
|
@@ -1579,8 +1856,8 @@ class Controller:
|
|
|
1579
1856
|
|
|
1580
1857
|
# Say that the connection is pending
|
|
1581
1858
|
self.send_hci_packet(
|
|
1582
|
-
HCI_Command_Status_Event(
|
|
1583
|
-
status=HCI_COMMAND_STATUS_PENDING,
|
|
1859
|
+
hci.HCI_Command_Status_Event(
|
|
1860
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
1584
1861
|
num_hci_command_packets=1,
|
|
1585
1862
|
command_opcode=command.op_code,
|
|
1586
1863
|
)
|
|
@@ -1593,7 +1870,7 @@ class Controller:
|
|
|
1593
1870
|
'''
|
|
1594
1871
|
See Bluetooth spec Vol 4, Part E - 7.8.13 LE Create Connection Cancel Command
|
|
1595
1872
|
'''
|
|
1596
|
-
return bytes([HCI_SUCCESS])
|
|
1873
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1597
1874
|
|
|
1598
1875
|
def on_hci_le_read_filter_accept_list_size_command(
|
|
1599
1876
|
self, _command: hci.HCI_LE_Read_Filter_Accept_List_Size_Command
|
|
@@ -1602,7 +1879,7 @@ class Controller:
|
|
|
1602
1879
|
See Bluetooth spec Vol 4, Part E - 7.8.14 LE Read Filter Accept List Size
|
|
1603
1880
|
Command
|
|
1604
1881
|
'''
|
|
1605
|
-
return bytes([HCI_SUCCESS, self.filter_accept_list_size])
|
|
1882
|
+
return bytes([hci.HCI_SUCCESS, self.filter_accept_list_size])
|
|
1606
1883
|
|
|
1607
1884
|
def on_hci_le_clear_filter_accept_list_command(
|
|
1608
1885
|
self, _command: hci.HCI_LE_Clear_Filter_Accept_List_Command
|
|
@@ -1610,7 +1887,7 @@ class Controller:
|
|
|
1610
1887
|
'''
|
|
1611
1888
|
See Bluetooth spec Vol 4, Part E - 7.8.15 LE Clear Filter Accept List Command
|
|
1612
1889
|
'''
|
|
1613
|
-
return bytes([HCI_SUCCESS])
|
|
1890
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1614
1891
|
|
|
1615
1892
|
def on_hci_le_add_device_to_filter_accept_list_command(
|
|
1616
1893
|
self, _command: hci.HCI_LE_Add_Device_To_Filter_Accept_List_Command
|
|
@@ -1619,7 +1896,7 @@ class Controller:
|
|
|
1619
1896
|
See Bluetooth spec Vol 4, Part E - 7.8.16 LE Add Device To Filter Accept List
|
|
1620
1897
|
Command
|
|
1621
1898
|
'''
|
|
1622
|
-
return bytes([HCI_SUCCESS])
|
|
1899
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1623
1900
|
|
|
1624
1901
|
def on_hci_le_remove_device_from_filter_accept_list_command(
|
|
1625
1902
|
self, _command: hci.HCI_LE_Remove_Device_From_Filter_Accept_List_Command
|
|
@@ -1628,7 +1905,16 @@ class Controller:
|
|
|
1628
1905
|
See Bluetooth spec Vol 4, Part E - 7.8.17 LE Remove Device From Filter Accept
|
|
1629
1906
|
List Command
|
|
1630
1907
|
'''
|
|
1631
|
-
return bytes([HCI_SUCCESS])
|
|
1908
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1909
|
+
|
|
1910
|
+
def on_hci_write_scan_enable_command(
|
|
1911
|
+
self, command: hci.HCI_Write_Scan_Enable_Command
|
|
1912
|
+
) -> Optional[bytes]:
|
|
1913
|
+
'''
|
|
1914
|
+
See Bluetooth spec Vol 4, Part E - 7.3.18 Write Scan Enable Command
|
|
1915
|
+
'''
|
|
1916
|
+
self.classic_scan_enable = command.scan_enable
|
|
1917
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1632
1918
|
|
|
1633
1919
|
def on_hci_le_read_remote_features_command(
|
|
1634
1920
|
self, command: hci.HCI_LE_Read_Remote_Features_Command
|
|
@@ -1641,8 +1927,8 @@ class Controller:
|
|
|
1641
1927
|
|
|
1642
1928
|
if not self.find_connection_by_handle(handle):
|
|
1643
1929
|
self.send_hci_packet(
|
|
1644
|
-
HCI_Command_Status_Event(
|
|
1645
|
-
status=HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR,
|
|
1930
|
+
hci.HCI_Command_Status_Event(
|
|
1931
|
+
status=hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR,
|
|
1646
1932
|
num_hci_command_packets=1,
|
|
1647
1933
|
command_opcode=command.op_code,
|
|
1648
1934
|
)
|
|
@@ -1651,8 +1937,8 @@ class Controller:
|
|
|
1651
1937
|
|
|
1652
1938
|
# First, say that the command is pending
|
|
1653
1939
|
self.send_hci_packet(
|
|
1654
|
-
HCI_Command_Status_Event(
|
|
1655
|
-
status=HCI_COMMAND_STATUS_PENDING,
|
|
1940
|
+
hci.HCI_Command_Status_Event(
|
|
1941
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
1656
1942
|
num_hci_command_packets=1,
|
|
1657
1943
|
command_opcode=command.op_code,
|
|
1658
1944
|
)
|
|
@@ -1660,8 +1946,8 @@ class Controller:
|
|
|
1660
1946
|
|
|
1661
1947
|
# Then send the remote features
|
|
1662
1948
|
self.send_hci_packet(
|
|
1663
|
-
HCI_LE_Read_Remote_Features_Complete_Event(
|
|
1664
|
-
status=HCI_SUCCESS,
|
|
1949
|
+
hci.HCI_LE_Read_Remote_Features_Complete_Event(
|
|
1950
|
+
status=hci.HCI_SUCCESS,
|
|
1665
1951
|
connection_handle=handle,
|
|
1666
1952
|
le_features=bytes.fromhex('dd40000000000000'),
|
|
1667
1953
|
)
|
|
@@ -1674,7 +1960,7 @@ class Controller:
|
|
|
1674
1960
|
'''
|
|
1675
1961
|
See Bluetooth spec Vol 4, Part E - 7.8.23 LE Rand Command
|
|
1676
1962
|
'''
|
|
1677
|
-
return bytes([HCI_SUCCESS]) + struct.pack('Q', random.randint(0, 1 << 64))
|
|
1963
|
+
return bytes([hci.HCI_SUCCESS]) + struct.pack('Q', random.randint(0, 1 << 64))
|
|
1678
1964
|
|
|
1679
1965
|
def on_hci_le_enable_encryption_command(
|
|
1680
1966
|
self, command: hci.HCI_LE_Enable_Encryption_Command
|
|
@@ -1692,7 +1978,7 @@ class Controller:
|
|
|
1692
1978
|
)
|
|
1693
1979
|
):
|
|
1694
1980
|
logger.warning('connection not found')
|
|
1695
|
-
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1981
|
+
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1696
1982
|
|
|
1697
1983
|
# Notify that the connection is now encrypted
|
|
1698
1984
|
self.link.on_connection_encrypted(
|
|
@@ -1704,8 +1990,8 @@ class Controller:
|
|
|
1704
1990
|
)
|
|
1705
1991
|
|
|
1706
1992
|
self.send_hci_packet(
|
|
1707
|
-
HCI_Command_Status_Event(
|
|
1708
|
-
status=HCI_COMMAND_STATUS_PENDING,
|
|
1993
|
+
hci.HCI_Command_Status_Event(
|
|
1994
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
1709
1995
|
num_hci_command_packets=1,
|
|
1710
1996
|
command_opcode=command.op_code,
|
|
1711
1997
|
)
|
|
@@ -1719,7 +2005,7 @@ class Controller:
|
|
|
1719
2005
|
'''
|
|
1720
2006
|
See Bluetooth spec Vol 4, Part E - 7.8.27 LE Read Supported States Command
|
|
1721
2007
|
'''
|
|
1722
|
-
return bytes([HCI_SUCCESS]) + self.le_states
|
|
2008
|
+
return bytes([hci.HCI_SUCCESS]) + self.le_states
|
|
1723
2009
|
|
|
1724
2010
|
def on_hci_le_read_suggested_default_data_length_command(
|
|
1725
2011
|
self, _command: hci.HCI_LE_Read_Suggested_Default_Data_Length_Command
|
|
@@ -1730,7 +2016,7 @@ class Controller:
|
|
|
1730
2016
|
'''
|
|
1731
2017
|
return struct.pack(
|
|
1732
2018
|
'<BHH',
|
|
1733
|
-
HCI_SUCCESS,
|
|
2019
|
+
hci.HCI_SUCCESS,
|
|
1734
2020
|
self.suggested_max_tx_octets,
|
|
1735
2021
|
self.suggested_max_tx_time,
|
|
1736
2022
|
)
|
|
@@ -1745,7 +2031,7 @@ class Controller:
|
|
|
1745
2031
|
self.suggested_max_tx_octets, self.suggested_max_tx_time = struct.unpack(
|
|
1746
2032
|
'<HH', command.parameters[:4]
|
|
1747
2033
|
)
|
|
1748
|
-
return bytes([HCI_SUCCESS])
|
|
2034
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1749
2035
|
|
|
1750
2036
|
def on_hci_le_read_local_p_256_public_key_command(
|
|
1751
2037
|
self, _command: hci.HCI_LE_Read_Local_P_256_Public_Key_Command
|
|
@@ -1753,8 +2039,8 @@ class Controller:
|
|
|
1753
2039
|
'''
|
|
1754
2040
|
See Bluetooth spec Vol 4, Part E - 7.8.36 LE Read P-256 Public Key Command
|
|
1755
2041
|
'''
|
|
1756
|
-
# TODO create key and send HCI_LE_Read_Local_P-256_Public_Key_Complete event
|
|
1757
|
-
return bytes([HCI_SUCCESS])
|
|
2042
|
+
# TODO create key and send hci.HCI_LE_Read_Local_P-256_Public_Key_Complete event
|
|
2043
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1758
2044
|
|
|
1759
2045
|
def on_hci_le_add_device_to_resolving_list_command(
|
|
1760
2046
|
self, _command: hci.HCI_LE_Add_Device_To_Resolving_List_Command
|
|
@@ -1763,7 +2049,7 @@ class Controller:
|
|
|
1763
2049
|
See Bluetooth spec Vol 4, Part E - 7.8.38 LE Add Device To Resolving List
|
|
1764
2050
|
Command
|
|
1765
2051
|
'''
|
|
1766
|
-
return bytes([HCI_SUCCESS])
|
|
2052
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1767
2053
|
|
|
1768
2054
|
def on_hci_le_clear_resolving_list_command(
|
|
1769
2055
|
self, _command: hci.HCI_LE_Clear_Resolving_List_Command
|
|
@@ -1771,7 +2057,7 @@ class Controller:
|
|
|
1771
2057
|
'''
|
|
1772
2058
|
See Bluetooth spec Vol 4, Part E - 7.8.40 LE Clear Resolving List Command
|
|
1773
2059
|
'''
|
|
1774
|
-
return bytes([HCI_SUCCESS])
|
|
2060
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1775
2061
|
|
|
1776
2062
|
def on_hci_le_read_resolving_list_size_command(
|
|
1777
2063
|
self, _command: hci.HCI_LE_Read_Resolving_List_Size_Command
|
|
@@ -1779,33 +2065,33 @@ class Controller:
|
|
|
1779
2065
|
'''
|
|
1780
2066
|
See Bluetooth spec Vol 4, Part E - 7.8.41 LE Read Resolving List Size Command
|
|
1781
2067
|
'''
|
|
1782
|
-
return bytes([HCI_SUCCESS, self.resolving_list_size])
|
|
2068
|
+
return bytes([hci.HCI_SUCCESS, self.resolving_list_size])
|
|
1783
2069
|
|
|
1784
2070
|
def on_hci_le_set_address_resolution_enable_command(
|
|
1785
2071
|
self, command: hci.HCI_LE_Set_Address_Resolution_Enable_Command
|
|
1786
2072
|
) -> Optional[bytes]:
|
|
1787
2073
|
'''
|
|
1788
|
-
See Bluetooth spec Vol 4, Part E - 7.8.44 LE Set Address Resolution Enable
|
|
2074
|
+
See Bluetooth spec Vol 4, Part E - 7.8.44 LE Set hci.Address Resolution Enable
|
|
1789
2075
|
Command
|
|
1790
2076
|
'''
|
|
1791
|
-
ret = HCI_SUCCESS
|
|
2077
|
+
ret = hci.HCI_SUCCESS
|
|
1792
2078
|
if command.address_resolution_enable == 1:
|
|
1793
2079
|
self.le_address_resolution = True
|
|
1794
2080
|
elif command.address_resolution_enable == 0:
|
|
1795
2081
|
self.le_address_resolution = False
|
|
1796
2082
|
else:
|
|
1797
|
-
ret = HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR
|
|
2083
|
+
ret = hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR
|
|
1798
2084
|
return bytes([ret])
|
|
1799
2085
|
|
|
1800
2086
|
def on_hci_le_set_resolvable_private_address_timeout_command(
|
|
1801
2087
|
self, command: hci.HCI_LE_Set_Resolvable_Private_Address_Timeout_Command
|
|
1802
2088
|
) -> Optional[bytes]:
|
|
1803
2089
|
'''
|
|
1804
|
-
See Bluetooth spec Vol 4, Part E - 7.8.45 LE Set Resolvable Private Address
|
|
2090
|
+
See Bluetooth spec Vol 4, Part E - 7.8.45 LE Set Resolvable Private hci.Address
|
|
1805
2091
|
Timeout Command
|
|
1806
2092
|
'''
|
|
1807
2093
|
self.le_rpa_timeout = command.rpa_timeout
|
|
1808
|
-
return bytes([HCI_SUCCESS])
|
|
2094
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1809
2095
|
|
|
1810
2096
|
def on_hci_le_read_maximum_data_length_command(
|
|
1811
2097
|
self, _command: hci.HCI_LE_Read_Maximum_Data_Length_Command
|
|
@@ -1815,7 +2101,7 @@ class Controller:
|
|
|
1815
2101
|
'''
|
|
1816
2102
|
return struct.pack(
|
|
1817
2103
|
'<BHHHH',
|
|
1818
|
-
HCI_SUCCESS,
|
|
2104
|
+
hci.HCI_SUCCESS,
|
|
1819
2105
|
self.supported_max_tx_octets,
|
|
1820
2106
|
self.supported_max_tx_time,
|
|
1821
2107
|
self.supported_max_rx_octets,
|
|
@@ -1830,10 +2116,10 @@ class Controller:
|
|
|
1830
2116
|
'''
|
|
1831
2117
|
return struct.pack(
|
|
1832
2118
|
'<BHBB',
|
|
1833
|
-
HCI_SUCCESS,
|
|
2119
|
+
hci.HCI_SUCCESS,
|
|
1834
2120
|
command.connection_handle,
|
|
1835
|
-
HCI_LE_1M_PHY,
|
|
1836
|
-
HCI_LE_1M_PHY,
|
|
2121
|
+
hci.HCI_LE_1M_PHY,
|
|
2122
|
+
hci.HCI_LE_1M_PHY,
|
|
1837
2123
|
)
|
|
1838
2124
|
|
|
1839
2125
|
def on_hci_le_set_default_phy_command(
|
|
@@ -1845,16 +2131,16 @@ class Controller:
|
|
|
1845
2131
|
self.default_phy['all_phys'] = command.all_phys
|
|
1846
2132
|
self.default_phy['tx_phys'] = command.tx_phys
|
|
1847
2133
|
self.default_phy['rx_phys'] = command.rx_phys
|
|
1848
|
-
return bytes([HCI_SUCCESS])
|
|
2134
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1849
2135
|
|
|
1850
2136
|
def on_hci_le_set_advertising_set_random_address_command(
|
|
1851
2137
|
self, _command: hci.HCI_LE_Set_Advertising_Set_Random_Address_Command
|
|
1852
2138
|
) -> Optional[bytes]:
|
|
1853
2139
|
'''
|
|
1854
|
-
See Bluetooth spec Vol 4, Part E - 7.8.52 LE Set Advertising Set Random Address
|
|
2140
|
+
See Bluetooth spec Vol 4, Part E - 7.8.52 LE Set Advertising Set Random hci.Address
|
|
1855
2141
|
Command
|
|
1856
2142
|
'''
|
|
1857
|
-
return bytes([HCI_SUCCESS])
|
|
2143
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1858
2144
|
|
|
1859
2145
|
def on_hci_le_set_extended_advertising_parameters_command(
|
|
1860
2146
|
self, _command: hci.HCI_LE_Set_Extended_Advertising_Parameters_Command
|
|
@@ -1863,7 +2149,7 @@ class Controller:
|
|
|
1863
2149
|
See Bluetooth spec Vol 4, Part E - 7.8.53 LE Set Extended Advertising Parameters
|
|
1864
2150
|
Command
|
|
1865
2151
|
'''
|
|
1866
|
-
return bytes([HCI_SUCCESS, 0])
|
|
2152
|
+
return bytes([hci.HCI_SUCCESS, 0])
|
|
1867
2153
|
|
|
1868
2154
|
def on_hci_le_set_extended_advertising_data_command(
|
|
1869
2155
|
self, _command: hci.HCI_LE_Set_Extended_Advertising_Data_Command
|
|
@@ -1872,7 +2158,7 @@ class Controller:
|
|
|
1872
2158
|
See Bluetooth spec Vol 4, Part E - 7.8.54 LE Set Extended Advertising Data
|
|
1873
2159
|
Command
|
|
1874
2160
|
'''
|
|
1875
|
-
return bytes([HCI_SUCCESS])
|
|
2161
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1876
2162
|
|
|
1877
2163
|
def on_hci_le_set_extended_scan_response_data_command(
|
|
1878
2164
|
self, _command: hci.HCI_LE_Set_Extended_Scan_Response_Data_Command
|
|
@@ -1881,7 +2167,7 @@ class Controller:
|
|
|
1881
2167
|
See Bluetooth spec Vol 4, Part E - 7.8.55 LE Set Extended Scan Response Data
|
|
1882
2168
|
Command
|
|
1883
2169
|
'''
|
|
1884
|
-
return bytes([HCI_SUCCESS])
|
|
2170
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1885
2171
|
|
|
1886
2172
|
def on_hci_le_set_extended_advertising_enable_command(
|
|
1887
2173
|
self, _command: hci.HCI_LE_Set_Extended_Advertising_Enable_Command
|
|
@@ -1890,7 +2176,7 @@ class Controller:
|
|
|
1890
2176
|
See Bluetooth spec Vol 4, Part E - 7.8.56 LE Set Extended Advertising Enable
|
|
1891
2177
|
Command
|
|
1892
2178
|
'''
|
|
1893
|
-
return bytes([HCI_SUCCESS])
|
|
2179
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1894
2180
|
|
|
1895
2181
|
def on_hci_le_read_maximum_advertising_data_length_command(
|
|
1896
2182
|
self, _command: hci.HCI_LE_Read_Maximum_Advertising_Data_Length_Command
|
|
@@ -1899,7 +2185,7 @@ class Controller:
|
|
|
1899
2185
|
See Bluetooth spec Vol 4, Part E - 7.8.57 LE Read Maximum Advertising Data
|
|
1900
2186
|
Length Command
|
|
1901
2187
|
'''
|
|
1902
|
-
return struct.pack('<BH', HCI_SUCCESS, 0x0672)
|
|
2188
|
+
return struct.pack('<BH', hci.HCI_SUCCESS, 0x0672)
|
|
1903
2189
|
|
|
1904
2190
|
def on_hci_le_read_number_of_supported_advertising_sets_command(
|
|
1905
2191
|
self, _command: hci.HCI_LE_Read_Number_Of_Supported_Advertising_Sets_Command
|
|
@@ -1908,7 +2194,7 @@ class Controller:
|
|
|
1908
2194
|
See Bluetooth spec Vol 4, Part E - 7.8.58 LE Read Number of Supported
|
|
1909
2195
|
Advertising Set Command
|
|
1910
2196
|
'''
|
|
1911
|
-
return struct.pack('<BB', HCI_SUCCESS, 0xF0)
|
|
2197
|
+
return struct.pack('<BB', hci.HCI_SUCCESS, 0xF0)
|
|
1912
2198
|
|
|
1913
2199
|
def on_hci_le_set_periodic_advertising_parameters_command(
|
|
1914
2200
|
self, _command: hci.HCI_LE_Set_Periodic_Advertising_Parameters_Command
|
|
@@ -1917,7 +2203,7 @@ class Controller:
|
|
|
1917
2203
|
See Bluetooth spec Vol 4, Part E - 7.8.61 LE Set Periodic Advertising Parameters
|
|
1918
2204
|
Command
|
|
1919
2205
|
'''
|
|
1920
|
-
return bytes([HCI_SUCCESS])
|
|
2206
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1921
2207
|
|
|
1922
2208
|
def on_hci_le_set_periodic_advertising_data_command(
|
|
1923
2209
|
self, _command: hci.HCI_LE_Set_Periodic_Advertising_Data_Command
|
|
@@ -1926,7 +2212,7 @@ class Controller:
|
|
|
1926
2212
|
See Bluetooth spec Vol 4, Part E - 7.8.62 LE Set Periodic Advertising Data
|
|
1927
2213
|
Command
|
|
1928
2214
|
'''
|
|
1929
|
-
return bytes([HCI_SUCCESS])
|
|
2215
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1930
2216
|
|
|
1931
2217
|
def on_hci_le_set_periodic_advertising_enable_command(
|
|
1932
2218
|
self, _command: hci.HCI_LE_Set_Periodic_Advertising_Enable_Command
|
|
@@ -1935,7 +2221,7 @@ class Controller:
|
|
|
1935
2221
|
See Bluetooth spec Vol 4, Part E - 7.8.63 LE Set Periodic Advertising Enable
|
|
1936
2222
|
Command
|
|
1937
2223
|
'''
|
|
1938
|
-
return bytes([HCI_SUCCESS])
|
|
2224
|
+
return bytes([hci.HCI_SUCCESS])
|
|
1939
2225
|
|
|
1940
2226
|
def on_hci_le_read_transmit_power_command(
|
|
1941
2227
|
self, _command: hci.HCI_LE_Read_Transmit_Power_Command
|
|
@@ -1943,7 +2229,7 @@ class Controller:
|
|
|
1943
2229
|
'''
|
|
1944
2230
|
See Bluetooth spec Vol 4, Part E - 7.8.74 LE Read Transmit Power Command
|
|
1945
2231
|
'''
|
|
1946
|
-
return struct.pack('<BBB', HCI_SUCCESS, 0, 0)
|
|
2232
|
+
return struct.pack('<BBB', hci.HCI_SUCCESS, 0, 0)
|
|
1947
2233
|
|
|
1948
2234
|
def on_hci_le_set_cig_parameters_command(
|
|
1949
2235
|
self, command: hci.HCI_LE_Set_CIG_Parameters_Command
|
|
@@ -1968,7 +2254,7 @@ class Controller:
|
|
|
1968
2254
|
handle=handle,
|
|
1969
2255
|
)
|
|
1970
2256
|
return struct.pack(
|
|
1971
|
-
'<BBB', HCI_SUCCESS, command.cig_id, len(handles)
|
|
2257
|
+
'<BBB', hci.HCI_SUCCESS, command.cig_id, len(handles)
|
|
1972
2258
|
) + b''.join([struct.pack('<H', handle) for handle in handles])
|
|
1973
2259
|
|
|
1974
2260
|
def on_hci_le_create_cis_command(
|
|
@@ -1985,11 +2271,11 @@ class Controller:
|
|
|
1985
2271
|
):
|
|
1986
2272
|
if not (connection := self.find_connection_by_handle(acl_handle)):
|
|
1987
2273
|
logger.error(f'Cannot find connection with handle={acl_handle}')
|
|
1988
|
-
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
2274
|
+
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1989
2275
|
|
|
1990
2276
|
if not (cis_link := self.central_cis_links.get(cis_handle)):
|
|
1991
2277
|
logger.error(f'Cannot find CIS with handle={cis_handle}')
|
|
1992
|
-
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
2278
|
+
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1993
2279
|
|
|
1994
2280
|
cis_link.acl_connection = connection
|
|
1995
2281
|
|
|
@@ -2001,8 +2287,8 @@ class Controller:
|
|
|
2001
2287
|
)
|
|
2002
2288
|
|
|
2003
2289
|
self.send_hci_packet(
|
|
2004
|
-
HCI_Command_Status_Event(
|
|
2005
|
-
status=HCI_COMMAND_STATUS_PENDING,
|
|
2290
|
+
hci.HCI_Command_Status_Event(
|
|
2291
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
2006
2292
|
num_hci_command_packets=1,
|
|
2007
2293
|
command_opcode=command.op_code,
|
|
2008
2294
|
)
|
|
@@ -2016,13 +2302,13 @@ class Controller:
|
|
|
2016
2302
|
See Bluetooth spec Vol 4, Part E - 7.8.100 LE Remove CIG Command
|
|
2017
2303
|
'''
|
|
2018
2304
|
|
|
2019
|
-
status = HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR
|
|
2305
|
+
status = hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR
|
|
2020
2306
|
|
|
2021
2307
|
cis_links = list(self.central_cis_links.items())
|
|
2022
2308
|
for cis_handle, cis_link in cis_links:
|
|
2023
2309
|
if cis_link.cig_id == command.cig_id:
|
|
2024
2310
|
self.central_cis_links.pop(cis_handle)
|
|
2025
|
-
status = HCI_SUCCESS
|
|
2311
|
+
status = hci.HCI_SUCCESS
|
|
2026
2312
|
|
|
2027
2313
|
return struct.pack('<BH', status, command.cig_id)
|
|
2028
2314
|
|
|
@@ -2039,7 +2325,7 @@ class Controller:
|
|
|
2039
2325
|
pending_cis_link := self.peripheral_cis_links.get(command.connection_handle)
|
|
2040
2326
|
):
|
|
2041
2327
|
logger.error(f'Cannot find CIS with handle={command.connection_handle}')
|
|
2042
|
-
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
2328
|
+
return bytes([hci.HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
2043
2329
|
|
|
2044
2330
|
assert pending_cis_link.acl_connection
|
|
2045
2331
|
self.link.accept_cis(
|
|
@@ -2050,8 +2336,8 @@ class Controller:
|
|
|
2050
2336
|
)
|
|
2051
2337
|
|
|
2052
2338
|
self.send_hci_packet(
|
|
2053
|
-
HCI_Command_Status_Event(
|
|
2054
|
-
status=HCI_COMMAND_STATUS_PENDING,
|
|
2339
|
+
hci.HCI_Command_Status_Event(
|
|
2340
|
+
status=hci.HCI_COMMAND_STATUS_PENDING,
|
|
2055
2341
|
num_hci_command_packets=1,
|
|
2056
2342
|
command_opcode=command.op_code,
|
|
2057
2343
|
)
|
|
@@ -2067,17 +2353,17 @@ class Controller:
|
|
|
2067
2353
|
if not (iso_link := self.find_iso_link_by_handle(command.connection_handle)):
|
|
2068
2354
|
return struct.pack(
|
|
2069
2355
|
'<BH',
|
|
2070
|
-
HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
2356
|
+
hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
2071
2357
|
command.connection_handle,
|
|
2072
2358
|
)
|
|
2073
2359
|
if command.data_path_direction in iso_link.data_paths:
|
|
2074
2360
|
return struct.pack(
|
|
2075
2361
|
'<BH',
|
|
2076
|
-
HCI_COMMAND_DISALLOWED_ERROR,
|
|
2362
|
+
hci.HCI_COMMAND_DISALLOWED_ERROR,
|
|
2077
2363
|
command.connection_handle,
|
|
2078
2364
|
)
|
|
2079
2365
|
iso_link.data_paths.add(command.data_path_direction)
|
|
2080
|
-
return struct.pack('<BH', HCI_SUCCESS, command.connection_handle)
|
|
2366
|
+
return struct.pack('<BH', hci.HCI_SUCCESS, command.connection_handle)
|
|
2081
2367
|
|
|
2082
2368
|
def on_hci_le_remove_iso_data_path_command(
|
|
2083
2369
|
self, command: hci.HCI_LE_Remove_ISO_Data_Path_Command
|
|
@@ -2088,7 +2374,7 @@ class Controller:
|
|
|
2088
2374
|
if not (iso_link := self.find_iso_link_by_handle(command.connection_handle)):
|
|
2089
2375
|
return struct.pack(
|
|
2090
2376
|
'<BH',
|
|
2091
|
-
HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
2377
|
+
hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
2092
2378
|
command.connection_handle,
|
|
2093
2379
|
)
|
|
2094
2380
|
data_paths: set[int] = set(
|
|
@@ -2099,11 +2385,11 @@ class Controller:
|
|
|
2099
2385
|
if not data_paths.issubset(iso_link.data_paths):
|
|
2100
2386
|
return struct.pack(
|
|
2101
2387
|
'<BH',
|
|
2102
|
-
HCI_COMMAND_DISALLOWED_ERROR,
|
|
2388
|
+
hci.HCI_COMMAND_DISALLOWED_ERROR,
|
|
2103
2389
|
command.connection_handle,
|
|
2104
2390
|
)
|
|
2105
2391
|
iso_link.data_paths.difference_update(data_paths)
|
|
2106
|
-
return struct.pack('<BH', HCI_SUCCESS, command.connection_handle)
|
|
2392
|
+
return struct.pack('<BH', hci.HCI_SUCCESS, command.connection_handle)
|
|
2107
2393
|
|
|
2108
2394
|
def on_hci_le_set_host_feature_command(
|
|
2109
2395
|
self, _command: hci.HCI_LE_Set_Host_Feature_Command
|
|
@@ -2111,4 +2397,4 @@ class Controller:
|
|
|
2111
2397
|
'''
|
|
2112
2398
|
See Bluetooth spec Vol 4, Part E - 7.8.115 LE Set Host Feature command
|
|
2113
2399
|
'''
|
|
2114
|
-
return bytes([HCI_SUCCESS])
|
|
2400
|
+
return bytes([hci.HCI_SUCCESS])
|