bumble 0.0.213__py3-none-any.whl → 0.0.215__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 +14 -38
- bumble/apps/bench.py +10 -15
- bumble/apps/ble_rpa_tool.py +1 -0
- bumble/apps/console.py +22 -25
- bumble/apps/controller_info.py +20 -25
- bumble/apps/controller_loopback.py +6 -10
- bumble/apps/controllers.py +2 -3
- bumble/apps/device_info.py +4 -5
- bumble/apps/gatt_dump.py +3 -3
- bumble/apps/gg_bridge.py +7 -8
- bumble/apps/hci_bridge.py +4 -3
- bumble/apps/l2cap_bridge.py +5 -5
- bumble/apps/lea_unicast/app.py +16 -26
- bumble/apps/pair.py +30 -43
- bumble/apps/pandora_server.py +5 -4
- bumble/apps/player/player.py +20 -24
- bumble/apps/rfcomm_bridge.py +4 -10
- bumble/apps/scan.py +17 -8
- bumble/apps/show.py +4 -5
- bumble/apps/speaker/speaker.py +23 -27
- bumble/apps/unbond.py +3 -3
- bumble/apps/usb_probe.py +2 -4
- 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 +1097 -589
- bumble/codecs.py +2 -0
- bumble/controller.py +142 -35
- 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 +319 -267
- 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 +114 -18
- bumble/helpers.py +19 -26
- bumble/hfp.py +10 -21
- bumble/hid.py +22 -16
- bumble/host.py +191 -103
- bumble/keys.py +5 -3
- bumble/l2cap.py +138 -104
- bumble/link.py +18 -19
- bumble/logging.py +65 -0
- bumble/pairing.py +7 -6
- bumble/pandora/__init__.py +9 -8
- 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 +403 -0
- bumble/profiles/ancs.py +6 -7
- bumble/profiles/ascs.py +14 -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 +151 -159
- 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 +5 -4
- bumble/tools/rtk_fw_download.py +6 -3
- bumble/tools/rtk_util.py +26 -8
- 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.213.dist-info → bumble-0.0.215.dist-info}/METADATA +4 -2
- bumble-0.0.215.dist-info/RECORD +183 -0
- bumble-0.0.213.dist-info/RECORD +0 -180
- {bumble-0.0.213.dist-info → bumble-0.0.215.dist-info}/WHEEL +0 -0
- {bumble-0.0.213.dist-info → bumble-0.0.215.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.213.dist-info → bumble-0.0.215.dist-info}/licenses/LICENSE +0 -0
- {bumble-0.0.213.dist-info → bumble-0.0.215.dist-info}/top_level.txt +0 -0
bumble/att.py
CHANGED
|
@@ -24,24 +24,26 @@
|
|
|
24
24
|
# -----------------------------------------------------------------------------
|
|
25
25
|
from __future__ import annotations
|
|
26
26
|
|
|
27
|
+
import dataclasses
|
|
27
28
|
import enum
|
|
28
29
|
import functools
|
|
29
30
|
import inspect
|
|
30
31
|
import struct
|
|
31
32
|
from typing import (
|
|
33
|
+
TYPE_CHECKING,
|
|
32
34
|
Awaitable,
|
|
33
35
|
Callable,
|
|
36
|
+
ClassVar,
|
|
34
37
|
Generic,
|
|
38
|
+
Optional,
|
|
35
39
|
TypeVar,
|
|
36
40
|
Union,
|
|
37
|
-
TYPE_CHECKING,
|
|
38
41
|
)
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
from bumble import utils
|
|
42
|
-
from bumble.core import UUID, name_or_number, InvalidOperationError, ProtocolError
|
|
43
|
-
from bumble.hci import HCI_Object, key_with_value
|
|
43
|
+
from bumble import hci, utils
|
|
44
44
|
from bumble.colors import color
|
|
45
|
+
from bumble.core import UUID, InvalidOperationError, ProtocolError
|
|
46
|
+
from bumble.hci import HCI_Object
|
|
45
47
|
|
|
46
48
|
# -----------------------------------------------------------------------------
|
|
47
49
|
# Typing
|
|
@@ -60,96 +62,66 @@ _T = TypeVar('_T')
|
|
|
60
62
|
ATT_CID = 0x04
|
|
61
63
|
ATT_PSM = 0x001F
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
ATT_PDU_NAMES = {
|
|
93
|
-
ATT_ERROR_RESPONSE: 'ATT_ERROR_RESPONSE',
|
|
94
|
-
ATT_EXCHANGE_MTU_REQUEST: 'ATT_EXCHANGE_MTU_REQUEST',
|
|
95
|
-
ATT_EXCHANGE_MTU_RESPONSE: 'ATT_EXCHANGE_MTU_RESPONSE',
|
|
96
|
-
ATT_FIND_INFORMATION_REQUEST: 'ATT_FIND_INFORMATION_REQUEST',
|
|
97
|
-
ATT_FIND_INFORMATION_RESPONSE: 'ATT_FIND_INFORMATION_RESPONSE',
|
|
98
|
-
ATT_FIND_BY_TYPE_VALUE_REQUEST: 'ATT_FIND_BY_TYPE_VALUE_REQUEST',
|
|
99
|
-
ATT_FIND_BY_TYPE_VALUE_RESPONSE: 'ATT_FIND_BY_TYPE_VALUE_RESPONSE',
|
|
100
|
-
ATT_READ_BY_TYPE_REQUEST: 'ATT_READ_BY_TYPE_REQUEST',
|
|
101
|
-
ATT_READ_BY_TYPE_RESPONSE: 'ATT_READ_BY_TYPE_RESPONSE',
|
|
102
|
-
ATT_READ_REQUEST: 'ATT_READ_REQUEST',
|
|
103
|
-
ATT_READ_RESPONSE: 'ATT_READ_RESPONSE',
|
|
104
|
-
ATT_READ_BLOB_REQUEST: 'ATT_READ_BLOB_REQUEST',
|
|
105
|
-
ATT_READ_BLOB_RESPONSE: 'ATT_READ_BLOB_RESPONSE',
|
|
106
|
-
ATT_READ_MULTIPLE_REQUEST: 'ATT_READ_MULTIPLE_REQUEST',
|
|
107
|
-
ATT_READ_MULTIPLE_RESPONSE: 'ATT_READ_MULTIPLE_RESPONSE',
|
|
108
|
-
ATT_READ_BY_GROUP_TYPE_REQUEST: 'ATT_READ_BY_GROUP_TYPE_REQUEST',
|
|
109
|
-
ATT_READ_BY_GROUP_TYPE_RESPONSE: 'ATT_READ_BY_GROUP_TYPE_RESPONSE',
|
|
110
|
-
ATT_WRITE_REQUEST: 'ATT_WRITE_REQUEST',
|
|
111
|
-
ATT_WRITE_RESPONSE: 'ATT_WRITE_RESPONSE',
|
|
112
|
-
ATT_WRITE_COMMAND: 'ATT_WRITE_COMMAND',
|
|
113
|
-
ATT_SIGNED_WRITE_COMMAND: 'ATT_SIGNED_WRITE_COMMAND',
|
|
114
|
-
ATT_PREPARE_WRITE_REQUEST: 'ATT_PREPARE_WRITE_REQUEST',
|
|
115
|
-
ATT_PREPARE_WRITE_RESPONSE: 'ATT_PREPARE_WRITE_RESPONSE',
|
|
116
|
-
ATT_EXECUTE_WRITE_REQUEST: 'ATT_EXECUTE_WRITE_REQUEST',
|
|
117
|
-
ATT_EXECUTE_WRITE_RESPONSE: 'ATT_EXECUTE_WRITE_RESPONSE',
|
|
118
|
-
ATT_HANDLE_VALUE_NOTIFICATION: 'ATT_HANDLE_VALUE_NOTIFICATION',
|
|
119
|
-
ATT_HANDLE_VALUE_INDICATION: 'ATT_HANDLE_VALUE_INDICATION',
|
|
120
|
-
ATT_HANDLE_VALUE_CONFIRMATION: 'ATT_HANDLE_VALUE_CONFIRMATION'
|
|
121
|
-
}
|
|
65
|
+
class Opcode(hci.SpecableEnum):
|
|
66
|
+
ATT_ERROR_RESPONSE = 0x01
|
|
67
|
+
ATT_EXCHANGE_MTU_REQUEST = 0x02
|
|
68
|
+
ATT_EXCHANGE_MTU_RESPONSE = 0x03
|
|
69
|
+
ATT_FIND_INFORMATION_REQUEST = 0x04
|
|
70
|
+
ATT_FIND_INFORMATION_RESPONSE = 0x05
|
|
71
|
+
ATT_FIND_BY_TYPE_VALUE_REQUEST = 0x06
|
|
72
|
+
ATT_FIND_BY_TYPE_VALUE_RESPONSE = 0x07
|
|
73
|
+
ATT_READ_BY_TYPE_REQUEST = 0x08
|
|
74
|
+
ATT_READ_BY_TYPE_RESPONSE = 0x09
|
|
75
|
+
ATT_READ_REQUEST = 0x0A
|
|
76
|
+
ATT_READ_RESPONSE = 0x0B
|
|
77
|
+
ATT_READ_BLOB_REQUEST = 0x0C
|
|
78
|
+
ATT_READ_BLOB_RESPONSE = 0x0D
|
|
79
|
+
ATT_READ_MULTIPLE_REQUEST = 0x0E
|
|
80
|
+
ATT_READ_MULTIPLE_RESPONSE = 0x0F
|
|
81
|
+
ATT_READ_BY_GROUP_TYPE_REQUEST = 0x10
|
|
82
|
+
ATT_READ_BY_GROUP_TYPE_RESPONSE = 0x11
|
|
83
|
+
ATT_WRITE_REQUEST = 0x12
|
|
84
|
+
ATT_WRITE_RESPONSE = 0x13
|
|
85
|
+
ATT_WRITE_COMMAND = 0x52
|
|
86
|
+
ATT_SIGNED_WRITE_COMMAND = 0xD2
|
|
87
|
+
ATT_PREPARE_WRITE_REQUEST = 0x16
|
|
88
|
+
ATT_PREPARE_WRITE_RESPONSE = 0x17
|
|
89
|
+
ATT_EXECUTE_WRITE_REQUEST = 0x18
|
|
90
|
+
ATT_EXECUTE_WRITE_RESPONSE = 0x19
|
|
91
|
+
ATT_HANDLE_VALUE_NOTIFICATION = 0x1B
|
|
92
|
+
ATT_HANDLE_VALUE_INDICATION = 0x1D
|
|
93
|
+
ATT_HANDLE_VALUE_CONFIRMATION = 0x1E
|
|
122
94
|
|
|
123
95
|
ATT_REQUESTS = [
|
|
124
|
-
ATT_EXCHANGE_MTU_REQUEST,
|
|
125
|
-
ATT_FIND_INFORMATION_REQUEST,
|
|
126
|
-
ATT_FIND_BY_TYPE_VALUE_REQUEST,
|
|
127
|
-
ATT_READ_BY_TYPE_REQUEST,
|
|
128
|
-
ATT_READ_REQUEST,
|
|
129
|
-
ATT_READ_BLOB_REQUEST,
|
|
130
|
-
ATT_READ_MULTIPLE_REQUEST,
|
|
131
|
-
ATT_READ_BY_GROUP_TYPE_REQUEST,
|
|
132
|
-
ATT_WRITE_REQUEST,
|
|
133
|
-
ATT_PREPARE_WRITE_REQUEST,
|
|
134
|
-
ATT_EXECUTE_WRITE_REQUEST
|
|
96
|
+
Opcode.ATT_EXCHANGE_MTU_REQUEST,
|
|
97
|
+
Opcode.ATT_FIND_INFORMATION_REQUEST,
|
|
98
|
+
Opcode.ATT_FIND_BY_TYPE_VALUE_REQUEST,
|
|
99
|
+
Opcode.ATT_READ_BY_TYPE_REQUEST,
|
|
100
|
+
Opcode.ATT_READ_REQUEST,
|
|
101
|
+
Opcode.ATT_READ_BLOB_REQUEST,
|
|
102
|
+
Opcode.ATT_READ_MULTIPLE_REQUEST,
|
|
103
|
+
Opcode.ATT_READ_BY_GROUP_TYPE_REQUEST,
|
|
104
|
+
Opcode.ATT_WRITE_REQUEST,
|
|
105
|
+
Opcode.ATT_PREPARE_WRITE_REQUEST,
|
|
106
|
+
Opcode.ATT_EXECUTE_WRITE_REQUEST
|
|
135
107
|
]
|
|
136
108
|
|
|
137
109
|
ATT_RESPONSES = [
|
|
138
|
-
ATT_ERROR_RESPONSE,
|
|
139
|
-
ATT_EXCHANGE_MTU_RESPONSE,
|
|
140
|
-
ATT_FIND_INFORMATION_RESPONSE,
|
|
141
|
-
ATT_FIND_BY_TYPE_VALUE_RESPONSE,
|
|
142
|
-
ATT_READ_BY_TYPE_RESPONSE,
|
|
143
|
-
ATT_READ_RESPONSE,
|
|
144
|
-
ATT_READ_BLOB_RESPONSE,
|
|
145
|
-
ATT_READ_MULTIPLE_RESPONSE,
|
|
146
|
-
ATT_READ_BY_GROUP_TYPE_RESPONSE,
|
|
147
|
-
ATT_WRITE_RESPONSE,
|
|
148
|
-
ATT_PREPARE_WRITE_RESPONSE,
|
|
149
|
-
ATT_EXECUTE_WRITE_RESPONSE
|
|
110
|
+
Opcode.ATT_ERROR_RESPONSE,
|
|
111
|
+
Opcode.ATT_EXCHANGE_MTU_RESPONSE,
|
|
112
|
+
Opcode.ATT_FIND_INFORMATION_RESPONSE,
|
|
113
|
+
Opcode.ATT_FIND_BY_TYPE_VALUE_RESPONSE,
|
|
114
|
+
Opcode.ATT_READ_BY_TYPE_RESPONSE,
|
|
115
|
+
Opcode.ATT_READ_RESPONSE,
|
|
116
|
+
Opcode.ATT_READ_BLOB_RESPONSE,
|
|
117
|
+
Opcode.ATT_READ_MULTIPLE_RESPONSE,
|
|
118
|
+
Opcode.ATT_READ_BY_GROUP_TYPE_RESPONSE,
|
|
119
|
+
Opcode.ATT_WRITE_RESPONSE,
|
|
120
|
+
Opcode.ATT_PREPARE_WRITE_RESPONSE,
|
|
121
|
+
Opcode.ATT_EXECUTE_WRITE_RESPONSE
|
|
150
122
|
]
|
|
151
123
|
|
|
152
|
-
class ErrorCode(
|
|
124
|
+
class ErrorCode(hci.SpecableEnum):
|
|
153
125
|
'''
|
|
154
126
|
See
|
|
155
127
|
|
|
@@ -204,10 +176,6 @@ ATT_INSUFFICIENT_RESOURCES_ERROR = ErrorCode.INSUFFICIENT_RESOURCES
|
|
|
204
176
|
ATT_DEFAULT_MTU = 23
|
|
205
177
|
|
|
206
178
|
HANDLE_FIELD_SPEC = {'size': 2, 'mapper': lambda x: f'0x{x:04X}'}
|
|
207
|
-
# pylint: disable-next=unnecessary-lambda-assignment,unnecessary-lambda
|
|
208
|
-
UUID_2_16_FIELD_SPEC = lambda x, y: UUID.parse_uuid(x, y)
|
|
209
|
-
# pylint: disable-next=unnecessary-lambda-assignment,unnecessary-lambda
|
|
210
|
-
UUID_2_FIELD_SPEC = lambda x, y: UUID.parse_uuid_2(x, y) # noqa: E731
|
|
211
179
|
|
|
212
180
|
# fmt: on
|
|
213
181
|
# pylint: enable=line-too-long
|
|
@@ -227,7 +195,7 @@ class ATT_Error(ProtocolError):
|
|
|
227
195
|
super().__init__(
|
|
228
196
|
error_code,
|
|
229
197
|
error_namespace='att',
|
|
230
|
-
error_name=
|
|
198
|
+
error_name=ErrorCode(error_code).name,
|
|
231
199
|
)
|
|
232
200
|
self.att_handle = att_handle
|
|
233
201
|
self.message = message
|
|
@@ -242,61 +210,45 @@ class ATT_Error(ProtocolError):
|
|
|
242
210
|
# -----------------------------------------------------------------------------
|
|
243
211
|
# Attribute Protocol
|
|
244
212
|
# -----------------------------------------------------------------------------
|
|
213
|
+
@dataclasses.dataclass
|
|
245
214
|
class ATT_PDU:
|
|
246
215
|
'''
|
|
247
216
|
See Bluetooth spec @ Vol 3, Part F - 3.3 ATTRIBUTE PDU
|
|
248
217
|
'''
|
|
249
218
|
|
|
250
|
-
pdu_classes: dict[int, type[ATT_PDU]] = {}
|
|
251
|
-
|
|
252
|
-
|
|
219
|
+
pdu_classes: ClassVar[dict[int, type[ATT_PDU]]] = {}
|
|
220
|
+
fields: ClassVar[hci.Fields] = ()
|
|
221
|
+
op_code: int = dataclasses.field(init=False)
|
|
222
|
+
name: str = dataclasses.field(init=False)
|
|
223
|
+
_payload: Optional[bytes] = dataclasses.field(default=None, init=False)
|
|
253
224
|
|
|
254
|
-
@
|
|
255
|
-
def from_bytes(pdu):
|
|
225
|
+
@classmethod
|
|
226
|
+
def from_bytes(cls, pdu: bytes) -> ATT_PDU:
|
|
256
227
|
op_code = pdu[0]
|
|
257
228
|
|
|
258
|
-
|
|
259
|
-
if
|
|
260
|
-
instance = ATT_PDU(
|
|
261
|
-
instance.name = ATT_PDU.pdu_name(op_code)
|
|
229
|
+
subclass = ATT_PDU.pdu_classes.get(op_code)
|
|
230
|
+
if subclass is None:
|
|
231
|
+
instance = ATT_PDU()
|
|
262
232
|
instance.op_code = op_code
|
|
233
|
+
instance.payload = pdu[1:]
|
|
234
|
+
instance.name = Opcode(op_code).name
|
|
263
235
|
return instance
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
self.init_from_bytes(pdu, 1)
|
|
268
|
-
return self
|
|
236
|
+
instance = subclass(**HCI_Object.dict_from_bytes(pdu, 1, subclass.fields))
|
|
237
|
+
instance.payload = pdu[1:]
|
|
238
|
+
return instance
|
|
269
239
|
|
|
270
|
-
|
|
271
|
-
def pdu_name(op_code):
|
|
272
|
-
return name_or_number(ATT_PDU_NAMES, op_code, 2)
|
|
240
|
+
_PDU = TypeVar("_PDU", bound="ATT_PDU")
|
|
273
241
|
|
|
274
242
|
@classmethod
|
|
275
|
-
def
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
def subclass(fields):
|
|
280
|
-
def inner(cls):
|
|
281
|
-
cls.name = cls.__name__.upper()
|
|
282
|
-
cls.op_code = key_with_value(ATT_PDU_NAMES, cls.name)
|
|
283
|
-
if cls.op_code is None:
|
|
284
|
-
raise KeyError(f'PDU name {cls.name} not found in ATT_PDU_NAMES')
|
|
285
|
-
cls.fields = fields
|
|
286
|
-
|
|
287
|
-
# Register a factory for this class
|
|
288
|
-
ATT_PDU.pdu_classes[cls.op_code] = cls
|
|
289
|
-
|
|
290
|
-
return cls
|
|
243
|
+
def subclass(cls, subclass: type[_PDU]) -> type[_PDU]:
|
|
244
|
+
subclass.name = subclass.__name__.upper()
|
|
245
|
+
subclass.op_code = Opcode[subclass.name]
|
|
246
|
+
subclass.fields = HCI_Object.fields_from_dataclass(subclass)
|
|
291
247
|
|
|
292
|
-
|
|
248
|
+
# Register a factory for this class
|
|
249
|
+
ATT_PDU.pdu_classes[subclass.op_code] = subclass
|
|
293
250
|
|
|
294
|
-
|
|
295
|
-
if hasattr(self, 'fields') and kwargs:
|
|
296
|
-
HCI_Object.init_from_fields(self, self.fields, kwargs)
|
|
297
|
-
if pdu is None:
|
|
298
|
-
pdu = bytes([self.op_code]) + HCI_Object.dict_to_bytes(kwargs, self.fields)
|
|
299
|
-
self.pdu = pdu
|
|
251
|
+
return subclass
|
|
300
252
|
|
|
301
253
|
def init_from_bytes(self, pdu, offset):
|
|
302
254
|
return HCI_Object.init_from_bytes(self, pdu, offset, self.fields)
|
|
@@ -309,67 +261,91 @@ class ATT_PDU:
|
|
|
309
261
|
def has_authentication_signature(self):
|
|
310
262
|
return ((self.op_code >> 7) & 1) == 1
|
|
311
263
|
|
|
312
|
-
|
|
313
|
-
|
|
264
|
+
@property
|
|
265
|
+
def payload(self) -> bytes:
|
|
266
|
+
if self._payload is None:
|
|
267
|
+
self._payload = HCI_Object.dict_to_bytes(self.__dict__, self.fields)
|
|
268
|
+
return self._payload
|
|
269
|
+
|
|
270
|
+
@payload.setter
|
|
271
|
+
def payload(self, value: bytes):
|
|
272
|
+
self._payload = value
|
|
273
|
+
|
|
274
|
+
def __bytes__(self) -> bytes:
|
|
275
|
+
return bytes([self.op_code]) + self.payload
|
|
314
276
|
|
|
315
277
|
def __str__(self):
|
|
316
278
|
result = color(self.name, 'yellow')
|
|
317
279
|
if fields := getattr(self, 'fields', None):
|
|
318
280
|
result += ':\n' + HCI_Object.format_fields(self.__dict__, fields, ' ')
|
|
319
281
|
else:
|
|
320
|
-
if
|
|
321
|
-
result += f': {self.
|
|
282
|
+
if self.payload:
|
|
283
|
+
result += f': {self.payload.hex()}'
|
|
322
284
|
return result
|
|
323
285
|
|
|
324
286
|
|
|
325
287
|
# -----------------------------------------------------------------------------
|
|
326
|
-
@ATT_PDU.subclass
|
|
327
|
-
|
|
328
|
-
('request_opcode_in_error', {'size': 1, 'mapper': ATT_PDU.pdu_name}),
|
|
329
|
-
('attribute_handle_in_error', HANDLE_FIELD_SPEC),
|
|
330
|
-
('error_code', {'size': 1, 'mapper': ATT_PDU.error_name}),
|
|
331
|
-
]
|
|
332
|
-
)
|
|
288
|
+
@ATT_PDU.subclass
|
|
289
|
+
@dataclasses.dataclass
|
|
333
290
|
class ATT_Error_Response(ATT_PDU):
|
|
334
291
|
'''
|
|
335
292
|
See Bluetooth spec @ Vol 3, Part F - 3.4.1.1 Error Response
|
|
336
293
|
'''
|
|
337
294
|
|
|
295
|
+
request_opcode_in_error: int = dataclasses.field(metadata=Opcode.type_metadata(1))
|
|
296
|
+
attribute_handle_in_error: int = dataclasses.field(
|
|
297
|
+
metadata=hci.metadata(HANDLE_FIELD_SPEC)
|
|
298
|
+
)
|
|
299
|
+
error_code: int = dataclasses.field(metadata=ErrorCode.type_metadata(1))
|
|
300
|
+
|
|
338
301
|
|
|
339
302
|
# -----------------------------------------------------------------------------
|
|
340
|
-
@ATT_PDU.subclass
|
|
303
|
+
@ATT_PDU.subclass
|
|
304
|
+
@dataclasses.dataclass
|
|
341
305
|
class ATT_Exchange_MTU_Request(ATT_PDU):
|
|
342
306
|
'''
|
|
343
307
|
See Bluetooth spec @ Vol 3, Part F - 3.4.2.1 Exchange MTU Request
|
|
344
308
|
'''
|
|
345
309
|
|
|
310
|
+
client_rx_mtu: int = dataclasses.field(metadata=hci.metadata(2))
|
|
311
|
+
|
|
346
312
|
|
|
347
313
|
# -----------------------------------------------------------------------------
|
|
348
|
-
@ATT_PDU.subclass
|
|
314
|
+
@ATT_PDU.subclass
|
|
315
|
+
@dataclasses.dataclass
|
|
349
316
|
class ATT_Exchange_MTU_Response(ATT_PDU):
|
|
350
317
|
'''
|
|
351
318
|
See Bluetooth spec @ Vol 3, Part F - 3.4.2.2 Exchange MTU Response
|
|
352
319
|
'''
|
|
353
320
|
|
|
321
|
+
server_rx_mtu: int = dataclasses.field(metadata=hci.metadata(2))
|
|
322
|
+
|
|
354
323
|
|
|
355
324
|
# -----------------------------------------------------------------------------
|
|
356
|
-
@ATT_PDU.subclass
|
|
357
|
-
|
|
358
|
-
)
|
|
325
|
+
@ATT_PDU.subclass
|
|
326
|
+
@dataclasses.dataclass
|
|
359
327
|
class ATT_Find_Information_Request(ATT_PDU):
|
|
360
328
|
'''
|
|
361
329
|
See Bluetooth spec @ Vol 3, Part F - 3.4.3.1 Find Information Request
|
|
362
330
|
'''
|
|
363
331
|
|
|
332
|
+
starting_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
333
|
+
ending_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
334
|
+
|
|
364
335
|
|
|
365
336
|
# -----------------------------------------------------------------------------
|
|
366
|
-
@ATT_PDU.subclass
|
|
337
|
+
@ATT_PDU.subclass
|
|
338
|
+
@dataclasses.dataclass
|
|
367
339
|
class ATT_Find_Information_Response(ATT_PDU):
|
|
368
340
|
'''
|
|
369
341
|
See Bluetooth spec @ Vol 3, Part F - 3.4.3.2 Find Information Response
|
|
370
342
|
'''
|
|
371
343
|
|
|
372
|
-
|
|
344
|
+
format: int = dataclasses.field(metadata=hci.metadata(1))
|
|
345
|
+
information_data: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
346
|
+
information: list[tuple[int, bytes]] = dataclasses.field(init=False)
|
|
347
|
+
|
|
348
|
+
def __post_init__(self) -> None:
|
|
373
349
|
self.information = []
|
|
374
350
|
offset = 0
|
|
375
351
|
uuid_size = 2 if self.format == 1 else 16
|
|
@@ -379,14 +355,6 @@ class ATT_Find_Information_Response(ATT_PDU):
|
|
|
379
355
|
self.information.append((handle, uuid))
|
|
380
356
|
offset += 2 + uuid_size
|
|
381
357
|
|
|
382
|
-
def __init__(self, *args, **kwargs):
|
|
383
|
-
super().__init__(*args, **kwargs)
|
|
384
|
-
self.parse_information_data()
|
|
385
|
-
|
|
386
|
-
def init_from_bytes(self, pdu, offset):
|
|
387
|
-
super().init_from_bytes(pdu, offset)
|
|
388
|
-
self.parse_information_data()
|
|
389
|
-
|
|
390
358
|
def __str__(self):
|
|
391
359
|
result = color(self.name, 'yellow')
|
|
392
360
|
result += ':\n' + HCI_Object.format_fields(
|
|
@@ -408,28 +376,31 @@ class ATT_Find_Information_Response(ATT_PDU):
|
|
|
408
376
|
|
|
409
377
|
|
|
410
378
|
# -----------------------------------------------------------------------------
|
|
411
|
-
@ATT_PDU.subclass
|
|
412
|
-
|
|
413
|
-
('starting_handle', HANDLE_FIELD_SPEC),
|
|
414
|
-
('ending_handle', HANDLE_FIELD_SPEC),
|
|
415
|
-
('attribute_type', UUID_2_FIELD_SPEC),
|
|
416
|
-
('attribute_value', '*'),
|
|
417
|
-
]
|
|
418
|
-
)
|
|
379
|
+
@ATT_PDU.subclass
|
|
380
|
+
@dataclasses.dataclass
|
|
419
381
|
class ATT_Find_By_Type_Value_Request(ATT_PDU):
|
|
420
382
|
'''
|
|
421
383
|
See Bluetooth spec @ Vol 3, Part F - 3.4.3.3 Find By Type Value Request
|
|
422
384
|
'''
|
|
423
385
|
|
|
386
|
+
starting_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
387
|
+
ending_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
388
|
+
attribute_type: UUID = dataclasses.field(metadata=hci.metadata(UUID.parse_uuid_2))
|
|
389
|
+
attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
390
|
+
|
|
424
391
|
|
|
425
392
|
# -----------------------------------------------------------------------------
|
|
426
|
-
@ATT_PDU.subclass
|
|
393
|
+
@ATT_PDU.subclass
|
|
394
|
+
@dataclasses.dataclass
|
|
427
395
|
class ATT_Find_By_Type_Value_Response(ATT_PDU):
|
|
428
396
|
'''
|
|
429
397
|
See Bluetooth spec @ Vol 3, Part F - 3.4.3.4 Find By Type Value Response
|
|
430
398
|
'''
|
|
431
399
|
|
|
432
|
-
|
|
400
|
+
handles_information_list: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
401
|
+
handles_information: list[tuple[int, int]] = dataclasses.field(init=False)
|
|
402
|
+
|
|
403
|
+
def __post_init__(self) -> None:
|
|
433
404
|
self.handles_information = []
|
|
434
405
|
offset = 0
|
|
435
406
|
while offset + 4 <= len(self.handles_information_list):
|
|
@@ -439,14 +410,6 @@ class ATT_Find_By_Type_Value_Response(ATT_PDU):
|
|
|
439
410
|
self.handles_information.append((found_attribute_handle, group_end_handle))
|
|
440
411
|
offset += 4
|
|
441
412
|
|
|
442
|
-
def __init__(self, *args, **kwargs):
|
|
443
|
-
super().__init__(*args, **kwargs)
|
|
444
|
-
self.parse_handles_information_list()
|
|
445
|
-
|
|
446
|
-
def init_from_bytes(self, pdu, offset):
|
|
447
|
-
super().init_from_bytes(pdu, offset)
|
|
448
|
-
self.parse_handles_information_list()
|
|
449
|
-
|
|
450
413
|
def __str__(self):
|
|
451
414
|
result = color(self.name, 'yellow')
|
|
452
415
|
result += ':\n' + HCI_Object.format_fields(
|
|
@@ -470,27 +433,31 @@ class ATT_Find_By_Type_Value_Response(ATT_PDU):
|
|
|
470
433
|
|
|
471
434
|
|
|
472
435
|
# -----------------------------------------------------------------------------
|
|
473
|
-
@ATT_PDU.subclass
|
|
474
|
-
|
|
475
|
-
('starting_handle', HANDLE_FIELD_SPEC),
|
|
476
|
-
('ending_handle', HANDLE_FIELD_SPEC),
|
|
477
|
-
('attribute_type', UUID_2_16_FIELD_SPEC),
|
|
478
|
-
]
|
|
479
|
-
)
|
|
436
|
+
@ATT_PDU.subclass
|
|
437
|
+
@dataclasses.dataclass
|
|
480
438
|
class ATT_Read_By_Type_Request(ATT_PDU):
|
|
481
439
|
'''
|
|
482
440
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.1 Read By Type Request
|
|
483
441
|
'''
|
|
484
442
|
|
|
443
|
+
starting_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
444
|
+
ending_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
445
|
+
attribute_type: UUID = dataclasses.field(metadata=hci.metadata(UUID.parse_uuid))
|
|
446
|
+
|
|
485
447
|
|
|
486
448
|
# -----------------------------------------------------------------------------
|
|
487
|
-
@ATT_PDU.subclass
|
|
449
|
+
@ATT_PDU.subclass
|
|
450
|
+
@dataclasses.dataclass
|
|
488
451
|
class ATT_Read_By_Type_Response(ATT_PDU):
|
|
489
452
|
'''
|
|
490
453
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.2 Read By Type Response
|
|
491
454
|
'''
|
|
492
455
|
|
|
493
|
-
|
|
456
|
+
length: int = dataclasses.field(metadata=hci.metadata(1))
|
|
457
|
+
attribute_data_list: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
458
|
+
attributes: list[tuple[int, bytes]] = dataclasses.field(init=False)
|
|
459
|
+
|
|
460
|
+
def __post_init__(self) -> None:
|
|
494
461
|
self.attributes = []
|
|
495
462
|
offset = 0
|
|
496
463
|
while self.length != 0 and offset + self.length <= len(
|
|
@@ -505,14 +472,6 @@ class ATT_Read_By_Type_Response(ATT_PDU):
|
|
|
505
472
|
self.attributes.append((attribute_handle, attribute_value))
|
|
506
473
|
offset += self.length
|
|
507
474
|
|
|
508
|
-
def __init__(self, *args, **kwargs):
|
|
509
|
-
super().__init__(*args, **kwargs)
|
|
510
|
-
self.parse_attribute_data_list()
|
|
511
|
-
|
|
512
|
-
def init_from_bytes(self, pdu, offset):
|
|
513
|
-
super().init_from_bytes(pdu, offset)
|
|
514
|
-
self.parse_attribute_data_list()
|
|
515
|
-
|
|
516
475
|
def __str__(self):
|
|
517
476
|
result = color(self.name, 'yellow')
|
|
518
477
|
result += ':\n' + HCI_Object.format_fields(
|
|
@@ -534,75 +493,100 @@ class ATT_Read_By_Type_Response(ATT_PDU):
|
|
|
534
493
|
|
|
535
494
|
|
|
536
495
|
# -----------------------------------------------------------------------------
|
|
537
|
-
@ATT_PDU.subclass
|
|
496
|
+
@ATT_PDU.subclass
|
|
497
|
+
@dataclasses.dataclass
|
|
538
498
|
class ATT_Read_Request(ATT_PDU):
|
|
539
499
|
'''
|
|
540
500
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.3 Read Request
|
|
541
501
|
'''
|
|
542
502
|
|
|
503
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
504
|
+
|
|
543
505
|
|
|
544
506
|
# -----------------------------------------------------------------------------
|
|
545
|
-
@ATT_PDU.subclass
|
|
507
|
+
@ATT_PDU.subclass
|
|
508
|
+
@dataclasses.dataclass
|
|
546
509
|
class ATT_Read_Response(ATT_PDU):
|
|
547
510
|
'''
|
|
548
511
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.4 Read Response
|
|
549
512
|
'''
|
|
550
513
|
|
|
514
|
+
attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
515
|
+
|
|
551
516
|
|
|
552
517
|
# -----------------------------------------------------------------------------
|
|
553
|
-
@ATT_PDU.subclass
|
|
518
|
+
@ATT_PDU.subclass
|
|
519
|
+
@dataclasses.dataclass
|
|
554
520
|
class ATT_Read_Blob_Request(ATT_PDU):
|
|
555
521
|
'''
|
|
556
522
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.5 Read Blob Request
|
|
557
523
|
'''
|
|
558
524
|
|
|
525
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
526
|
+
value_offset: int = dataclasses.field(metadata=hci.metadata(2))
|
|
527
|
+
|
|
559
528
|
|
|
560
529
|
# -----------------------------------------------------------------------------
|
|
561
|
-
@ATT_PDU.subclass
|
|
530
|
+
@ATT_PDU.subclass
|
|
531
|
+
@dataclasses.dataclass
|
|
562
532
|
class ATT_Read_Blob_Response(ATT_PDU):
|
|
563
533
|
'''
|
|
564
534
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.6 Read Blob Response
|
|
565
535
|
'''
|
|
566
536
|
|
|
537
|
+
part_attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
538
|
+
|
|
567
539
|
|
|
568
540
|
# -----------------------------------------------------------------------------
|
|
569
|
-
@ATT_PDU.subclass
|
|
541
|
+
@ATT_PDU.subclass
|
|
542
|
+
@dataclasses.dataclass
|
|
570
543
|
class ATT_Read_Multiple_Request(ATT_PDU):
|
|
571
544
|
'''
|
|
572
545
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.7 Read Multiple Request
|
|
573
546
|
'''
|
|
574
547
|
|
|
548
|
+
set_of_handles: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
549
|
+
|
|
575
550
|
|
|
576
551
|
# -----------------------------------------------------------------------------
|
|
577
|
-
@ATT_PDU.subclass
|
|
552
|
+
@ATT_PDU.subclass
|
|
553
|
+
@dataclasses.dataclass
|
|
578
554
|
class ATT_Read_Multiple_Response(ATT_PDU):
|
|
579
555
|
'''
|
|
580
556
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.8 Read Multiple Response
|
|
581
557
|
'''
|
|
582
558
|
|
|
559
|
+
set_of_values: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
560
|
+
|
|
583
561
|
|
|
584
562
|
# -----------------------------------------------------------------------------
|
|
585
|
-
@ATT_PDU.subclass
|
|
586
|
-
|
|
587
|
-
('starting_handle', HANDLE_FIELD_SPEC),
|
|
588
|
-
('ending_handle', HANDLE_FIELD_SPEC),
|
|
589
|
-
('attribute_group_type', UUID_2_16_FIELD_SPEC),
|
|
590
|
-
]
|
|
591
|
-
)
|
|
563
|
+
@ATT_PDU.subclass
|
|
564
|
+
@dataclasses.dataclass
|
|
592
565
|
class ATT_Read_By_Group_Type_Request(ATT_PDU):
|
|
593
566
|
'''
|
|
594
567
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.9 Read by Group Type Request
|
|
595
568
|
'''
|
|
596
569
|
|
|
570
|
+
starting_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
571
|
+
ending_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
572
|
+
attribute_group_type: UUID = dataclasses.field(
|
|
573
|
+
metadata=hci.metadata(UUID.parse_uuid)
|
|
574
|
+
)
|
|
575
|
+
|
|
597
576
|
|
|
598
577
|
# -----------------------------------------------------------------------------
|
|
599
|
-
@ATT_PDU.subclass
|
|
578
|
+
@ATT_PDU.subclass
|
|
579
|
+
@dataclasses.dataclass
|
|
600
580
|
class ATT_Read_By_Group_Type_Response(ATT_PDU):
|
|
601
581
|
'''
|
|
602
582
|
See Bluetooth spec @ Vol 3, Part F - 3.4.4.10 Read by Group Type Response
|
|
603
583
|
'''
|
|
604
584
|
|
|
605
|
-
|
|
585
|
+
length: int = dataclasses.field(metadata=hci.metadata(1))
|
|
586
|
+
attribute_data_list: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
587
|
+
attributes: list[tuple[int, int, bytes]] = dataclasses.field(init=False)
|
|
588
|
+
|
|
589
|
+
def __post_init__(self) -> None:
|
|
606
590
|
self.attributes = []
|
|
607
591
|
offset = 0
|
|
608
592
|
while self.length != 0 and offset + self.length <= len(
|
|
@@ -619,14 +603,6 @@ class ATT_Read_By_Group_Type_Response(ATT_PDU):
|
|
|
619
603
|
)
|
|
620
604
|
offset += self.length
|
|
621
605
|
|
|
622
|
-
def __init__(self, *args, **kwargs):
|
|
623
|
-
super().__init__(*args, **kwargs)
|
|
624
|
-
self.parse_attribute_data_list()
|
|
625
|
-
|
|
626
|
-
def init_from_bytes(self, pdu, offset):
|
|
627
|
-
super().init_from_bytes(pdu, offset)
|
|
628
|
-
self.parse_attribute_data_list()
|
|
629
|
-
|
|
630
606
|
def __str__(self):
|
|
631
607
|
result = color(self.name, 'yellow')
|
|
632
608
|
result += ':\n' + HCI_Object.format_fields(
|
|
@@ -651,15 +627,20 @@ class ATT_Read_By_Group_Type_Response(ATT_PDU):
|
|
|
651
627
|
|
|
652
628
|
|
|
653
629
|
# -----------------------------------------------------------------------------
|
|
654
|
-
@ATT_PDU.subclass
|
|
630
|
+
@ATT_PDU.subclass
|
|
631
|
+
@dataclasses.dataclass
|
|
655
632
|
class ATT_Write_Request(ATT_PDU):
|
|
656
633
|
'''
|
|
657
634
|
See Bluetooth spec @ Vol 3, Part F - 3.4.5.1 Write Request
|
|
658
635
|
'''
|
|
659
636
|
|
|
637
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
638
|
+
attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
639
|
+
|
|
660
640
|
|
|
661
641
|
# -----------------------------------------------------------------------------
|
|
662
|
-
@ATT_PDU.subclass
|
|
642
|
+
@ATT_PDU.subclass
|
|
643
|
+
@dataclasses.dataclass
|
|
663
644
|
class ATT_Write_Response(ATT_PDU):
|
|
664
645
|
'''
|
|
665
646
|
See Bluetooth spec @ Vol 3, Part F - 3.4.5.2 Write Response
|
|
@@ -667,65 +648,70 @@ class ATT_Write_Response(ATT_PDU):
|
|
|
667
648
|
|
|
668
649
|
|
|
669
650
|
# -----------------------------------------------------------------------------
|
|
670
|
-
@ATT_PDU.subclass
|
|
651
|
+
@ATT_PDU.subclass
|
|
652
|
+
@dataclasses.dataclass
|
|
671
653
|
class ATT_Write_Command(ATT_PDU):
|
|
672
654
|
'''
|
|
673
655
|
See Bluetooth spec @ Vol 3, Part F - 3.4.5.3 Write Command
|
|
674
656
|
'''
|
|
675
657
|
|
|
658
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
659
|
+
attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
660
|
+
|
|
676
661
|
|
|
677
662
|
# -----------------------------------------------------------------------------
|
|
678
|
-
@ATT_PDU.subclass
|
|
679
|
-
|
|
680
|
-
('attribute_handle', HANDLE_FIELD_SPEC),
|
|
681
|
-
('attribute_value', '*'),
|
|
682
|
-
# ('authentication_signature', 'TODO')
|
|
683
|
-
]
|
|
684
|
-
)
|
|
663
|
+
@ATT_PDU.subclass
|
|
664
|
+
@dataclasses.dataclass
|
|
685
665
|
class ATT_Signed_Write_Command(ATT_PDU):
|
|
686
666
|
'''
|
|
687
667
|
See Bluetooth spec @ Vol 3, Part F - 3.4.5.4 Signed Write Command
|
|
688
668
|
'''
|
|
689
669
|
|
|
670
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
671
|
+
attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
672
|
+
# TODO: authentication_signature
|
|
673
|
+
|
|
690
674
|
|
|
691
675
|
# -----------------------------------------------------------------------------
|
|
692
|
-
@ATT_PDU.subclass
|
|
693
|
-
|
|
694
|
-
('attribute_handle', HANDLE_FIELD_SPEC),
|
|
695
|
-
('value_offset', 2),
|
|
696
|
-
('part_attribute_value', '*'),
|
|
697
|
-
]
|
|
698
|
-
)
|
|
676
|
+
@ATT_PDU.subclass
|
|
677
|
+
@dataclasses.dataclass
|
|
699
678
|
class ATT_Prepare_Write_Request(ATT_PDU):
|
|
700
679
|
'''
|
|
701
680
|
See Bluetooth spec @ Vol 3, Part F - 3.4.6.1 Prepare Write Request
|
|
702
681
|
'''
|
|
703
682
|
|
|
683
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
684
|
+
value_offset: int = dataclasses.field(metadata=hci.metadata(2))
|
|
685
|
+
part_attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
686
|
+
|
|
704
687
|
|
|
705
688
|
# -----------------------------------------------------------------------------
|
|
706
|
-
@ATT_PDU.subclass
|
|
707
|
-
|
|
708
|
-
('attribute_handle', HANDLE_FIELD_SPEC),
|
|
709
|
-
('value_offset', 2),
|
|
710
|
-
('part_attribute_value', '*'),
|
|
711
|
-
]
|
|
712
|
-
)
|
|
689
|
+
@ATT_PDU.subclass
|
|
690
|
+
@dataclasses.dataclass
|
|
713
691
|
class ATT_Prepare_Write_Response(ATT_PDU):
|
|
714
692
|
'''
|
|
715
693
|
See Bluetooth spec @ Vol 3, Part F - 3.4.6.2 Prepare Write Response
|
|
716
694
|
'''
|
|
717
695
|
|
|
696
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
697
|
+
value_offset: int = dataclasses.field(metadata=hci.metadata(2))
|
|
698
|
+
part_attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
699
|
+
|
|
718
700
|
|
|
719
701
|
# -----------------------------------------------------------------------------
|
|
720
|
-
@ATT_PDU.subclass
|
|
702
|
+
@ATT_PDU.subclass
|
|
703
|
+
@dataclasses.dataclass
|
|
721
704
|
class ATT_Execute_Write_Request(ATT_PDU):
|
|
722
705
|
'''
|
|
723
706
|
See Bluetooth spec @ Vol 3, Part F - 3.4.6.3 Execute Write Request
|
|
724
707
|
'''
|
|
725
708
|
|
|
709
|
+
flags: int = dataclasses.field(metadata=hci.metadata(1))
|
|
710
|
+
|
|
726
711
|
|
|
727
712
|
# -----------------------------------------------------------------------------
|
|
728
|
-
@ATT_PDU.subclass
|
|
713
|
+
@ATT_PDU.subclass
|
|
714
|
+
@dataclasses.dataclass
|
|
729
715
|
class ATT_Execute_Write_Response(ATT_PDU):
|
|
730
716
|
'''
|
|
731
717
|
See Bluetooth spec @ Vol 3, Part F - 3.4.6.4 Execute Write Response
|
|
@@ -733,23 +719,32 @@ class ATT_Execute_Write_Response(ATT_PDU):
|
|
|
733
719
|
|
|
734
720
|
|
|
735
721
|
# -----------------------------------------------------------------------------
|
|
736
|
-
@ATT_PDU.subclass
|
|
722
|
+
@ATT_PDU.subclass
|
|
723
|
+
@dataclasses.dataclass
|
|
737
724
|
class ATT_Handle_Value_Notification(ATT_PDU):
|
|
738
725
|
'''
|
|
739
726
|
See Bluetooth spec @ Vol 3, Part F - 3.4.7.1 Handle Value Notification
|
|
740
727
|
'''
|
|
741
728
|
|
|
729
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
730
|
+
attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
731
|
+
|
|
742
732
|
|
|
743
733
|
# -----------------------------------------------------------------------------
|
|
744
|
-
@ATT_PDU.subclass
|
|
734
|
+
@ATT_PDU.subclass
|
|
735
|
+
@dataclasses.dataclass
|
|
745
736
|
class ATT_Handle_Value_Indication(ATT_PDU):
|
|
746
737
|
'''
|
|
747
738
|
See Bluetooth spec @ Vol 3, Part F - 3.4.7.2 Handle Value Indication
|
|
748
739
|
'''
|
|
749
740
|
|
|
741
|
+
attribute_handle: int = dataclasses.field(metadata=hci.metadata(HANDLE_FIELD_SPEC))
|
|
742
|
+
attribute_value: bytes = dataclasses.field(metadata=hci.metadata("*"))
|
|
743
|
+
|
|
750
744
|
|
|
751
745
|
# -----------------------------------------------------------------------------
|
|
752
|
-
@ATT_PDU.subclass
|
|
746
|
+
@ATT_PDU.subclass
|
|
747
|
+
@dataclasses.dataclass
|
|
753
748
|
class ATT_Handle_Value_Confirmation(ATT_PDU):
|
|
754
749
|
'''
|
|
755
750
|
See Bluetooth spec @ Vol 3, Part F - 3.4.7.3 Handle Value Confirmation
|