bumble 0.0.212__py3-none-any.whl → 0.0.214__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 +6 -0
- bumble/apps/README.md +0 -3
- bumble/apps/auracast.py +14 -11
- bumble/apps/bench.py +482 -37
- bumble/apps/console.py +3 -3
- bumble/apps/controller_info.py +44 -12
- bumble/apps/controller_loopback.py +7 -7
- bumble/apps/controllers.py +4 -5
- bumble/apps/device_info.py +4 -5
- bumble/apps/gatt_dump.py +5 -5
- bumble/apps/gg_bridge.py +5 -5
- bumble/apps/hci_bridge.py +5 -4
- bumble/apps/l2cap_bridge.py +5 -5
- bumble/apps/lea_unicast/app.py +8 -3
- bumble/apps/pair.py +19 -11
- bumble/apps/pandora_server.py +2 -2
- bumble/apps/player/player.py +2 -3
- bumble/apps/rfcomm_bridge.py +3 -4
- bumble/apps/scan.py +4 -5
- bumble/apps/show.py +6 -4
- bumble/apps/speaker/speaker.html +1 -0
- bumble/apps/speaker/speaker.js +113 -62
- bumble/apps/speaker/speaker.py +123 -19
- bumble/apps/unbond.py +2 -3
- bumble/apps/usb_probe.py +2 -3
- bumble/at.py +4 -4
- bumble/att.py +2 -6
- bumble/avc.py +7 -7
- bumble/avctp.py +3 -3
- bumble/avdtp.py +16 -20
- bumble/avrcp.py +42 -54
- bumble/colors.py +2 -2
- bumble/controller.py +174 -45
- bumble/device.py +398 -182
- bumble/drivers/__init__.py +2 -2
- bumble/drivers/common.py +0 -2
- bumble/drivers/intel.py +37 -40
- bumble/drivers/rtk.py +28 -35
- bumble/gatt.py +4 -4
- bumble/gatt_adapters.py +4 -5
- bumble/gatt_client.py +26 -31
- bumble/gatt_server.py +7 -11
- bumble/hci.py +2648 -2909
- bumble/helpers.py +4 -5
- bumble/hfp.py +32 -37
- bumble/host.py +104 -35
- bumble/keys.py +5 -5
- bumble/l2cap.py +312 -409
- bumble/link.py +16 -280
- bumble/logging.py +65 -0
- bumble/pairing.py +23 -20
- bumble/pandora/__init__.py +2 -2
- bumble/pandora/config.py +2 -2
- bumble/pandora/device.py +6 -6
- bumble/pandora/host.py +27 -28
- bumble/pandora/l2cap.py +2 -2
- bumble/pandora/security.py +6 -6
- bumble/pandora/utils.py +3 -3
- bumble/profiles/ams.py +404 -0
- bumble/profiles/ascs.py +142 -131
- bumble/profiles/asha.py +2 -2
- bumble/profiles/bap.py +3 -4
- bumble/profiles/csip.py +2 -2
- bumble/profiles/device_information_service.py +2 -2
- bumble/profiles/gap.py +2 -2
- bumble/profiles/hap.py +34 -33
- bumble/profiles/le_audio.py +4 -4
- bumble/profiles/mcp.py +4 -4
- bumble/profiles/vcs.py +3 -5
- bumble/rfcomm.py +10 -10
- bumble/rtp.py +1 -2
- bumble/sdp.py +2 -2
- bumble/smp.py +62 -63
- bumble/tools/intel_util.py +3 -2
- bumble/tools/rtk_util.py +6 -5
- bumble/transport/__init__.py +2 -16
- bumble/transport/android_netsim.py +5 -5
- bumble/transport/common.py +4 -4
- bumble/transport/pyusb.py +2 -2
- bumble/utils.py +2 -5
- bumble/vendor/android/hci.py +118 -200
- bumble/vendor/zephyr/hci.py +32 -27
- {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/METADATA +4 -3
- {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/RECORD +89 -90
- {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/WHEEL +1 -1
- {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/entry_points.txt +0 -1
- bumble/apps/link_relay/__init__.py +0 -0
- bumble/apps/link_relay/link_relay.py +0 -289
- bumble/apps/link_relay/logging.yml +0 -21
- {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/licenses/LICENSE +0 -0
- {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/top_level.txt +0 -0
bumble/controller.py
CHANGED
|
@@ -27,7 +27,7 @@ from bumble.colors import color
|
|
|
27
27
|
from bumble.core import (
|
|
28
28
|
PhysicalTransport,
|
|
29
29
|
)
|
|
30
|
-
|
|
30
|
+
from bumble import hci
|
|
31
31
|
from bumble.hci import (
|
|
32
32
|
HCI_ACL_DATA_PACKET,
|
|
33
33
|
HCI_COMMAND_DISALLOWED_ERROR,
|
|
@@ -63,7 +63,7 @@ from bumble.hci import (
|
|
|
63
63
|
HCI_Packet,
|
|
64
64
|
HCI_Role_Change_Event,
|
|
65
65
|
)
|
|
66
|
-
from typing import Optional, Union,
|
|
66
|
+
from typing import Optional, Union, Any, TYPE_CHECKING
|
|
67
67
|
|
|
68
68
|
if TYPE_CHECKING:
|
|
69
69
|
from bumble.link import LocalLink
|
|
@@ -108,7 +108,9 @@ class Connection:
|
|
|
108
108
|
def on_hci_acl_data_packet(self, packet):
|
|
109
109
|
self.assembler.feed_packet(packet)
|
|
110
110
|
self.controller.send_hci_packet(
|
|
111
|
-
HCI_Number_Of_Completed_Packets_Event(
|
|
111
|
+
HCI_Number_Of_Completed_Packets_Event(
|
|
112
|
+
connection_handles=[self.handle], num_completed_packets=[1]
|
|
113
|
+
)
|
|
112
114
|
)
|
|
113
115
|
|
|
114
116
|
def on_acl_pdu(self, data):
|
|
@@ -132,17 +134,17 @@ class Controller:
|
|
|
132
134
|
self.hci_sink = None
|
|
133
135
|
self.link = link
|
|
134
136
|
|
|
135
|
-
self.central_connections:
|
|
137
|
+
self.central_connections: dict[Address, Connection] = (
|
|
136
138
|
{}
|
|
137
139
|
) # Connections where this controller is the central
|
|
138
|
-
self.peripheral_connections:
|
|
140
|
+
self.peripheral_connections: dict[Address, Connection] = (
|
|
139
141
|
{}
|
|
140
142
|
) # Connections where this controller is the peripheral
|
|
141
|
-
self.classic_connections:
|
|
143
|
+
self.classic_connections: dict[Address, Connection] = (
|
|
142
144
|
{}
|
|
143
145
|
) # Connections in BR/EDR
|
|
144
|
-
self.central_cis_links:
|
|
145
|
-
self.peripheral_cis_links:
|
|
146
|
+
self.central_cis_links: dict[int, CisLink] = {} # CIS links by handle
|
|
147
|
+
self.peripheral_cis_links: dict[int, CisLink] = {} # CIS links by handle
|
|
146
148
|
|
|
147
149
|
self.hci_version = HCI_VERSION_BLUETOOTH_CORE_5_0
|
|
148
150
|
self.hci_revision = 0
|
|
@@ -368,6 +370,12 @@ class Controller:
|
|
|
368
370
|
return connection
|
|
369
371
|
return None
|
|
370
372
|
|
|
373
|
+
def find_peripheral_connection_by_handle(self, handle):
|
|
374
|
+
for connection in self.peripheral_connections.values():
|
|
375
|
+
if connection.handle == handle:
|
|
376
|
+
return connection
|
|
377
|
+
return None
|
|
378
|
+
|
|
371
379
|
def find_classic_connection_by_handle(self, handle):
|
|
372
380
|
for connection in self.classic_connections.values():
|
|
373
381
|
if connection.handle == handle:
|
|
@@ -392,7 +400,7 @@ class Controller:
|
|
|
392
400
|
peer_address=peer_address,
|
|
393
401
|
link=self.link,
|
|
394
402
|
transport=PhysicalTransport.LE,
|
|
395
|
-
link_type=HCI_Connection_Complete_Event.
|
|
403
|
+
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
396
404
|
)
|
|
397
405
|
self.peripheral_connections[peer_address] = connection
|
|
398
406
|
logger.debug(f'New PERIPHERAL connection handle: 0x{connection_handle:04X}')
|
|
@@ -412,7 +420,7 @@ class Controller:
|
|
|
412
420
|
)
|
|
413
421
|
)
|
|
414
422
|
|
|
415
|
-
def
|
|
423
|
+
def on_link_disconnected(self, peer_address, reason):
|
|
416
424
|
'''
|
|
417
425
|
Called when an active disconnection occurs from a peer
|
|
418
426
|
'''
|
|
@@ -429,6 +437,17 @@ class Controller:
|
|
|
429
437
|
|
|
430
438
|
# Remove the connection
|
|
431
439
|
del self.peripheral_connections[peer_address]
|
|
440
|
+
elif connection := self.central_connections.get(peer_address):
|
|
441
|
+
self.send_hci_packet(
|
|
442
|
+
HCI_Disconnection_Complete_Event(
|
|
443
|
+
status=HCI_SUCCESS,
|
|
444
|
+
connection_handle=connection.handle,
|
|
445
|
+
reason=reason,
|
|
446
|
+
)
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
# Remove the connection
|
|
450
|
+
del self.central_connections[peer_address]
|
|
432
451
|
else:
|
|
433
452
|
logger.warning(f'!!! No peripheral connection found for {peer_address}')
|
|
434
453
|
|
|
@@ -452,7 +471,7 @@ class Controller:
|
|
|
452
471
|
peer_address=peer_address,
|
|
453
472
|
link=self.link,
|
|
454
473
|
transport=PhysicalTransport.LE,
|
|
455
|
-
link_type=HCI_Connection_Complete_Event.
|
|
474
|
+
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
456
475
|
)
|
|
457
476
|
self.central_connections[peer_address] = connection
|
|
458
477
|
logger.debug(
|
|
@@ -477,7 +496,7 @@ class Controller:
|
|
|
477
496
|
)
|
|
478
497
|
)
|
|
479
498
|
|
|
480
|
-
def
|
|
499
|
+
def on_link_disconnection_complete(self, disconnection_command, status):
|
|
481
500
|
'''
|
|
482
501
|
Called when a disconnection has been completed
|
|
483
502
|
'''
|
|
@@ -497,26 +516,11 @@ class Controller:
|
|
|
497
516
|
):
|
|
498
517
|
logger.debug(f'CENTRAL Connection removed: {connection}')
|
|
499
518
|
del self.central_connections[connection.peer_address]
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
# Send a disconnection complete event
|
|
507
|
-
if connection := self.central_connections.get(peer_address):
|
|
508
|
-
self.send_hci_packet(
|
|
509
|
-
HCI_Disconnection_Complete_Event(
|
|
510
|
-
status=HCI_SUCCESS,
|
|
511
|
-
connection_handle=connection.handle,
|
|
512
|
-
reason=HCI_CONNECTION_TIMEOUT_ERROR,
|
|
513
|
-
)
|
|
514
|
-
)
|
|
515
|
-
|
|
516
|
-
# Remove the connection
|
|
517
|
-
del self.central_connections[peer_address]
|
|
518
|
-
else:
|
|
519
|
-
logger.warning(f'!!! No central connection found for {peer_address}')
|
|
519
|
+
elif connection := self.find_peripheral_connection_by_handle(
|
|
520
|
+
disconnection_command.connection_handle
|
|
521
|
+
):
|
|
522
|
+
logger.debug(f'PERIPHERAL Connection removed: {connection}')
|
|
523
|
+
del self.peripheral_connections[connection.peer_address]
|
|
520
524
|
|
|
521
525
|
def on_link_encrypted(self, peer_address, _rand, _ediv, _ltk):
|
|
522
526
|
# For now, just setup the encryption without asking the host
|
|
@@ -542,15 +546,14 @@ class Controller:
|
|
|
542
546
|
acl_packet = HCI_AclDataPacket(connection.handle, 2, 0, len(data), data)
|
|
543
547
|
self.send_hci_packet(acl_packet)
|
|
544
548
|
|
|
545
|
-
def on_link_advertising_data(self, sender_address, data):
|
|
549
|
+
def on_link_advertising_data(self, sender_address: Address, data: bytes):
|
|
546
550
|
# Ignore if we're not scanning
|
|
547
551
|
if self.le_scan_enable == 0:
|
|
548
552
|
return
|
|
549
553
|
|
|
550
554
|
# Send a scan report
|
|
551
555
|
report = HCI_LE_Advertising_Report_Event.Report(
|
|
552
|
-
HCI_LE_Advertising_Report_Event.
|
|
553
|
-
event_type=HCI_LE_Advertising_Report_Event.ADV_IND,
|
|
556
|
+
event_type=HCI_LE_Advertising_Report_Event.EventType.ADV_IND,
|
|
554
557
|
address_type=sender_address.address_type,
|
|
555
558
|
address=sender_address,
|
|
556
559
|
data=data,
|
|
@@ -560,8 +563,7 @@ class Controller:
|
|
|
560
563
|
|
|
561
564
|
# Simulate a scan response
|
|
562
565
|
report = HCI_LE_Advertising_Report_Event.Report(
|
|
563
|
-
HCI_LE_Advertising_Report_Event.
|
|
564
|
-
event_type=HCI_LE_Advertising_Report_Event.SCAN_RSP,
|
|
566
|
+
event_type=HCI_LE_Advertising_Report_Event.EventType.SCAN_RSP,
|
|
565
567
|
address_type=sender_address.address_type,
|
|
566
568
|
address=sender_address,
|
|
567
569
|
data=data,
|
|
@@ -618,8 +620,8 @@ class Controller:
|
|
|
618
620
|
cis_sync_delay=0,
|
|
619
621
|
transport_latency_c_to_p=0,
|
|
620
622
|
transport_latency_p_to_c=0,
|
|
621
|
-
phy_c_to_p=
|
|
622
|
-
phy_p_to_c=
|
|
623
|
+
phy_c_to_p=1,
|
|
624
|
+
phy_p_to_c=1,
|
|
623
625
|
nse=0,
|
|
624
626
|
bn_c_to_p=0,
|
|
625
627
|
bn_p_to_c=0,
|
|
@@ -695,7 +697,7 @@ class Controller:
|
|
|
695
697
|
peer_address=peer_address,
|
|
696
698
|
link=self.link,
|
|
697
699
|
transport=PhysicalTransport.BR_EDR,
|
|
698
|
-
link_type=HCI_Connection_Complete_Event.
|
|
700
|
+
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
699
701
|
)
|
|
700
702
|
self.classic_connections[peer_address] = connection
|
|
701
703
|
logger.debug(
|
|
@@ -709,7 +711,7 @@ class Controller:
|
|
|
709
711
|
connection_handle=connection_handle,
|
|
710
712
|
bd_addr=peer_address,
|
|
711
713
|
encryption_enabled=False,
|
|
712
|
-
link_type=HCI_Connection_Complete_Event.
|
|
714
|
+
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
713
715
|
)
|
|
714
716
|
)
|
|
715
717
|
else:
|
|
@@ -720,7 +722,7 @@ class Controller:
|
|
|
720
722
|
connection_handle=0,
|
|
721
723
|
bd_addr=peer_address,
|
|
722
724
|
encryption_enabled=False,
|
|
723
|
-
link_type=HCI_Connection_Complete_Event.
|
|
725
|
+
link_type=HCI_Connection_Complete_Event.LinkType.ACL,
|
|
724
726
|
)
|
|
725
727
|
)
|
|
726
728
|
|
|
@@ -877,6 +879,14 @@ class Controller:
|
|
|
877
879
|
else:
|
|
878
880
|
# Remove the connection
|
|
879
881
|
del self.central_connections[connection.peer_address]
|
|
882
|
+
elif connection := self.find_peripheral_connection_by_handle(handle):
|
|
883
|
+
if self.link:
|
|
884
|
+
self.link.disconnect(
|
|
885
|
+
self.random_address, connection.peer_address, command
|
|
886
|
+
)
|
|
887
|
+
else:
|
|
888
|
+
# Remove the connection
|
|
889
|
+
del self.peripheral_connections[connection.peer_address]
|
|
880
890
|
elif connection := self.find_classic_connection_by_handle(handle):
|
|
881
891
|
if self.link:
|
|
882
892
|
self.link.classic_disconnect(
|
|
@@ -945,7 +955,7 @@ class Controller:
|
|
|
945
955
|
)
|
|
946
956
|
)
|
|
947
957
|
self.link.classic_sco_connect(
|
|
948
|
-
self, connection.peer_address, HCI_Connection_Complete_Event.
|
|
958
|
+
self, connection.peer_address, HCI_Connection_Complete_Event.LinkType.ESCO
|
|
949
959
|
)
|
|
950
960
|
|
|
951
961
|
def on_hci_enhanced_accept_synchronous_connection_request_command(self, command):
|
|
@@ -974,10 +984,71 @@ class Controller:
|
|
|
974
984
|
)
|
|
975
985
|
)
|
|
976
986
|
self.link.classic_accept_sco_connection(
|
|
977
|
-
self, connection.peer_address, HCI_Connection_Complete_Event.
|
|
987
|
+
self, connection.peer_address, HCI_Connection_Complete_Event.LinkType.ESCO
|
|
978
988
|
)
|
|
979
989
|
|
|
980
|
-
def
|
|
990
|
+
def on_hci_sniff_mode_command(self, command: hci.HCI_Sniff_Mode_Command):
|
|
991
|
+
'''
|
|
992
|
+
See Bluetooth spec Vol 4, Part E - 7.2.2 Sniff Mode command
|
|
993
|
+
'''
|
|
994
|
+
if self.link is None:
|
|
995
|
+
self.send_hci_packet(
|
|
996
|
+
hci.HCI_Command_Status_Event(
|
|
997
|
+
status=hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
998
|
+
num_hci_command_packets=1,
|
|
999
|
+
command_opcode=command.op_code,
|
|
1000
|
+
)
|
|
1001
|
+
)
|
|
1002
|
+
return
|
|
1003
|
+
|
|
1004
|
+
self.send_hci_packet(
|
|
1005
|
+
hci.HCI_Command_Status_Event(
|
|
1006
|
+
status=HCI_SUCCESS,
|
|
1007
|
+
num_hci_command_packets=1,
|
|
1008
|
+
command_opcode=command.op_code,
|
|
1009
|
+
)
|
|
1010
|
+
)
|
|
1011
|
+
self.send_hci_packet(
|
|
1012
|
+
hci.HCI_Mode_Change_Event(
|
|
1013
|
+
status=HCI_SUCCESS,
|
|
1014
|
+
connection_handle=command.connection_handle,
|
|
1015
|
+
current_mode=hci.HCI_Mode_Change_Event.Mode.SNIFF,
|
|
1016
|
+
interval=2,
|
|
1017
|
+
)
|
|
1018
|
+
)
|
|
1019
|
+
|
|
1020
|
+
def on_hci_exit_sniff_mode_command(self, command: hci.HCI_Exit_Sniff_Mode_Command):
|
|
1021
|
+
'''
|
|
1022
|
+
See Bluetooth spec Vol 4, Part E - 7.2.3 Exit Sniff Mode command
|
|
1023
|
+
'''
|
|
1024
|
+
|
|
1025
|
+
if self.link is None:
|
|
1026
|
+
self.send_hci_packet(
|
|
1027
|
+
hci.HCI_Command_Status_Event(
|
|
1028
|
+
status=hci.HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR,
|
|
1029
|
+
num_hci_command_packets=1,
|
|
1030
|
+
command_opcode=command.op_code,
|
|
1031
|
+
)
|
|
1032
|
+
)
|
|
1033
|
+
return
|
|
1034
|
+
|
|
1035
|
+
self.send_hci_packet(
|
|
1036
|
+
hci.HCI_Command_Status_Event(
|
|
1037
|
+
status=HCI_SUCCESS,
|
|
1038
|
+
num_hci_command_packets=1,
|
|
1039
|
+
command_opcode=command.op_code,
|
|
1040
|
+
)
|
|
1041
|
+
)
|
|
1042
|
+
self.send_hci_packet(
|
|
1043
|
+
hci.HCI_Mode_Change_Event(
|
|
1044
|
+
status=HCI_SUCCESS,
|
|
1045
|
+
connection_handle=command.connection_handle,
|
|
1046
|
+
current_mode=hci.HCI_Mode_Change_Event.Mode.ACTIVE,
|
|
1047
|
+
interval=2,
|
|
1048
|
+
)
|
|
1049
|
+
)
|
|
1050
|
+
|
|
1051
|
+
def on_hci_switch_role_command(self, command: hci.HCI_Switch_Role_Command):
|
|
981
1052
|
'''
|
|
982
1053
|
See Bluetooth spec Vol 4, Part E - 7.2.8 Switch Role command
|
|
983
1054
|
'''
|
|
@@ -1198,6 +1269,56 @@ class Controller:
|
|
|
1198
1269
|
)
|
|
1199
1270
|
return bytes([HCI_SUCCESS]) + bd_addr
|
|
1200
1271
|
|
|
1272
|
+
def on_hci_le_set_default_subrate_command(
|
|
1273
|
+
self, command: hci.HCI_LE_Set_Default_Subrate_Command
|
|
1274
|
+
):
|
|
1275
|
+
'''
|
|
1276
|
+
See Bluetooth spec Vol 6, Part E - 7.8.123 LE Set Event Mask Command
|
|
1277
|
+
'''
|
|
1278
|
+
|
|
1279
|
+
if (
|
|
1280
|
+
command.subrate_max * (command.max_latency) > 500
|
|
1281
|
+
or command.subrate_max < command.subrate_min
|
|
1282
|
+
or command.continuation_number >= command.subrate_max
|
|
1283
|
+
):
|
|
1284
|
+
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1285
|
+
|
|
1286
|
+
return bytes([HCI_SUCCESS])
|
|
1287
|
+
|
|
1288
|
+
def on_hci_le_subrate_request_command(
|
|
1289
|
+
self, command: hci.HCI_LE_Subrate_Request_Command
|
|
1290
|
+
):
|
|
1291
|
+
'''
|
|
1292
|
+
See Bluetooth spec Vol 6, Part E - 7.8.124 LE Subrate Request command
|
|
1293
|
+
'''
|
|
1294
|
+
if (
|
|
1295
|
+
command.subrate_max * (command.max_latency) > 500
|
|
1296
|
+
or command.continuation_number < command.continuation_number
|
|
1297
|
+
or command.subrate_max < command.subrate_min
|
|
1298
|
+
or command.continuation_number >= command.subrate_max
|
|
1299
|
+
):
|
|
1300
|
+
return bytes([HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR])
|
|
1301
|
+
|
|
1302
|
+
self.send_hci_packet(
|
|
1303
|
+
hci.HCI_Command_Status_Event(
|
|
1304
|
+
status=hci.HCI_SUCCESS,
|
|
1305
|
+
num_hci_command_packets=1,
|
|
1306
|
+
command_opcode=command.op_code,
|
|
1307
|
+
)
|
|
1308
|
+
)
|
|
1309
|
+
|
|
1310
|
+
self.send_hci_packet(
|
|
1311
|
+
hci.HCI_LE_Subrate_Change_Event(
|
|
1312
|
+
status=hci.HCI_SUCCESS,
|
|
1313
|
+
connection_handle=command.connection_handle,
|
|
1314
|
+
subrate_factor=2,
|
|
1315
|
+
peripheral_latency=2,
|
|
1316
|
+
continuation_number=command.continuation_number,
|
|
1317
|
+
supervision_timeout=command.supervision_timeout,
|
|
1318
|
+
)
|
|
1319
|
+
)
|
|
1320
|
+
return None
|
|
1321
|
+
|
|
1201
1322
|
def on_hci_le_set_event_mask_command(self, command):
|
|
1202
1323
|
'''
|
|
1203
1324
|
See Bluetooth spec Vol 4, Part E - 7.8.1 LE Set Event Mask Command
|
|
@@ -1744,3 +1865,11 @@ class Controller:
|
|
|
1744
1865
|
See Bluetooth spec Vol 4, Part E - 7.8.110 LE Remove ISO Data Path Command
|
|
1745
1866
|
'''
|
|
1746
1867
|
return struct.pack('<BH', HCI_SUCCESS, command.connection_handle)
|
|
1868
|
+
|
|
1869
|
+
def on_hci_le_set_host_feature_command(
|
|
1870
|
+
self, _command: hci.HCI_LE_Set_Host_Feature_Command
|
|
1871
|
+
):
|
|
1872
|
+
'''
|
|
1873
|
+
See Bluetooth spec Vol 4, Part E - 7.8.115 LE Set Host Feature command
|
|
1874
|
+
'''
|
|
1875
|
+
return bytes([HCI_SUCCESS])
|