bumble 0.0.214__py3-none-any.whl → 0.0.216__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 +16 -3
- bumble/a2dp.py +15 -16
- bumble/apps/auracast.py +13 -38
- bumble/apps/bench.py +9 -10
- bumble/apps/ble_rpa_tool.py +1 -0
- bumble/apps/console.py +22 -25
- bumble/apps/controller_info.py +19 -19
- bumble/apps/controller_loopback.py +2 -2
- bumble/apps/controllers.py +1 -1
- bumble/apps/device_info.py +3 -3
- bumble/apps/gatt_dump.py +1 -1
- bumble/apps/gg_bridge.py +5 -6
- bumble/apps/hci_bridge.py +3 -3
- bumble/apps/l2cap_bridge.py +3 -3
- bumble/apps/lea_unicast/app.py +15 -25
- bumble/apps/pair.py +30 -43
- bumble/apps/pandora_server.py +5 -4
- bumble/apps/player/player.py +19 -22
- bumble/apps/rfcomm_bridge.py +3 -8
- bumble/apps/scan.py +16 -6
- bumble/apps/show.py +3 -4
- bumble/apps/speaker/speaker.py +22 -22
- bumble/apps/unbond.py +2 -1
- bumble/apps/usb_probe.py +1 -2
- bumble/att.py +241 -246
- bumble/audio/io.py +5 -9
- bumble/avc.py +2 -2
- bumble/avctp.py +6 -7
- bumble/avdtp.py +19 -22
- bumble/avrcp.py +1096 -588
- bumble/codecs.py +2 -0
- bumble/controller.py +52 -13
- bumble/core.py +567 -248
- bumble/crypto/__init__.py +2 -2
- bumble/crypto/builtin.py +1 -1
- bumble/crypto/cryptography.py +2 -4
- bumble/data_types.py +1025 -0
- bumble/device.py +318 -279
- bumble/drivers/__init__.py +3 -2
- bumble/drivers/intel.py +3 -4
- bumble/drivers/rtk.py +26 -9
- bumble/gap.py +4 -4
- bumble/gatt.py +3 -2
- bumble/gatt_adapters.py +3 -11
- bumble/gatt_client.py +69 -81
- bumble/gatt_server.py +124 -124
- bumble/hci.py +67 -18
- bumble/helpers.py +19 -26
- bumble/hfp.py +10 -21
- bumble/hid.py +22 -16
- bumble/host.py +181 -103
- bumble/keys.py +5 -3
- bumble/l2cap.py +121 -74
- bumble/link.py +8 -9
- bumble/pairing.py +7 -6
- bumble/pandora/__init__.py +8 -7
- bumble/pandora/config.py +3 -1
- bumble/pandora/device.py +3 -2
- bumble/pandora/host.py +38 -36
- bumble/pandora/l2cap.py +22 -21
- bumble/pandora/security.py +15 -15
- bumble/pandora/utils.py +5 -3
- bumble/profiles/aics.py +11 -11
- bumble/profiles/ams.py +7 -8
- bumble/profiles/ancs.py +6 -7
- bumble/profiles/ascs.py +4 -9
- bumble/profiles/asha.py +8 -12
- bumble/profiles/bap.py +11 -23
- bumble/profiles/bass.py +2 -7
- bumble/profiles/battery_service.py +3 -4
- bumble/profiles/cap.py +1 -2
- bumble/profiles/csip.py +2 -6
- bumble/profiles/device_information_service.py +2 -2
- bumble/profiles/gap.py +4 -4
- bumble/profiles/gatt_service.py +1 -4
- bumble/profiles/gmap.py +5 -5
- bumble/profiles/hap.py +62 -59
- bumble/profiles/heart_rate_service.py +5 -4
- bumble/profiles/le_audio.py +3 -1
- bumble/profiles/mcp.py +3 -7
- bumble/profiles/pacs.py +3 -6
- bumble/profiles/pbp.py +2 -0
- bumble/profiles/tmap.py +2 -3
- bumble/profiles/vcs.py +2 -8
- bumble/profiles/vocs.py +8 -8
- bumble/rfcomm.py +11 -14
- bumble/rtp.py +1 -0
- bumble/sdp.py +10 -8
- bumble/smp.py +142 -153
- bumble/snoop.py +5 -5
- bumble/tools/generate_company_id_list.py +1 -0
- bumble/tools/intel_fw_download.py +3 -3
- bumble/tools/intel_util.py +4 -4
- bumble/tools/rtk_fw_download.py +6 -3
- bumble/tools/rtk_util.py +24 -7
- bumble/transport/__init__.py +19 -15
- bumble/transport/android_emulator.py +8 -13
- bumble/transport/android_netsim.py +19 -18
- bumble/transport/common.py +12 -15
- bumble/transport/file.py +1 -1
- bumble/transport/hci_socket.py +4 -6
- bumble/transport/pty.py +5 -6
- bumble/transport/pyusb.py +7 -10
- bumble/transport/serial.py +2 -1
- bumble/transport/tcp_client.py +2 -2
- bumble/transport/tcp_server.py +11 -14
- bumble/transport/udp.py +3 -3
- bumble/transport/unix.py +67 -1
- bumble/transport/usb.py +6 -6
- bumble/transport/vhci.py +0 -1
- bumble/transport/ws_client.py +2 -1
- bumble/transport/ws_server.py +3 -2
- bumble/utils.py +20 -5
- bumble/vendor/android/hci.py +1 -2
- bumble/vendor/zephyr/hci.py +0 -1
- {bumble-0.0.214.dist-info → bumble-0.0.216.dist-info}/METADATA +2 -1
- bumble-0.0.216.dist-info/RECORD +183 -0
- bumble-0.0.214.dist-info/RECORD +0 -182
- {bumble-0.0.214.dist-info → bumble-0.0.216.dist-info}/WHEEL +0 -0
- {bumble-0.0.214.dist-info → bumble-0.0.216.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.214.dist-info → bumble-0.0.216.dist-info}/licenses/LICENSE +0 -0
- {bumble-0.0.214.dist-info → bumble-0.0.216.dist-info}/top_level.txt +0 -0
bumble/hci.py
CHANGED
|
@@ -16,19 +16,31 @@
|
|
|
16
16
|
# Imports
|
|
17
17
|
# -----------------------------------------------------------------------------
|
|
18
18
|
from __future__ import annotations
|
|
19
|
+
|
|
19
20
|
import collections
|
|
20
21
|
import dataclasses
|
|
21
|
-
from dataclasses import field
|
|
22
22
|
import enum
|
|
23
23
|
import functools
|
|
24
24
|
import logging
|
|
25
25
|
import secrets
|
|
26
26
|
import struct
|
|
27
27
|
from collections.abc import Sequence
|
|
28
|
-
from
|
|
28
|
+
from dataclasses import field
|
|
29
|
+
from typing import (
|
|
30
|
+
Any,
|
|
31
|
+
Callable,
|
|
32
|
+
ClassVar,
|
|
33
|
+
Iterable,
|
|
34
|
+
Literal,
|
|
35
|
+
Optional,
|
|
36
|
+
TypeVar,
|
|
37
|
+
Union,
|
|
38
|
+
cast,
|
|
39
|
+
)
|
|
40
|
+
|
|
29
41
|
from typing_extensions import Self
|
|
30
42
|
|
|
31
|
-
from bumble import crypto
|
|
43
|
+
from bumble import crypto, utils
|
|
32
44
|
from bumble.colors import color
|
|
33
45
|
from bumble.core import (
|
|
34
46
|
DeviceClass,
|
|
@@ -40,8 +52,6 @@ from bumble.core import (
|
|
|
40
52
|
name_or_number,
|
|
41
53
|
padded_bytes,
|
|
42
54
|
)
|
|
43
|
-
from bumble import utils
|
|
44
|
-
|
|
45
55
|
|
|
46
56
|
# -----------------------------------------------------------------------------
|
|
47
57
|
# Logging
|
|
@@ -111,23 +121,57 @@ def phy_list_to_bits(phys: Optional[Iterable[Phy]]) -> int:
|
|
|
111
121
|
class SpecableEnum(utils.OpenIntEnum):
|
|
112
122
|
|
|
113
123
|
@classmethod
|
|
114
|
-
def type_spec(cls, size: int):
|
|
115
|
-
return {
|
|
124
|
+
def type_spec(cls, size: int, byteorder: Literal['little', 'big'] = 'little'):
|
|
125
|
+
return {
|
|
126
|
+
'serializer': lambda x: x.to_bytes(size, byteorder),
|
|
127
|
+
'parser': lambda data, offset: (
|
|
128
|
+
offset + size,
|
|
129
|
+
cls(int.from_bytes(data[offset : offset + size], byteorder)),
|
|
130
|
+
),
|
|
131
|
+
'mapper': lambda x: cls(x).name,
|
|
132
|
+
}
|
|
116
133
|
|
|
117
134
|
@classmethod
|
|
118
|
-
def type_metadata(
|
|
119
|
-
|
|
135
|
+
def type_metadata(
|
|
136
|
+
cls,
|
|
137
|
+
size: int,
|
|
138
|
+
list_begin: bool = False,
|
|
139
|
+
list_end: bool = False,
|
|
140
|
+
byteorder: Literal['little', 'big'] = 'little',
|
|
141
|
+
):
|
|
142
|
+
return metadata(
|
|
143
|
+
cls.type_spec(size, byteorder),
|
|
144
|
+
list_begin=list_begin,
|
|
145
|
+
list_end=list_end,
|
|
146
|
+
)
|
|
120
147
|
|
|
121
148
|
|
|
122
149
|
class SpecableFlag(enum.IntFlag):
|
|
123
150
|
|
|
124
151
|
@classmethod
|
|
125
|
-
def type_spec(cls, size: int):
|
|
126
|
-
return {
|
|
152
|
+
def type_spec(cls, size: int, byteorder: Literal['little', 'big'] = 'little'):
|
|
153
|
+
return {
|
|
154
|
+
'serializer': lambda x: x.to_bytes(size, byteorder),
|
|
155
|
+
'parser': lambda data, offset: (
|
|
156
|
+
offset + size,
|
|
157
|
+
cls(int.from_bytes(data[offset : offset + size], byteorder)),
|
|
158
|
+
),
|
|
159
|
+
'mapper': lambda x: cls(x).name,
|
|
160
|
+
}
|
|
127
161
|
|
|
128
162
|
@classmethod
|
|
129
|
-
def type_metadata(
|
|
130
|
-
|
|
163
|
+
def type_metadata(
|
|
164
|
+
cls,
|
|
165
|
+
size: int,
|
|
166
|
+
list_begin: bool = False,
|
|
167
|
+
list_end: bool = False,
|
|
168
|
+
byteorder: Literal['little', 'big'] = 'little',
|
|
169
|
+
):
|
|
170
|
+
return metadata(
|
|
171
|
+
cls.type_spec(size, byteorder),
|
|
172
|
+
list_begin=list_begin,
|
|
173
|
+
list_end=list_end,
|
|
174
|
+
)
|
|
131
175
|
|
|
132
176
|
|
|
133
177
|
# -----------------------------------------------------------------------------
|
|
@@ -1322,7 +1366,7 @@ class LeFeature(SpecableEnum):
|
|
|
1322
1366
|
MONITORING_ADVERTISERS = 64
|
|
1323
1367
|
FRAME_SPACE_UPDATE = 65
|
|
1324
1368
|
|
|
1325
|
-
class LeFeatureMask(
|
|
1369
|
+
class LeFeatureMask(utils.CompatibleIntFlag):
|
|
1326
1370
|
LE_ENCRYPTION = 1 << LeFeature.LE_ENCRYPTION
|
|
1327
1371
|
CONNECTION_PARAMETERS_REQUEST_PROCEDURE = 1 << LeFeature.CONNECTION_PARAMETERS_REQUEST_PROCEDURE
|
|
1328
1372
|
EXTENDED_REJECT_INDICATION = 1 << LeFeature.EXTENDED_REJECT_INDICATION
|
|
@@ -1463,7 +1507,7 @@ class LmpFeature(SpecableEnum):
|
|
|
1463
1507
|
SLOT_AVAILABILITY_MASK = 138
|
|
1464
1508
|
TRAIN_NUDGING = 139
|
|
1465
1509
|
|
|
1466
|
-
class LmpFeatureMask(
|
|
1510
|
+
class LmpFeatureMask(utils.CompatibleIntFlag):
|
|
1467
1511
|
# Page 0 (Legacy LMP features)
|
|
1468
1512
|
LMP_3_SLOT_PACKETS = (1 << LmpFeature.LMP_3_SLOT_PACKETS)
|
|
1469
1513
|
LMP_5_SLOT_PACKETS = (1 << LmpFeature.LMP_5_SLOT_PACKETS)
|
|
@@ -2135,6 +2179,7 @@ class Address:
|
|
|
2135
2179
|
if len(address) == 12 + 5:
|
|
2136
2180
|
# Form with ':' separators
|
|
2137
2181
|
address = address.replace(':', '')
|
|
2182
|
+
|
|
2138
2183
|
self.address_bytes = bytes(reversed(bytes.fromhex(address)))
|
|
2139
2184
|
|
|
2140
2185
|
if len(self.address_bytes) != 6:
|
|
@@ -5257,7 +5302,7 @@ class HCI_LE_BIG_Terminate_Sync_Command(HCI_Command):
|
|
|
5257
5302
|
|
|
5258
5303
|
return_parameters_fields = [
|
|
5259
5304
|
('status', STATUS_SPEC),
|
|
5260
|
-
('big_handle',
|
|
5305
|
+
('big_handle', 1),
|
|
5261
5306
|
]
|
|
5262
5307
|
|
|
5263
5308
|
|
|
@@ -6421,7 +6466,9 @@ class HCI_LE_Create_BIG_Complete_Event(HCI_LE_Meta_Event):
|
|
|
6421
6466
|
irc: int = field(metadata=metadata(1))
|
|
6422
6467
|
max_pdu: int = field(metadata=metadata(2))
|
|
6423
6468
|
iso_interval: int = field(metadata=metadata(2))
|
|
6424
|
-
connection_handle: int = field(
|
|
6469
|
+
connection_handle: Sequence[int] = field(
|
|
6470
|
+
metadata=metadata(2, list_begin=True, list_end=True)
|
|
6471
|
+
)
|
|
6425
6472
|
|
|
6426
6473
|
|
|
6427
6474
|
# -----------------------------------------------------------------------------
|
|
@@ -6453,7 +6500,9 @@ class HCI_LE_BIG_Sync_Established_Event(HCI_LE_Meta_Event):
|
|
|
6453
6500
|
irc: int = field(metadata=metadata(1))
|
|
6454
6501
|
max_pdu: int = field(metadata=metadata(2))
|
|
6455
6502
|
iso_interval: int = field(metadata=metadata(2))
|
|
6456
|
-
connection_handle: int = field(
|
|
6503
|
+
connection_handle: Sequence[int] = field(
|
|
6504
|
+
metadata=metadata(2, list_begin=True, list_end=True)
|
|
6505
|
+
)
|
|
6457
6506
|
|
|
6458
6507
|
|
|
6459
6508
|
# -----------------------------------------------------------------------------
|
bumble/helpers.py
CHANGED
|
@@ -17,43 +17,36 @@
|
|
|
17
17
|
# -----------------------------------------------------------------------------
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
from collections.abc import Callable, MutableMapping
|
|
21
20
|
import datetime
|
|
22
|
-
from typing import cast, Any, Optional
|
|
23
21
|
import logging
|
|
22
|
+
from collections.abc import Callable, MutableMapping
|
|
23
|
+
from typing import Any, Optional, cast
|
|
24
24
|
|
|
25
|
-
from bumble import avc
|
|
26
|
-
from bumble import avctp
|
|
27
|
-
from bumble import avdtp
|
|
28
|
-
from bumble import avrcp
|
|
29
|
-
from bumble import crypto
|
|
30
|
-
from bumble import rfcomm
|
|
31
|
-
from bumble import sdp
|
|
32
|
-
from bumble.colors import color
|
|
25
|
+
from bumble import avc, avctp, avdtp, avrcp, crypto, rfcomm, sdp
|
|
33
26
|
from bumble.att import ATT_CID, ATT_PDU
|
|
34
|
-
from bumble.
|
|
27
|
+
from bumble.colors import color
|
|
35
28
|
from bumble.core import name_or_number
|
|
36
|
-
from bumble.l2cap import (
|
|
37
|
-
CommandCode,
|
|
38
|
-
L2CAP_PDU,
|
|
39
|
-
L2CAP_SIGNALING_CID,
|
|
40
|
-
L2CAP_LE_SIGNALING_CID,
|
|
41
|
-
L2CAP_Control_Frame,
|
|
42
|
-
L2CAP_Connection_Request,
|
|
43
|
-
L2CAP_Connection_Response,
|
|
44
|
-
)
|
|
45
29
|
from bumble.hci import (
|
|
46
|
-
Address,
|
|
47
|
-
HCI_EVENT_PACKET,
|
|
48
30
|
HCI_ACL_DATA_PACKET,
|
|
49
31
|
HCI_DISCONNECTION_COMPLETE_EVENT,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
HCI_Event,
|
|
32
|
+
HCI_EVENT_PACKET,
|
|
33
|
+
Address,
|
|
53
34
|
HCI_AclDataPacket,
|
|
35
|
+
HCI_AclDataPacketAssembler,
|
|
54
36
|
HCI_Disconnection_Complete_Event,
|
|
37
|
+
HCI_Event,
|
|
38
|
+
HCI_Packet,
|
|
55
39
|
)
|
|
56
|
-
|
|
40
|
+
from bumble.l2cap import (
|
|
41
|
+
L2CAP_LE_SIGNALING_CID,
|
|
42
|
+
L2CAP_PDU,
|
|
43
|
+
L2CAP_SIGNALING_CID,
|
|
44
|
+
CommandCode,
|
|
45
|
+
L2CAP_Connection_Request,
|
|
46
|
+
L2CAP_Connection_Response,
|
|
47
|
+
L2CAP_Control_Frame,
|
|
48
|
+
)
|
|
49
|
+
from bumble.smp import SMP_CID, SMP_Command
|
|
57
50
|
|
|
58
51
|
# -----------------------------------------------------------------------------
|
|
59
52
|
# Logging
|
bumble/hfp.py
CHANGED
|
@@ -17,45 +17,34 @@
|
|
|
17
17
|
# -----------------------------------------------------------------------------
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
+
import asyncio
|
|
20
21
|
import collections
|
|
21
22
|
import collections.abc
|
|
22
|
-
import logging
|
|
23
|
-
import asyncio
|
|
24
23
|
import dataclasses
|
|
25
24
|
import enum
|
|
26
|
-
import
|
|
25
|
+
import logging
|
|
27
26
|
import re
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Optional,
|
|
32
|
-
ClassVar,
|
|
33
|
-
Iterable,
|
|
34
|
-
TYPE_CHECKING,
|
|
35
|
-
)
|
|
27
|
+
import traceback
|
|
28
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Iterable, Optional, Union
|
|
29
|
+
|
|
36
30
|
from typing_extensions import Self
|
|
37
31
|
|
|
38
|
-
from bumble import at
|
|
39
|
-
from bumble import device
|
|
40
|
-
from bumble import rfcomm
|
|
41
|
-
from bumble import sdp
|
|
42
|
-
from bumble import utils
|
|
32
|
+
from bumble import at, device, rfcomm, sdp, utils
|
|
43
33
|
from bumble.colors import color
|
|
44
34
|
from bumble.core import (
|
|
45
|
-
ProtocolError,
|
|
46
35
|
BT_GENERIC_AUDIO_SERVICE,
|
|
47
|
-
BT_HANDSFREE_SERVICE,
|
|
48
36
|
BT_HANDSFREE_AUDIO_GATEWAY_SERVICE,
|
|
37
|
+
BT_HANDSFREE_SERVICE,
|
|
49
38
|
BT_L2CAP_PROTOCOL_ID,
|
|
50
39
|
BT_RFCOMM_PROTOCOL_ID,
|
|
40
|
+
ProtocolError,
|
|
51
41
|
)
|
|
52
42
|
from bumble.hci import (
|
|
53
|
-
HCI_Enhanced_Setup_Synchronous_Connection_Command,
|
|
54
|
-
CodingFormat,
|
|
55
43
|
CodecID,
|
|
44
|
+
CodingFormat,
|
|
45
|
+
HCI_Enhanced_Setup_Synchronous_Connection_Command,
|
|
56
46
|
)
|
|
57
47
|
|
|
58
|
-
|
|
59
48
|
# -----------------------------------------------------------------------------
|
|
60
49
|
# Logging
|
|
61
50
|
# -----------------------------------------------------------------------------
|
bumble/hid.py
CHANGED
|
@@ -16,22 +16,20 @@
|
|
|
16
16
|
# Imports
|
|
17
17
|
# -----------------------------------------------------------------------------
|
|
18
18
|
from __future__ import annotations
|
|
19
|
-
|
|
20
|
-
import logging
|
|
19
|
+
|
|
21
20
|
import enum
|
|
21
|
+
import logging
|
|
22
22
|
import struct
|
|
23
|
-
|
|
24
23
|
from abc import ABC, abstractmethod
|
|
25
|
-
from
|
|
24
|
+
from dataclasses import dataclass
|
|
25
|
+
from typing import Callable, Optional
|
|
26
|
+
|
|
26
27
|
from typing_extensions import override
|
|
27
28
|
|
|
28
|
-
from bumble import l2cap
|
|
29
|
-
from bumble import device
|
|
30
|
-
from bumble import utils
|
|
29
|
+
from bumble import device, l2cap, utils
|
|
31
30
|
from bumble.core import InvalidStateError, ProtocolError
|
|
32
31
|
from bumble.hci import Address
|
|
33
32
|
|
|
34
|
-
|
|
35
33
|
# -----------------------------------------------------------------------------
|
|
36
34
|
# Logging
|
|
37
35
|
# -----------------------------------------------------------------------------
|
|
@@ -219,33 +217,41 @@ class HID(ABC, utils.EventEmitter):
|
|
|
219
217
|
self.role = role
|
|
220
218
|
|
|
221
219
|
# Register ourselves with the L2CAP channel manager
|
|
222
|
-
device.
|
|
223
|
-
|
|
220
|
+
device.create_l2cap_server(
|
|
221
|
+
l2cap.ClassicChannelSpec(HID_CONTROL_PSM), self.on_l2cap_connection
|
|
222
|
+
)
|
|
223
|
+
device.create_l2cap_server(
|
|
224
|
+
l2cap.ClassicChannelSpec(HID_INTERRUPT_PSM), self.on_l2cap_connection
|
|
225
|
+
)
|
|
224
226
|
|
|
225
227
|
device.on(device.EVENT_CONNECTION, self.on_device_connection)
|
|
226
228
|
|
|
227
229
|
async def connect_control_channel(self) -> None:
|
|
230
|
+
if not self.connection:
|
|
231
|
+
raise InvalidStateError("Connection is not established!")
|
|
228
232
|
# Create a new L2CAP connection - control channel
|
|
229
233
|
try:
|
|
230
|
-
channel = await self.
|
|
231
|
-
|
|
234
|
+
channel = await self.connection.create_l2cap_channel(
|
|
235
|
+
l2cap.ClassicChannelSpec(HID_CONTROL_PSM)
|
|
232
236
|
)
|
|
233
237
|
channel.sink = self.on_ctrl_pdu
|
|
234
238
|
self.l2cap_ctrl_channel = channel
|
|
235
239
|
except ProtocolError:
|
|
236
|
-
logging.exception(
|
|
240
|
+
logging.exception('L2CAP connection failed.')
|
|
237
241
|
raise
|
|
238
242
|
|
|
239
243
|
async def connect_interrupt_channel(self) -> None:
|
|
244
|
+
if not self.connection:
|
|
245
|
+
raise InvalidStateError("Connection is not established!")
|
|
240
246
|
# Create a new L2CAP connection - interrupt channel
|
|
241
247
|
try:
|
|
242
|
-
channel = await self.
|
|
243
|
-
|
|
248
|
+
channel = await self.connection.create_l2cap_channel(
|
|
249
|
+
l2cap.ClassicChannelSpec(HID_CONTROL_PSM)
|
|
244
250
|
)
|
|
245
251
|
channel.sink = self.on_intr_pdu
|
|
246
252
|
self.l2cap_intr_channel = channel
|
|
247
253
|
except ProtocolError:
|
|
248
|
-
logging.exception(
|
|
254
|
+
logging.exception('L2CAP connection failed.')
|
|
249
255
|
raise
|
|
250
256
|
|
|
251
257
|
async def disconnect_interrupt_channel(self) -> None:
|