bumble 0.0.178__py3-none-any.whl → 0.0.180__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 +83 -68
- bumble/apps/bench.py +180 -24
- bumble/apps/controller_info.py +14 -0
- bumble/apps/pair.py +9 -2
- bumble/avdtp.py +3 -3
- bumble/crypto.py +82 -66
- bumble/device.py +247 -23
- bumble/gatt.py +117 -7
- bumble/gatt_client.py +56 -20
- bumble/hci.py +351 -78
- bumble/helpers.py +67 -42
- bumble/hid.py +8 -7
- bumble/l2cap.py +8 -0
- bumble/profiles/csip.py +147 -0
- bumble/rfcomm.py +2 -3
- bumble/sdp.py +4 -4
- bumble/smp.py +66 -43
- bumble/transport/common.py +1 -1
- bumble/transport/usb.py +58 -61
- bumble/utils.py +17 -1
- {bumble-0.0.178.dist-info → bumble-0.0.180.dist-info}/METADATA +1 -1
- {bumble-0.0.178.dist-info → bumble-0.0.180.dist-info}/RECORD +27 -26
- {bumble-0.0.178.dist-info → bumble-0.0.180.dist-info}/WHEEL +1 -1
- {bumble-0.0.178.dist-info → bumble-0.0.180.dist-info}/LICENSE +0 -0
- {bumble-0.0.178.dist-info → bumble-0.0.180.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.178.dist-info → bumble-0.0.180.dist-info}/top_level.txt +0 -0
bumble/hci.py
CHANGED
|
@@ -21,7 +21,7 @@ import enum
|
|
|
21
21
|
import functools
|
|
22
22
|
import logging
|
|
23
23
|
import struct
|
|
24
|
-
from typing import Any, Dict, Callable, Optional, Type, Union
|
|
24
|
+
from typing import Any, Dict, Callable, Optional, Type, Union, List
|
|
25
25
|
|
|
26
26
|
from .colors import color
|
|
27
27
|
from .core import (
|
|
@@ -149,6 +149,7 @@ HCI_COMMAND_PACKET = 0x01
|
|
|
149
149
|
HCI_ACL_DATA_PACKET = 0x02
|
|
150
150
|
HCI_SYNCHRONOUS_DATA_PACKET = 0x03
|
|
151
151
|
HCI_EVENT_PACKET = 0x04
|
|
152
|
+
HCI_ISO_DATA_PACKET = 0x05
|
|
152
153
|
|
|
153
154
|
# HCI Event Codes
|
|
154
155
|
HCI_INQUIRY_COMPLETE_EVENT = 0x01
|
|
@@ -3828,8 +3829,10 @@ class HCI_LE_Set_Advertising_Set_Random_Address_Command(HCI_Command):
|
|
|
3828
3829
|
'advertising_event_properties',
|
|
3829
3830
|
{
|
|
3830
3831
|
'size': 2,
|
|
3831
|
-
'mapper': lambda x:
|
|
3832
|
-
|
|
3832
|
+
'mapper': lambda x: str(
|
|
3833
|
+
HCI_LE_Set_Extended_Advertising_Parameters_Command.AdvertisingProperties(
|
|
3834
|
+
x
|
|
3835
|
+
)
|
|
3833
3836
|
),
|
|
3834
3837
|
},
|
|
3835
3838
|
),
|
|
@@ -3839,8 +3842,8 @@ class HCI_LE_Set_Advertising_Set_Random_Address_Command(HCI_Command):
|
|
|
3839
3842
|
'primary_advertising_channel_map',
|
|
3840
3843
|
{
|
|
3841
3844
|
'size': 1,
|
|
3842
|
-
'mapper': lambda x:
|
|
3843
|
-
x
|
|
3845
|
+
'mapper': lambda x: str(
|
|
3846
|
+
HCI_LE_Set_Extended_Advertising_Parameters_Command.ChannelMap(x)
|
|
3844
3847
|
),
|
|
3845
3848
|
},
|
|
3846
3849
|
),
|
|
@@ -3862,38 +3865,33 @@ class HCI_LE_Set_Extended_Advertising_Parameters_Command(HCI_Command):
|
|
|
3862
3865
|
See Bluetooth spec @ 7.8.53 LE Set Extended Advertising Parameters Command
|
|
3863
3866
|
'''
|
|
3864
3867
|
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
'INCLUDE_TX_POWER',
|
|
3881
|
-
)
|
|
3882
|
-
|
|
3883
|
-
CHANNEL_37 = 0
|
|
3884
|
-
CHANNEL_38 = 1
|
|
3885
|
-
CHANNEL_39 = 2
|
|
3868
|
+
class AdvertisingProperties(enum.IntFlag):
|
|
3869
|
+
CONNECTABLE_ADVERTISING = 1 << 0
|
|
3870
|
+
SCANNABLE_ADVERTISING = 1 << 1
|
|
3871
|
+
DIRECTED_ADVERTISING = 1 << 2
|
|
3872
|
+
HIGH_DUTY_CYCLE_DIRECTED_CONNECTABLE_ADVERTISING = 1 << 3
|
|
3873
|
+
USE_LEGACY_ADVERTISING_PDUS = 1 << 4
|
|
3874
|
+
ANONYMOUS_ADVERTISING = 1 << 5
|
|
3875
|
+
INCLUDE_TX_POWER = 1 << 6
|
|
3876
|
+
|
|
3877
|
+
def __str__(self) -> str:
|
|
3878
|
+
return '|'.join(
|
|
3879
|
+
flag.name
|
|
3880
|
+
for flag in HCI_LE_Set_Extended_Advertising_Parameters_Command.AdvertisingProperties
|
|
3881
|
+
if self.value & flag.value and flag.name is not None
|
|
3882
|
+
)
|
|
3886
3883
|
|
|
3887
|
-
|
|
3884
|
+
class ChannelMap(enum.IntFlag):
|
|
3885
|
+
CHANNEL_37 = 1 << 0
|
|
3886
|
+
CHANNEL_38 = 1 << 1
|
|
3887
|
+
CHANNEL_39 = 1 << 2
|
|
3888
3888
|
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
def channel_map_string(cls, channel_map):
|
|
3896
|
-
return f'[{",".join(bit_flags_to_strings(channel_map, cls.CHANNEL_NAMES))}]'
|
|
3889
|
+
def __str__(self) -> str:
|
|
3890
|
+
return '|'.join(
|
|
3891
|
+
flag.name
|
|
3892
|
+
for flag in HCI_LE_Set_Extended_Advertising_Parameters_Command.ChannelMap
|
|
3893
|
+
if self.value & flag.value and flag.name is not None
|
|
3894
|
+
)
|
|
3897
3895
|
|
|
3898
3896
|
|
|
3899
3897
|
# -----------------------------------------------------------------------------
|
|
@@ -3905,9 +3903,9 @@ class HCI_LE_Set_Extended_Advertising_Parameters_Command(HCI_Command):
|
|
|
3905
3903
|
'operation',
|
|
3906
3904
|
{
|
|
3907
3905
|
'size': 1,
|
|
3908
|
-
'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.
|
|
3906
|
+
'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.Operation(
|
|
3909
3907
|
x
|
|
3910
|
-
),
|
|
3908
|
+
).name,
|
|
3911
3909
|
},
|
|
3912
3910
|
),
|
|
3913
3911
|
('fragment_preference', 1),
|
|
@@ -3925,23 +3923,12 @@ class HCI_LE_Set_Extended_Advertising_Data_Command(HCI_Command):
|
|
|
3925
3923
|
See Bluetooth spec @ 7.8.54 LE Set Extended Advertising Data Command
|
|
3926
3924
|
'''
|
|
3927
3925
|
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
OPERATION_NAMES = {
|
|
3935
|
-
INTERMEDIATE_FRAGMENT: 'INTERMEDIATE_FRAGMENT',
|
|
3936
|
-
FIRST_FRAGMENT: 'FIRST_FRAGMENT',
|
|
3937
|
-
LAST_FRAGMENT: 'LAST_FRAGMENT',
|
|
3938
|
-
COMPLETE_DATA: 'COMPLETE_DATA',
|
|
3939
|
-
UNCHANGED_DATA: 'UNCHANGED_DATA',
|
|
3940
|
-
}
|
|
3941
|
-
|
|
3942
|
-
@classmethod
|
|
3943
|
-
def operation_name(cls, operation):
|
|
3944
|
-
return name_or_number(cls.OPERATION_NAMES, operation)
|
|
3926
|
+
class Operation(enum.IntEnum):
|
|
3927
|
+
INTERMEDIATE_FRAGMENT = 0x00
|
|
3928
|
+
FIRST_FRAGMENT = 0x01
|
|
3929
|
+
LAST_FRAGMENT = 0x02
|
|
3930
|
+
COMPLETE_DATA = 0x03
|
|
3931
|
+
UNCHANGED_DATA = 0x04
|
|
3945
3932
|
|
|
3946
3933
|
|
|
3947
3934
|
# -----------------------------------------------------------------------------
|
|
@@ -3953,9 +3940,9 @@ class HCI_LE_Set_Extended_Advertising_Data_Command(HCI_Command):
|
|
|
3953
3940
|
'operation',
|
|
3954
3941
|
{
|
|
3955
3942
|
'size': 1,
|
|
3956
|
-
'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.
|
|
3943
|
+
'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.Operation(
|
|
3957
3944
|
x
|
|
3958
|
-
),
|
|
3945
|
+
).name,
|
|
3959
3946
|
},
|
|
3960
3947
|
),
|
|
3961
3948
|
('fragment_preference', 1),
|
|
@@ -3973,22 +3960,6 @@ class HCI_LE_Set_Extended_Scan_Response_Data_Command(HCI_Command):
|
|
|
3973
3960
|
See Bluetooth spec @ 7.8.55 LE Set Extended Scan Response Data Command
|
|
3974
3961
|
'''
|
|
3975
3962
|
|
|
3976
|
-
INTERMEDIATE_FRAGMENT = 0x00
|
|
3977
|
-
FIRST_FRAGMENT = 0x01
|
|
3978
|
-
LAST_FRAGMENT = 0x02
|
|
3979
|
-
COMPLETE_DATA = 0x03
|
|
3980
|
-
|
|
3981
|
-
OPERATION_NAMES = {
|
|
3982
|
-
INTERMEDIATE_FRAGMENT: 'INTERMEDIATE_FRAGMENT',
|
|
3983
|
-
FIRST_FRAGMENT: 'FIRST_FRAGMENT',
|
|
3984
|
-
LAST_FRAGMENT: 'LAST_FRAGMENT',
|
|
3985
|
-
COMPLETE_DATA: 'COMPLETE_DATA',
|
|
3986
|
-
}
|
|
3987
|
-
|
|
3988
|
-
@classmethod
|
|
3989
|
-
def operation_name(cls, operation):
|
|
3990
|
-
return name_or_number(cls.OPERATION_NAMES, operation)
|
|
3991
|
-
|
|
3992
3963
|
|
|
3993
3964
|
# -----------------------------------------------------------------------------
|
|
3994
3965
|
@HCI_Command.command(
|
|
@@ -4386,6 +4357,158 @@ class HCI_LE_Set_Host_Feature_Command(HCI_Command):
|
|
|
4386
4357
|
'''
|
|
4387
4358
|
|
|
4388
4359
|
|
|
4360
|
+
# -----------------------------------------------------------------------------
|
|
4361
|
+
@HCI_Command.command(
|
|
4362
|
+
fields=[
|
|
4363
|
+
('cig_id', 1),
|
|
4364
|
+
('sdu_interval_c_to_p', 3),
|
|
4365
|
+
('sdu_interval_p_to_c', 3),
|
|
4366
|
+
('worst_case_sca', 1),
|
|
4367
|
+
('packing', 1),
|
|
4368
|
+
('framing', 1),
|
|
4369
|
+
('max_transport_latency_c_to_p', 2),
|
|
4370
|
+
('max_transport_latency_p_to_c', 2),
|
|
4371
|
+
[
|
|
4372
|
+
('cis_id', 1),
|
|
4373
|
+
('max_sdu_c_to_p', 2),
|
|
4374
|
+
('max_sdu_p_to_c', 2),
|
|
4375
|
+
('phy_c_to_p', 1),
|
|
4376
|
+
('phy_p_to_c', 1),
|
|
4377
|
+
('rtn_c_to_p', 1),
|
|
4378
|
+
('rtn_p_to_c', 1),
|
|
4379
|
+
],
|
|
4380
|
+
],
|
|
4381
|
+
return_parameters_fields=[
|
|
4382
|
+
('status', STATUS_SPEC),
|
|
4383
|
+
('cig_id', 1),
|
|
4384
|
+
[('connection_handle', 2)],
|
|
4385
|
+
],
|
|
4386
|
+
)
|
|
4387
|
+
class HCI_LE_Set_CIG_Parameters_Command(HCI_Command):
|
|
4388
|
+
'''
|
|
4389
|
+
See Bluetooth spec @ 7.8.97 LE Set CIG Parameters Command
|
|
4390
|
+
'''
|
|
4391
|
+
|
|
4392
|
+
cig_id: int
|
|
4393
|
+
sdu_interval_c_to_p: int
|
|
4394
|
+
sdu_interval_p_to_c: int
|
|
4395
|
+
worst_case_sca: int
|
|
4396
|
+
packing: int
|
|
4397
|
+
framing: int
|
|
4398
|
+
max_transport_latency_c_to_p: int
|
|
4399
|
+
max_transport_latency_p_to_c: int
|
|
4400
|
+
cis_id: List[int]
|
|
4401
|
+
max_sdu_c_to_p: List[int]
|
|
4402
|
+
max_sdu_p_to_c: List[int]
|
|
4403
|
+
phy_c_to_p: List[int]
|
|
4404
|
+
phy_p_to_c: List[int]
|
|
4405
|
+
rtn_c_to_p: List[int]
|
|
4406
|
+
rtn_p_to_c: List[int]
|
|
4407
|
+
|
|
4408
|
+
|
|
4409
|
+
# -----------------------------------------------------------------------------
|
|
4410
|
+
@HCI_Command.command(
|
|
4411
|
+
fields=[
|
|
4412
|
+
[
|
|
4413
|
+
('cis_connection_handle', 2),
|
|
4414
|
+
('acl_connection_handle', 2),
|
|
4415
|
+
],
|
|
4416
|
+
],
|
|
4417
|
+
)
|
|
4418
|
+
class HCI_LE_Create_CIS_Command(HCI_Command):
|
|
4419
|
+
'''
|
|
4420
|
+
See Bluetooth spec @ 7.8.99 LE Create CIS command
|
|
4421
|
+
'''
|
|
4422
|
+
|
|
4423
|
+
cis_connection_handle: List[int]
|
|
4424
|
+
acl_connection_handle: List[int]
|
|
4425
|
+
|
|
4426
|
+
|
|
4427
|
+
# -----------------------------------------------------------------------------
|
|
4428
|
+
@HCI_Command.command(
|
|
4429
|
+
fields=[('cig_id', 1)],
|
|
4430
|
+
return_parameters_fields=[('status', STATUS_SPEC), ('cig_id', 1)],
|
|
4431
|
+
)
|
|
4432
|
+
class HCI_LE_Remove_CIG_Command(HCI_Command):
|
|
4433
|
+
'''
|
|
4434
|
+
See Bluetooth spec @ 7.8.100 LE Remove CIG command
|
|
4435
|
+
'''
|
|
4436
|
+
|
|
4437
|
+
cig_id: int
|
|
4438
|
+
|
|
4439
|
+
|
|
4440
|
+
# -----------------------------------------------------------------------------
|
|
4441
|
+
@HCI_Command.command(
|
|
4442
|
+
fields=[('connection_handle', 2)],
|
|
4443
|
+
)
|
|
4444
|
+
class HCI_LE_Accept_CIS_Request_Command(HCI_Command):
|
|
4445
|
+
'''
|
|
4446
|
+
See Bluetooth spec @ 7.8.101 LE Accept CIS Request command
|
|
4447
|
+
'''
|
|
4448
|
+
|
|
4449
|
+
connection_handle: int
|
|
4450
|
+
|
|
4451
|
+
|
|
4452
|
+
# -----------------------------------------------------------------------------
|
|
4453
|
+
@HCI_Command.command(
|
|
4454
|
+
fields=[('connection_handle', 2)],
|
|
4455
|
+
)
|
|
4456
|
+
class HCI_LE_Reject_CIS_Request_Command(HCI_Command):
|
|
4457
|
+
'''
|
|
4458
|
+
See Bluetooth spec @ 7.8.102 LE Reject CIS Request command
|
|
4459
|
+
'''
|
|
4460
|
+
|
|
4461
|
+
connection_handle: int
|
|
4462
|
+
|
|
4463
|
+
|
|
4464
|
+
# -----------------------------------------------------------------------------
|
|
4465
|
+
@HCI_Command.command(
|
|
4466
|
+
fields=[
|
|
4467
|
+
('connection_handle', 2),
|
|
4468
|
+
('data_path_direction', 1),
|
|
4469
|
+
('data_path_id', 1),
|
|
4470
|
+
('codec_id', 5),
|
|
4471
|
+
('controller_delay', 3),
|
|
4472
|
+
('codec_configuration', '*'),
|
|
4473
|
+
],
|
|
4474
|
+
return_parameters_fields=[
|
|
4475
|
+
('status', STATUS_SPEC),
|
|
4476
|
+
('connection_handle', 2),
|
|
4477
|
+
],
|
|
4478
|
+
)
|
|
4479
|
+
class HCI_LE_Setup_ISO_Data_Path_Command(HCI_Command):
|
|
4480
|
+
'''
|
|
4481
|
+
See Bluetooth spec @ 7.8.109 LE Setup ISO Data Path command
|
|
4482
|
+
'''
|
|
4483
|
+
|
|
4484
|
+
connection_handle: int
|
|
4485
|
+
data_path_direction: int
|
|
4486
|
+
data_path_id: int
|
|
4487
|
+
codec_id: int
|
|
4488
|
+
controller_delay: int
|
|
4489
|
+
codec_configuration: int
|
|
4490
|
+
|
|
4491
|
+
|
|
4492
|
+
# -----------------------------------------------------------------------------
|
|
4493
|
+
@HCI_Command.command(
|
|
4494
|
+
fields=[
|
|
4495
|
+
('connection_handle', 2),
|
|
4496
|
+
('data_path_direction', 1),
|
|
4497
|
+
],
|
|
4498
|
+
return_parameters_fields=[
|
|
4499
|
+
('status', STATUS_SPEC),
|
|
4500
|
+
('connection_handle', 2),
|
|
4501
|
+
],
|
|
4502
|
+
)
|
|
4503
|
+
class HCI_LE_Remove_ISO_Data_Path_Command(HCI_Command):
|
|
4504
|
+
'''
|
|
4505
|
+
See Bluetooth spec @ 7.8.110 LE Remove ISO Data Path command
|
|
4506
|
+
'''
|
|
4507
|
+
|
|
4508
|
+
connection_handle: int
|
|
4509
|
+
data_path_direction: int
|
|
4510
|
+
|
|
4511
|
+
|
|
4389
4512
|
# -----------------------------------------------------------------------------
|
|
4390
4513
|
# HCI Events
|
|
4391
4514
|
# -----------------------------------------------------------------------------
|
|
@@ -5005,6 +5128,48 @@ class HCI_LE_Channel_Selection_Algorithm_Event(HCI_LE_Meta_Event):
|
|
|
5005
5128
|
'''
|
|
5006
5129
|
|
|
5007
5130
|
|
|
5131
|
+
# -----------------------------------------------------------------------------
|
|
5132
|
+
@HCI_LE_Meta_Event.event(
|
|
5133
|
+
[
|
|
5134
|
+
('status', STATUS_SPEC),
|
|
5135
|
+
('connection_handle', 2),
|
|
5136
|
+
('cig_sync_delay', 3),
|
|
5137
|
+
('cis_sync_delay', 3),
|
|
5138
|
+
('transport_latency_c_to_p', 3),
|
|
5139
|
+
('transport_latency_p_to_c', 3),
|
|
5140
|
+
('phy_c_to_p', 1),
|
|
5141
|
+
('phy_p_to_c', 1),
|
|
5142
|
+
('nse', 1),
|
|
5143
|
+
('bn_c_to_p', 1),
|
|
5144
|
+
('bn_p_to_c', 1),
|
|
5145
|
+
('ft_c_to_p', 1),
|
|
5146
|
+
('ft_p_to_c', 1),
|
|
5147
|
+
('max_pdu_c_to_p', 2),
|
|
5148
|
+
('max_pdu_p_to_c', 2),
|
|
5149
|
+
('iso_interval', 2),
|
|
5150
|
+
]
|
|
5151
|
+
)
|
|
5152
|
+
class HCI_LE_CIS_Established_Event(HCI_LE_Meta_Event):
|
|
5153
|
+
'''
|
|
5154
|
+
See Bluetooth spec @ 7.7.65.25 LE CIS Established Event
|
|
5155
|
+
'''
|
|
5156
|
+
|
|
5157
|
+
|
|
5158
|
+
# -----------------------------------------------------------------------------
|
|
5159
|
+
@HCI_LE_Meta_Event.event(
|
|
5160
|
+
[
|
|
5161
|
+
('acl_connection_handle', 2),
|
|
5162
|
+
('cis_connection_handle', 2),
|
|
5163
|
+
('cig_id', 1),
|
|
5164
|
+
('cis_id', 1),
|
|
5165
|
+
]
|
|
5166
|
+
)
|
|
5167
|
+
class HCI_LE_CIS_Request_Event(HCI_LE_Meta_Event):
|
|
5168
|
+
'''
|
|
5169
|
+
See Bluetooth spec @ 7.7.65.26 LE CIS Request Event
|
|
5170
|
+
'''
|
|
5171
|
+
|
|
5172
|
+
|
|
5008
5173
|
# -----------------------------------------------------------------------------
|
|
5009
5174
|
@HCI_Event.event([('status', STATUS_SPEC)])
|
|
5010
5175
|
class HCI_Inquiry_Complete_Event(HCI_Event):
|
|
@@ -5131,6 +5296,10 @@ class HCI_Disconnection_Complete_Event(HCI_Event):
|
|
|
5131
5296
|
See Bluetooth spec @ 7.7.5 Disconnection Complete Event
|
|
5132
5297
|
'''
|
|
5133
5298
|
|
|
5299
|
+
status: int
|
|
5300
|
+
connection_handle: int
|
|
5301
|
+
reason: int
|
|
5302
|
+
|
|
5134
5303
|
|
|
5135
5304
|
# -----------------------------------------------------------------------------
|
|
5136
5305
|
@HCI_Event.event([('status', STATUS_SPEC), ('connection_handle', 2)])
|
|
@@ -5815,18 +5984,17 @@ class HCI_SynchronousDataPacket(HCI_Packet):
|
|
|
5815
5984
|
h, data_total_length = struct.unpack_from('<HB', packet, 1)
|
|
5816
5985
|
connection_handle = h & 0xFFF
|
|
5817
5986
|
packet_status = (h >> 12) & 0b11
|
|
5818
|
-
rfu = (h >> 14) & 0b11
|
|
5819
5987
|
data = packet[4:]
|
|
5820
5988
|
if len(data) != data_total_length:
|
|
5821
5989
|
raise ValueError(
|
|
5822
5990
|
f'invalid packet length {len(data)} != {data_total_length}'
|
|
5823
5991
|
)
|
|
5824
5992
|
return HCI_SynchronousDataPacket(
|
|
5825
|
-
connection_handle, packet_status,
|
|
5993
|
+
connection_handle, packet_status, data_total_length, data
|
|
5826
5994
|
)
|
|
5827
5995
|
|
|
5828
5996
|
def to_bytes(self) -> bytes:
|
|
5829
|
-
h = (self.packet_status << 12) |
|
|
5997
|
+
h = (self.packet_status << 12) | self.connection_handle
|
|
5830
5998
|
return (
|
|
5831
5999
|
struct.pack('<BHB', HCI_SYNCHRONOUS_DATA_PACKET, h, self.data_total_length)
|
|
5832
6000
|
+ self.data
|
|
@@ -5836,13 +6004,11 @@ class HCI_SynchronousDataPacket(HCI_Packet):
|
|
|
5836
6004
|
self,
|
|
5837
6005
|
connection_handle: int,
|
|
5838
6006
|
packet_status: int,
|
|
5839
|
-
rfu: int,
|
|
5840
6007
|
data_total_length: int,
|
|
5841
6008
|
data: bytes,
|
|
5842
6009
|
) -> None:
|
|
5843
6010
|
self.connection_handle = connection_handle
|
|
5844
6011
|
self.packet_status = packet_status
|
|
5845
|
-
self.rfu = rfu
|
|
5846
6012
|
self.data_total_length = data_total_length
|
|
5847
6013
|
self.data = data
|
|
5848
6014
|
|
|
@@ -5853,12 +6019,119 @@ class HCI_SynchronousDataPacket(HCI_Packet):
|
|
|
5853
6019
|
return (
|
|
5854
6020
|
f'{color("SCO", "blue")}: '
|
|
5855
6021
|
f'handle=0x{self.connection_handle:04x}, '
|
|
5856
|
-
f'ps={self.packet_status},
|
|
6022
|
+
f'ps={self.packet_status}, '
|
|
5857
6023
|
f'data_total_length={self.data_total_length}, '
|
|
5858
6024
|
f'data={self.data.hex()}'
|
|
5859
6025
|
)
|
|
5860
6026
|
|
|
5861
6027
|
|
|
6028
|
+
# -----------------------------------------------------------------------------
|
|
6029
|
+
class HCI_IsoDataPacket(HCI_Packet):
|
|
6030
|
+
'''
|
|
6031
|
+
See Bluetooth spec @ 5.4.5 HCI ISO Data Packets
|
|
6032
|
+
'''
|
|
6033
|
+
|
|
6034
|
+
hci_packet_type = HCI_ISO_DATA_PACKET
|
|
6035
|
+
|
|
6036
|
+
@staticmethod
|
|
6037
|
+
def from_bytes(packet: bytes) -> HCI_IsoDataPacket:
|
|
6038
|
+
time_stamp: Optional[int] = None
|
|
6039
|
+
packet_sequence_number: Optional[int] = None
|
|
6040
|
+
iso_sdu_length: Optional[int] = None
|
|
6041
|
+
packet_status_flag: Optional[int] = None
|
|
6042
|
+
|
|
6043
|
+
pos = 1
|
|
6044
|
+
pdu_info, data_total_length = struct.unpack_from('<HH', packet, pos)
|
|
6045
|
+
connection_handle = pdu_info & 0xFFF
|
|
6046
|
+
pb_flag = (pdu_info >> 12) & 0b11
|
|
6047
|
+
ts_flag = (pdu_info >> 14) & 0b01
|
|
6048
|
+
pos += 4
|
|
6049
|
+
|
|
6050
|
+
# pb_flag in (0b00, 0b10) but faster
|
|
6051
|
+
should_include_sdu_info = not (pb_flag & 0b01)
|
|
6052
|
+
|
|
6053
|
+
if ts_flag:
|
|
6054
|
+
if not should_include_sdu_info:
|
|
6055
|
+
logger.warn(f'Timestamp included when pb_flag={bin(pb_flag)}')
|
|
6056
|
+
time_stamp, _ = struct.unpack_from('<I', packet, pos)
|
|
6057
|
+
pos += 4
|
|
6058
|
+
|
|
6059
|
+
if should_include_sdu_info:
|
|
6060
|
+
packet_sequence_number, sdu_info = struct.unpack_from('<HH', packet, pos)
|
|
6061
|
+
iso_sdu_length = sdu_info & 0xFFF
|
|
6062
|
+
packet_status_flag = sdu_info >> 14
|
|
6063
|
+
pos += 4
|
|
6064
|
+
|
|
6065
|
+
iso_sdu_fragment = packet[pos:]
|
|
6066
|
+
return HCI_IsoDataPacket(
|
|
6067
|
+
connection_handle=connection_handle,
|
|
6068
|
+
pb_flag=pb_flag,
|
|
6069
|
+
ts_flag=ts_flag,
|
|
6070
|
+
data_total_length=data_total_length,
|
|
6071
|
+
time_stamp=time_stamp,
|
|
6072
|
+
packet_sequence_number=packet_sequence_number,
|
|
6073
|
+
iso_sdu_length=iso_sdu_length,
|
|
6074
|
+
packet_status_flag=packet_status_flag,
|
|
6075
|
+
iso_sdu_fragment=iso_sdu_fragment,
|
|
6076
|
+
)
|
|
6077
|
+
|
|
6078
|
+
def __init__(
|
|
6079
|
+
self,
|
|
6080
|
+
connection_handle: int,
|
|
6081
|
+
pb_flag: int,
|
|
6082
|
+
ts_flag: int,
|
|
6083
|
+
data_total_length: int,
|
|
6084
|
+
time_stamp: Optional[int],
|
|
6085
|
+
packet_sequence_number: Optional[int],
|
|
6086
|
+
iso_sdu_length: Optional[int],
|
|
6087
|
+
packet_status_flag: Optional[int],
|
|
6088
|
+
iso_sdu_fragment: bytes,
|
|
6089
|
+
) -> None:
|
|
6090
|
+
self.connection_handle = connection_handle
|
|
6091
|
+
self.pb_flag = pb_flag
|
|
6092
|
+
self.ts_flag = ts_flag
|
|
6093
|
+
self.data_total_length = data_total_length
|
|
6094
|
+
self.time_stamp = time_stamp
|
|
6095
|
+
self.packet_sequence_number = packet_sequence_number
|
|
6096
|
+
self.iso_sdu_length = iso_sdu_length
|
|
6097
|
+
self.packet_status_flag = packet_status_flag
|
|
6098
|
+
self.iso_sdu_fragment = iso_sdu_fragment
|
|
6099
|
+
|
|
6100
|
+
def __bytes__(self) -> bytes:
|
|
6101
|
+
return self.to_bytes()
|
|
6102
|
+
|
|
6103
|
+
def to_bytes(self) -> bytes:
|
|
6104
|
+
fmt = '<BHH'
|
|
6105
|
+
args = [
|
|
6106
|
+
HCI_ISO_DATA_PACKET,
|
|
6107
|
+
self.ts_flag << 14 | self.pb_flag << 12 | self.connection_handle,
|
|
6108
|
+
self.data_total_length,
|
|
6109
|
+
]
|
|
6110
|
+
if self.time_stamp is not None:
|
|
6111
|
+
fmt += 'I'
|
|
6112
|
+
args.append(self.time_stamp)
|
|
6113
|
+
if (
|
|
6114
|
+
self.packet_sequence_number is not None
|
|
6115
|
+
and self.iso_sdu_length is not None
|
|
6116
|
+
and self.packet_status_flag is not None
|
|
6117
|
+
):
|
|
6118
|
+
fmt += 'HH'
|
|
6119
|
+
args += [
|
|
6120
|
+
self.packet_sequence_number,
|
|
6121
|
+
self.iso_sdu_length | self.packet_status_flag << 14,
|
|
6122
|
+
]
|
|
6123
|
+
return struct.pack(fmt, args) + self.iso_sdu_fragment
|
|
6124
|
+
|
|
6125
|
+
def __str__(self) -> str:
|
|
6126
|
+
return (
|
|
6127
|
+
f'{color("ISO", "blue")}: '
|
|
6128
|
+
f'handle=0x{self.connection_handle:04x}, '
|
|
6129
|
+
f'ps={self.packet_status_flag}, '
|
|
6130
|
+
f'data_total_length={self.data_total_length}, '
|
|
6131
|
+
f'sdu={self.iso_sdu_fragment.hex()}'
|
|
6132
|
+
)
|
|
6133
|
+
|
|
6134
|
+
|
|
5862
6135
|
# -----------------------------------------------------------------------------
|
|
5863
6136
|
class HCI_AclDataPacketAssembler:
|
|
5864
6137
|
current_data: Optional[bytes]
|