1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Philippe Biondi <phil@secdev.org>
5# Copyright (C) Mike Ryan <mikeryan@lacklustre.net>
6# Copyright (C) Michael Farrell <micolous+git@gmail.com>
7# Copyright (C) Haram Park <freehr94@korea.ac.kr>
8
9"""
10Bluetooth layers, sockets and send/receive functions.
11"""
12
13import ctypes
14import socket
15import struct
16import select
17from ctypes import sizeof
18
19from scapy.config import conf
20from scapy.data import (
21 DLT_BLUETOOTH_HCI_H4,
22 DLT_BLUETOOTH_HCI_H4_WITH_PHDR,
23 DLT_BLUETOOTH_LINUX_MONITOR,
24 BLUETOOTH_CORE_COMPANY_IDENTIFIERS
25)
26from scapy.packet import bind_layers, Packet
27from scapy.fields import (
28 BitField,
29 XBitField,
30 ByteEnumField,
31 ByteField,
32 FieldLenField,
33 FieldListField,
34 FlagsField,
35 IntField,
36 LEShortEnumField,
37 LEShortField,
38 LEIntField,
39 LenField,
40 MultipleTypeField,
41 NBytesField,
42 PacketListField,
43 PadField,
44 ShortField,
45 SignedByteField,
46 StrField,
47 StrFixedLenField,
48 StrLenField,
49 StrNullField,
50 UUIDField,
51 XByteField,
52 XLE3BytesField,
53 XLELongField,
54 XStrLenField,
55 XLEShortField,
56 XLEIntField,
57 LEMACField,
58 BitEnumField,
59 LEThreeBytesField,
60 ConditionalField
61)
62from scapy.supersocket import SuperSocket
63from scapy.sendrecv import sndrcv
64from scapy.data import MTU
65from scapy.consts import WINDOWS
66from scapy.error import warning
67
68
69############
70# Consts #
71############
72
73# From hci.h
74HCI_CHANNEL_RAW = 0
75HCI_CHANNEL_USER = 1
76HCI_CHANNEL_MONITOR = 2
77HCI_CHANNEL_CONTROL = 3
78HCI_CHANNEL_LOGGING = 4
79
80HCI_DEV_NONE = 0xffff
81
82
83##########
84# Layers #
85##########
86
87# See bluez/lib/hci.h for details
88
89# Transport layers
90
91class HCI_PHDR_Hdr(Packet):
92 name = "HCI PHDR transport layer"
93 fields_desc = [IntField("direction", 0)]
94
95
96# Real layers
97
98_bluetooth_packet_types = {
99 0: "Acknowledgement",
100 1: "Command",
101 2: "ACL Data",
102 3: "Synchronous",
103 4: "Event",
104 5: "Reserve",
105 14: "Vendor",
106 15: "Link Control"
107}
108
109_bluetooth_error_codes = {
110 0x00: "Success",
111 0x01: "Unknown HCI Command",
112 0x02: "Unknown Connection Identifier",
113 0x03: "Hardware Failure",
114 0x04: "Page Timeout",
115 0x05: "Authentication Failure",
116 0x06: "PIN or Key Missing",
117 0x07: "Memory Capacity Exceeded",
118 0x08: "Connection Timeout",
119 0x09: "Connection Limit Exceeded",
120 0x0A: "Synchronous Connection Limit To A Device Exceeded",
121 0x0B: "Connection Already Exists",
122 0x0C: "Command Disallowed",
123 0x0D: "Connection Rejected due to Limited Resources",
124 0x0E: "Connection Rejected Due To Security Reasons",
125 0x0F: "Connection Rejected due to Unacceptable BD_ADDR",
126 0x10: "Connection Accept Timeout Exceeded",
127 0x11: "Unsupported Feature or Parameter Value",
128 0x12: "Invalid HCI Command Parameters",
129 0x13: "Remote User Terminated Connection",
130 0x14: "Remote Device Terminated Connection due to Low Resources",
131 0x15: "Remote Device Terminated Connection due to Power Off",
132 0x16: "Connection Terminated By Local Host",
133 0x17: "Repeated Attempts",
134 0x18: "Pairing Not Allowed",
135 0x19: "Unknown LMP PDU",
136 0x1A: "Unsupported Remote Feature / Unsupported LMP Feature",
137 0x1B: "SCO Offset Rejected",
138 0x1C: "SCO Interval Rejected",
139 0x1D: "SCO Air Mode Rejected",
140 0x1E: "Invalid LMP Parameters / Invalid LL Parameters",
141 0x1F: "Unspecified Error",
142 0x20: "Unsupported LMP Parameter Value / Unsupported LL Parameter Value",
143 0x21: "Role Change Not Allowed",
144 0x22: "LMP Response Timeout / LL Response Timeout",
145 0x23: "LMP Error Transaction Collision / LL Procedure Collision",
146 0x24: "LMP PDU Not Allowed",
147 0x25: "Encryption Mode Not Acceptable",
148 0x26: "Link Key cannot be Changed",
149 0x27: "Requested QoS Not Supported",
150 0x28: "Instant Passed",
151 0x29: "Pairing With Unit Key Not Supported",
152 0x2A: "Different Transaction Collision",
153 0x2B: "Reserved for future use",
154 0x2C: "QoS Unacceptable Parameter",
155 0x2D: "QoS Rejected",
156 0x2E: "Channel Classification Not Supported",
157 0x2F: "Insufficient Security",
158 0x30: "Parameter Out Of Mandatory Range",
159 0x31: "Reserved for future use",
160 0x32: "Role Switch Pending",
161 0x33: "Reserved for future use",
162 0x34: "Reserved Slot Violation",
163 0x35: "Role Switch Failed",
164 0x36: "Extended Inquiry Response Too Large",
165 0x37: "Secure Simple Pairing Not Supported By Host",
166 0x38: "Host Busy - Pairing",
167 0x39: "Connection Rejected due to No Suitable Channel Found",
168 0x3A: "Controller Busy",
169 0x3B: "Unacceptable Connection Parameters",
170 0x3C: "Advertising Timeout",
171 0x3D: "Connection Terminated due to MIC Failure",
172 0x3E: "Connection Failed to be Established / Synchronization Timeout",
173 0x3F: "MAC Connection Failed",
174 0x40: "Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock"
175 " Dragging",
176 0x41: "Type0 Submap Not Defined",
177 0x42: "Unknown Advertising Identifier",
178 0x43: "Limit Reached",
179 0x44: "Operation Cancelled by Host",
180 0x45: "Packet Too Long"
181}
182
183_att_error_codes = {
184 0x01: "invalid handle",
185 0x02: "read not permitted",
186 0x03: "write not permitted",
187 0x04: "invalid pdu",
188 0x05: "insufficient auth",
189 0x06: "unsupported req",
190 0x07: "invalid offset",
191 0x08: "insufficient author",
192 0x09: "prepare queue full",
193 0x0a: "attr not found",
194 0x0b: "attr not long",
195 0x0c: "insufficient key size",
196 0x0d: "invalid value size",
197 0x0e: "unlikely",
198 0x0f: "insufficiet encrypt",
199 0x10: "unsupported gpr type",
200 0x11: "insufficient resources",
201}
202
203_bluetooth_features = [
204 '3_slot_packets',
205 '5_slot_packets',
206 'encryption',
207 'slot_offset',
208 'timing_accuracy',
209 'role_switch',
210 'hold_mode',
211 'sniff_mode',
212 'park_mode',
213 'power_control_requests',
214 'channel_quality_driven_data_rate',
215 'sco_link',
216 'hv2_packets',
217 'hv3_packets',
218 'u_law_log_synchronous_data',
219 'a_law_log_synchronous_data',
220 'cvsd_synchronous_data',
221 'paging_parameter_negotiation',
222 'power_control',
223 'transparent_synchronous_data',
224 'flow_control_lag_4_bit0',
225 'flow_control_lag_4_bit1',
226 'flow_control_lag_4_bit2',
227 'broadband_encryption',
228 'cvsd_synchronous_data',
229 'edr_acl_2_mbps_mode',
230 'edr_acl_3_mbps_mode',
231 'enhanced_inquiry_scan',
232 'interlaced_inquiry_scan',
233 'interlaced_page_scan',
234 'rssi_with_inquiry_results',
235 'ev3_packets',
236 'ev4_packets',
237 'ev5_packets',
238 'reserved',
239 'afh_capable_slave',
240 'afh_classification_slave',
241 'br_edr_not_supported',
242 'le_supported_controller',
243 '3_slot_edr_acl_packets',
244 '5_slot_edr_acl_packets',
245 'sniff_subrating',
246 'pause_encryption',
247 'afh_capable_master',
248 'afh_classification_master',
249 'edr_esco_2_mbps_mode',
250 'edr_esco_3_mbps_mode',
251 '3_slot_edr_esco_packets',
252 'extended_inquiry_response',
253 'simultaneous_le_and_br_edr_to_same_device_capable_controller',
254 'reserved2',
255 'secure_simple_pairing',
256 'encapsulated_pdu',
257 'erroneous_data_reporting',
258 'non_flushable_packet_boundary_flag',
259 'reserved3',
260 'link_supervision_timeout_changed_event',
261 'inquiry_tx_power_level',
262 'enhanced_power_control',
263 'reserved4_bit0',
264 'reserved4_bit1',
265 'reserved4_bit2',
266 'reserved4_bit3',
267 'extended_features',
268]
269
270_bluetooth_core_specification_versions = {
271 0x00: '1.0b',
272 0x01: '1.1',
273 0x02: '1.2',
274 0x03: '2.0+EDR',
275 0x04: '2.1+EDR',
276 0x05: '3.0+HS',
277 0x06: '4.0',
278 0x07: '4.1',
279 0x08: '4.2',
280 0x09: '5.0',
281 0x0a: '5.1',
282 0x0b: '5.2',
283 0x0c: '5.3',
284 0x0d: '5.4',
285 0x0e: '6.0',
286}
287
288
289class HCI_Hdr(Packet):
290 name = "HCI header"
291 fields_desc = [ByteEnumField("type", 2, _bluetooth_packet_types)]
292
293 def mysummary(self):
294 return self.sprintf("HCI %type%")
295
296
297class HCI_ACL_Hdr(Packet):
298 name = "HCI ACL header"
299 fields_desc = [BitField("BC", 0, 2, tot_size=-2),
300 BitField("PB", 0, 2),
301 BitField("handle", 0, 12, end_tot_size=-2),
302 LEShortField("len", None), ]
303
304 def post_build(self, p, pay):
305 p += pay
306 if self.len is None:
307 p = p[:2] + struct.pack("<H", len(pay)) + p[4:]
308 return p
309
310
311class L2CAP_Hdr(Packet):
312 name = "L2CAP header"
313 fields_desc = [LEShortField("len", None),
314 LEShortEnumField("cid", 0, {1: "control", 4: "attribute"}), ] # noqa: E501
315
316 def post_build(self, p, pay):
317 p += pay
318 if self.len is None:
319 p = struct.pack("<H", len(pay)) + p[2:]
320 return p
321
322
323class L2CAP_CmdHdr(Packet):
324 name = "L2CAP command header"
325 fields_desc = [
326 ByteEnumField("code", 8, {1: "rej",
327 2: "conn_req",
328 3: "conn_resp",
329 4: "conf_req",
330 5: "conf_resp",
331 6: "disconn_req",
332 7: "disconn_resp",
333 8: "echo_req",
334 9: "echo_resp",
335 10: "info_req",
336 11: "info_resp",
337 12: "create_channel_req",
338 13: "create_channel_resp",
339 14: "move_channel_req",
340 15: "move_channel_resp",
341 16: "move_channel_confirm_req",
342 17: "move_channel_confirm_resp",
343 18: "conn_param_update_req",
344 19: "conn_param_update_resp",
345 20: "LE_credit_based_conn_req",
346 21: "LE_credit_based_conn_resp",
347 22: "flow_control_credit_ind",
348 23: "credit_based_conn_req",
349 24: "credit_based_conn_resp",
350 25: "credit_based_reconf_req",
351 26: "credit_based_reconf_resp"}),
352 ByteField("id", 1),
353 LEShortField("len", None)]
354
355 def post_build(self, p, pay):
356 p += pay
357 if self.len is None:
358 p = p[:2] + struct.pack("<H", len(pay)) + p[4:]
359 return p
360
361 def answers(self, other):
362 if other.id == self.id:
363 if self.code == 1:
364 return 1
365 if other.code in [2, 4, 6, 8, 10, 18] and self.code == other.code + 1: # noqa: E501
366 if other.code == 8:
367 return 1
368 return self.payload.answers(other.payload)
369 return 0
370
371
372class L2CAP_ConnReq(Packet):
373 name = "L2CAP Conn Req"
374 fields_desc = [LEShortEnumField("psm", 0, {1: "SDP",
375 3: "RFCOMM",
376 5: "TCS-BIN",
377 7: "TCS-BIN-CORDLESS",
378 15: "BNEP",
379 17: "HID-Control",
380 19: "HID-Interrupt",
381 21: "UPnP",
382 23: "AVCTP-Control",
383 25: "AVDTP",
384 27: "AVCTP-Browsing",
385 29: "UDI_C-Plane",
386 31: "ATT",
387 33: "3DSP",
388 35: "IPSP",
389 37: "OTS"}),
390 LEShortField("scid", 0),
391 ]
392
393
394class L2CAP_ConnResp(Packet):
395 name = "L2CAP Conn Resp"
396 fields_desc = [LEShortField("dcid", 0),
397 LEShortField("scid", 0),
398 LEShortEnumField("result", 0, ["success", "pend", "cr_bad_psm", "cr_sec_block", "cr_no_mem", "reserved", "cr_inval_scid", "cr_scid_in_use"]), # noqa: E501
399 LEShortEnumField("status", 0, ["no_info", "authen_pend", "author_pend", "reserved"]), # noqa: E501
400 ]
401
402 def answers(self, other):
403 # dcid Resp == scid Req. Therefore compare SCIDs
404 return isinstance(other, L2CAP_ConnReq) and self.scid == other.scid
405
406
407class L2CAP_CmdRej(Packet):
408 name = "L2CAP Command Rej"
409 fields_desc = [LEShortField("reason", 0),
410 ]
411
412
413class L2CAP_ConfReq(Packet):
414 name = "L2CAP Conf Req"
415 fields_desc = [LEShortField("dcid", 0),
416 LEShortField("flags", 0),
417 ]
418
419
420class L2CAP_ConfResp(Packet):
421 name = "L2CAP Conf Resp"
422 fields_desc = [LEShortField("scid", 0),
423 LEShortField("flags", 0),
424 LEShortEnumField("result", 0, ["success", "unaccept", "reject", "unknown"]), # noqa: E501
425 ]
426
427 def answers(self, other):
428 # Req and Resp contain either the SCID or the DCID.
429 return isinstance(other, L2CAP_ConfReq)
430
431
432class L2CAP_DisconnReq(Packet):
433 name = "L2CAP Disconn Req"
434 fields_desc = [LEShortField("dcid", 0),
435 LEShortField("scid", 0), ]
436
437
438class L2CAP_DisconnResp(Packet):
439 name = "L2CAP Disconn Resp"
440 fields_desc = [LEShortField("dcid", 0),
441 LEShortField("scid", 0), ]
442
443 def answers(self, other):
444 return self.scid == other.scid
445
446
447class L2CAP_EchoReq(Packet):
448 name = "L2CAP Echo Req"
449 fields_desc = [StrField("data", ""), ]
450
451
452class L2CAP_EchoResp(Packet):
453 name = "L2CAP Echo Resp"
454 fields_desc = [StrField("data", ""), ]
455
456
457class L2CAP_InfoReq(Packet):
458 name = "L2CAP Info Req"
459 fields_desc = [LEShortEnumField("type", 0, {1: "CL_MTU", 2: "FEAT_MASK"}),
460 StrField("data", "")
461 ]
462
463
464class L2CAP_InfoResp(Packet):
465 name = "L2CAP Info Resp"
466 fields_desc = [LEShortField("type", 0),
467 LEShortEnumField("result", 0, ["success", "not_supp"]),
468 StrField("data", ""), ]
469
470 def answers(self, other):
471 return self.type == other.type
472
473
474class L2CAP_Create_Channel_Request(Packet):
475 name = "L2CAP Create Channel Request"
476 fields_desc = [LEShortEnumField("psm", 0, {1: "SDP",
477 3: "RFCOMM",
478 5: "TCS-BIN",
479 7: "TCS-BIN-CORDLESS",
480 15: "BNEP",
481 17: "HID-Control",
482 19: "HID-Interrupt",
483 21: "UPnP",
484 23: "AVCTP-Control",
485 25: "AVDTP",
486 27: "AVCTP-Browsing",
487 29: "UDI_C-Plane",
488 31: "ATT",
489 33: "3DSP",
490 35: "IPSP",
491 37: "OTS"}),
492 LEShortField("scid", 0),
493 ByteField("controller_id", 0), ]
494
495
496class L2CAP_Create_Channel_Response(Packet):
497 name = "L2CAP Create Channel Response"
498 fields_desc = [LEShortField("dcid", 0),
499 LEShortField("scid", 0),
500 LEShortEnumField("result", 0, {
501 0: "Connection successful",
502 1: "Connection pending",
503 2: "Connection refused - PSM not supported",
504 3: "Connection refused - security block",
505 4: "Connection refused - no resources available",
506 5: "Connection refused - cont_ID not supported",
507 6: "Connection refused - invalid scid",
508 7: "Connection refused - scid already allocated"}),
509 LEShortEnumField("status", 0, {
510 0: "No further information available",
511 1: "Authentication pending",
512 2: "Authorization pending"}), ]
513
514
515class L2CAP_Move_Channel_Request(Packet):
516 name = "L2CAP Move Channel Request"
517 fields_desc = [LEShortField("icid", 0),
518 ByteField("dest_controller_id", 0), ]
519
520
521class L2CAP_Move_Channel_Response(Packet):
522 name = "L2CAP Move Channel Response"
523 fields_desc = [LEShortField("icid", 0),
524 LEShortEnumField("result", 0, {
525 0: "Move success",
526 1: "Move pending",
527 2: "Move refused - Cont_ID not supported",
528 3: "Move refused - Cont_ID is same as old one",
529 4: "Move refused - Configuration not supported",
530 5: "Move refused - Move channel collision",
531 6: "Move refused - Not allowed to be moved"}), ]
532
533
534class L2CAP_Move_Channel_Confirmation_Request(Packet):
535 name = "L2CAP Move Channel Confirmation Request"
536 fields_desc = [LEShortField("icid", 0),
537 LEShortEnumField("result", 0, {0: "Move success",
538 1: "Move failure"}), ]
539
540
541class L2CAP_Move_Channel_Confirmation_Response(Packet):
542 name = "L2CAP Move Channel Confirmation Response"
543 fields_desc = [LEShortField("icid", 0), ]
544
545
546class L2CAP_Connection_Parameter_Update_Request(Packet):
547 name = "L2CAP Connection Parameter Update Request"
548 fields_desc = [LEShortField("min_interval", 0),
549 LEShortField("max_interval", 0),
550 LEShortField("slave_latency", 0),
551 LEShortField("timeout_mult", 0), ]
552
553
554class L2CAP_Connection_Parameter_Update_Response(Packet):
555 name = "L2CAP Connection Parameter Update Response"
556 fields_desc = [LEShortField("move_result", 0), ]
557
558
559class L2CAP_LE_Credit_Based_Connection_Request(Packet):
560 name = "L2CAP LE Credit Based Connection Request"
561 fields_desc = [LEShortField("spsm", 0),
562 LEShortField("scid", 0),
563 LEShortField("mtu", 0),
564 LEShortField("mps", 0),
565 LEShortField("initial_credits", 0), ]
566
567
568class L2CAP_LE_Credit_Based_Connection_Response(Packet):
569 name = "L2CAP LE Credit Based Connection Response"
570 fields_desc = [LEShortField("dcid", 0),
571 LEShortField("mtu", 0),
572 LEShortField("mps", 0),
573 LEShortField("initial_credits", 0),
574 LEShortEnumField("result", 0, {
575 0: "Connection successful",
576 2: "Connection refused - SPSM not supported",
577 4: "Connection refused - no resources available",
578 5: "Connection refused - authentication error",
579 6: "Connection refused - authorization error",
580 7: "Connection refused - encrypt_key size error",
581 8: "Connection refused - insufficient encryption",
582 9: "Connection refused - invalid scid",
583 10: "Connection refused - scid already allocated",
584 11: "Connection refused - parameters error"}), ]
585
586
587class L2CAP_Flow_Control_Credit_Ind(Packet):
588 name = "L2CAP Flow Control Credit Ind"
589 fields_desc = [LEShortField("cid", 0),
590 LEShortField("credits", 0), ]
591
592
593class L2CAP_Credit_Based_Connection_Request(Packet):
594 name = "L2CAP Credit Based Connection Request"
595 fields_desc = [LEShortField("spsm", 0),
596 LEShortField("mtu", 0),
597 LEShortField("mps", 0),
598 LEShortField("initial_credits", 0),
599 LEShortField("scid", 0), ]
600
601
602class L2CAP_Credit_Based_Connection_Response(Packet):
603 name = "L2CAP Credit Based Connection Response"
604 fields_desc = [LEShortField("mtu", 0),
605 LEShortField("mps", 0),
606 LEShortField("initial_credits", 0),
607 LEShortEnumField("result", 0, {
608 0: "All connection successful",
609 2: "All connection refused - SPSM not supported",
610 4: "Some connections refused - resources error",
611 5: "All connection refused - authentication error",
612 6: "All connection refused - authorization error",
613 7: "All connection refused - encrypt_key size error",
614 8: "All connection refused - encryption error",
615 9: "Some connection refused - invalid scid",
616 10: "Some connection refused - scid already allocated",
617 11: "All Connection refused - unacceptable parameters",
618 12: "All connections refused - invalid parameters"}),
619 LEShortField("dcid", 0), ]
620
621
622class L2CAP_Credit_Based_Reconfigure_Request(Packet):
623 name = "L2CAP Credit Based Reconfigure Request"
624 fields_desc = [LEShortField("mtu", 0),
625 LEShortField("mps", 0),
626 LEShortField("dcid", 0), ]
627
628
629class L2CAP_Credit_Based_Reconfigure_Response(Packet):
630 name = "L2CAP Credit Based Reconfigure Response"
631 fields_desc = [LEShortEnumField("result", 0, {
632 0: "Reconfig successful",
633 1: "Reconfig failed - MTU size reduction not allowed",
634 2: "Reconfig failed - MPS size reduction not allowed",
635 3: "Reconfig failed - one or more dcids invalid",
636 4: "Reconfig failed - unacceptable parameters"}), ]
637
638
639class ATT_Hdr(Packet):
640 name = "ATT header"
641 fields_desc = [XByteField("opcode", None), ]
642
643
644class ATT_Handle(Packet):
645 name = "ATT Short Handle"
646 fields_desc = [XLEShortField("handle", 0),
647 XLEShortField("value", 0)]
648
649 def extract_padding(self, s):
650 return b'', s
651
652
653class ATT_Handle_UUID128(Packet):
654 name = "ATT Handle (UUID 128)"
655 fields_desc = [XLEShortField("handle", 0),
656 UUIDField("value", None, uuid_fmt=UUIDField.FORMAT_REV)]
657
658 def extract_padding(self, s):
659 return b'', s
660
661
662class ATT_Error_Response(Packet):
663 name = "Error Response"
664 fields_desc = [XByteField("request", 0),
665 LEShortField("handle", 0),
666 ByteEnumField("ecode", 0, _att_error_codes), ]
667
668
669class ATT_Exchange_MTU_Request(Packet):
670 name = "Exchange MTU Request"
671 fields_desc = [LEShortField("mtu", 0), ]
672
673
674class ATT_Exchange_MTU_Response(Packet):
675 name = "Exchange MTU Response"
676 fields_desc = [LEShortField("mtu", 0), ]
677
678
679class ATT_Find_Information_Request(Packet):
680 name = "Find Information Request"
681 fields_desc = [XLEShortField("start", 0x0000),
682 XLEShortField("end", 0xffff), ]
683
684
685class ATT_Find_Information_Response(Packet):
686 name = "Find Information Response"
687 fields_desc = [
688 XByteField("format", 1),
689 MultipleTypeField(
690 [
691 (PacketListField("handles", [], ATT_Handle),
692 lambda pkt: pkt.format == 1),
693 (PacketListField("handles", [], ATT_Handle_UUID128),
694 lambda pkt: pkt.format == 2),
695 ],
696 StrFixedLenField("handles", "", length=0)
697 )
698 ]
699
700
701class ATT_Find_By_Type_Value_Request(Packet):
702 name = "Find By Type Value Request"
703 fields_desc = [XLEShortField("start", 0x0001),
704 XLEShortField("end", 0xffff),
705 XLEShortField("uuid", None),
706 StrField("data", ""), ]
707
708
709class ATT_Find_By_Type_Value_Response(Packet):
710 name = "Find By Type Value Response"
711 fields_desc = [PacketListField("handles", [], ATT_Handle)]
712
713
714class ATT_Read_By_Type_Request_128bit(Packet):
715 name = "Read By Type Request"
716 fields_desc = [XLEShortField("start", 0x0001),
717 XLEShortField("end", 0xffff),
718 XLELongField("uuid1", None),
719 XLELongField("uuid2", None)]
720
721 @classmethod
722 def dispatch_hook(cls, _pkt=None, *args, **kargs):
723 if _pkt and len(_pkt) == 6:
724 return ATT_Read_By_Type_Request
725 return ATT_Read_By_Type_Request_128bit
726
727
728class ATT_Read_By_Type_Request(Packet):
729 name = "Read By Type Request"
730 fields_desc = [XLEShortField("start", 0x0001),
731 XLEShortField("end", 0xffff),
732 XLEShortField("uuid", None)]
733
734
735class ATT_Handle_Variable(Packet):
736 fields_desc = [XLEShortField("handle", 0),
737 XStrLenField(
738 "value", 0,
739 length_from=lambda pkt: pkt and pkt.parent.len - 2 or 0)]
740
741 def extract_padding(self, s):
742 return b"", s
743
744
745class ATT_Read_By_Type_Response(Packet):
746 name = "Read By Type Response"
747 fields_desc = [ByteField("len", 4),
748 PacketListField("handles", [], ATT_Handle_Variable)]
749
750
751class ATT_Read_Request(Packet):
752 name = "Read Request"
753 fields_desc = [XLEShortField("gatt_handle", 0), ]
754
755
756class ATT_Read_Response(Packet):
757 name = "Read Response"
758 fields_desc = [StrField("value", "")]
759
760
761class ATT_Read_Multiple_Request(Packet):
762 name = "Read Multiple Request"
763 fields_desc = [FieldListField("handles", [], XLEShortField("", 0))]
764
765
766class ATT_Read_Multiple_Response(Packet):
767 name = "Read Multiple Response"
768 fields_desc = [StrField("values", "")]
769
770
771class ATT_Read_By_Group_Type_Request(Packet):
772 name = "Read By Group Type Request"
773 fields_desc = [XLEShortField("start", 0),
774 XLEShortField("end", 0xffff),
775 XLEShortField("uuid", 0), ]
776
777
778class ATT_Group_Handle_Variable(Packet):
779 fields_desc = [XLEShortField("handle", 0),
780 XLEShortField("group_end_handle", 0),
781 XStrLenField(
782 "value", 0,
783 length_from=lambda pkt: pkt and pkt.parent.len - 4 or 0)]
784
785 def extract_padding(self, s):
786 return b"", s
787
788
789class ATT_Read_By_Group_Type_Response(Packet):
790 name = "Read By Group Type Response"
791 fields_desc = [ByteField("len", 4),
792 PacketListField("handles", [], ATT_Group_Handle_Variable)]
793
794
795class ATT_Write_Request(Packet):
796 name = "Write Request"
797 fields_desc = [XLEShortField("gatt_handle", 0),
798 StrField("data", ""), ]
799
800
801class ATT_Write_Command(Packet):
802 name = "Write Request"
803 fields_desc = [XLEShortField("gatt_handle", 0),
804 StrField("data", ""), ]
805
806
807class ATT_Write_Response(Packet):
808 name = "Write Response"
809
810
811class ATT_Prepare_Write_Request(Packet):
812 name = "Prepare Write Request"
813 fields_desc = [
814 XLEShortField("gatt_handle", 0),
815 LEShortField("offset", 0),
816 StrField("data", "")
817 ]
818
819
820class ATT_Prepare_Write_Response(ATT_Prepare_Write_Request):
821 name = "Prepare Write Response"
822
823
824class ATT_Handle_Value_Notification(Packet):
825 name = "Handle Value Notification"
826 fields_desc = [XLEShortField("gatt_handle", 0),
827 StrField("value", ""), ]
828
829
830class ATT_Execute_Write_Request(Packet):
831 name = "Execute Write Request"
832 fields_desc = [
833 ByteEnumField("flags", 1, {
834 0: "Cancel all prepared writes",
835 1: "Immediately write all pending prepared values",
836 }),
837 ]
838
839
840class ATT_Execute_Write_Response(Packet):
841 name = "Execute Write Response"
842
843
844class ATT_Read_Blob_Request(Packet):
845 name = "Read Blob Request"
846 fields_desc = [
847 XLEShortField("gatt_handle", 0),
848 LEShortField("offset", 0)
849 ]
850
851
852class ATT_Read_Blob_Response(Packet):
853 name = "Read Blob Response"
854 fields_desc = [
855 StrField("value", "")
856 ]
857
858
859class ATT_Handle_Value_Indication(Packet):
860 name = "Handle Value Indication"
861 fields_desc = [
862 XLEShortField("gatt_handle", 0),
863 StrField("value", ""),
864 ]
865
866
867class SM_Hdr(Packet):
868 name = "SM header"
869 fields_desc = [ByteField("sm_command", None)]
870
871
872class SM_Pairing_Request(Packet):
873 name = "Pairing Request"
874 fields_desc = [ByteEnumField("iocap", 3, {0: "DisplayOnly", 1: "DisplayYesNo", 2: "KeyboardOnly", 3: "NoInputNoOutput", 4: "KeyboardDisplay"}), # noqa: E501
875 ByteEnumField("oob", 0, {0: "Not Present", 1: "Present (from remote device)"}), # noqa: E501
876 BitField("authentication", 0, 8),
877 ByteField("max_key_size", 16),
878 ByteField("initiator_key_distribution", 0),
879 ByteField("responder_key_distribution", 0), ]
880
881
882class SM_Pairing_Response(Packet):
883 name = "Pairing Response"
884 fields_desc = [ByteEnumField("iocap", 3, {0: "DisplayOnly", 1: "DisplayYesNo", 2: "KeyboardOnly", 3: "NoInputNoOutput", 4: "KeyboardDisplay"}), # noqa: E501
885 ByteEnumField("oob", 0, {0: "Not Present", 1: "Present (from remote device)"}), # noqa: E501
886 BitField("authentication", 0, 8),
887 ByteField("max_key_size", 16),
888 ByteField("initiator_key_distribution", 0),
889 ByteField("responder_key_distribution", 0), ]
890
891
892class SM_Confirm(Packet):
893 name = "Pairing Confirm"
894 fields_desc = [StrFixedLenField("confirm", b'\x00' * 16, 16)]
895
896
897class SM_Random(Packet):
898 name = "Pairing Random"
899 fields_desc = [StrFixedLenField("random", b'\x00' * 16, 16)]
900
901
902class SM_Failed(Packet):
903 name = "Pairing Failed"
904 fields_desc = [XByteField("reason", 0)]
905
906
907class SM_Encryption_Information(Packet):
908 name = "Encryption Information"
909 fields_desc = [StrFixedLenField("ltk", b"\x00" * 16, 16), ]
910
911
912class SM_Master_Identification(Packet):
913 name = "Master Identification"
914 fields_desc = [XLEShortField("ediv", 0),
915 StrFixedLenField("rand", b'\x00' * 8, 8), ]
916
917
918class SM_Identity_Information(Packet):
919 name = "Identity Information"
920 fields_desc = [StrFixedLenField("irk", b'\x00' * 16, 16), ]
921
922
923class SM_Identity_Address_Information(Packet):
924 name = "Identity Address Information"
925 fields_desc = [ByteEnumField("addr_type", 0, {0: "public"}),
926 LEMACField("addr", None), ]
927 deprecated_fields = {
928 "atype": ("addr_type", "2.7.0"),
929 "address": ("addr", "2.7.0"),
930 }
931
932
933class SM_Signing_Information(Packet):
934 name = "Signing Information"
935 fields_desc = [StrFixedLenField("csrk", b'\x00' * 16, 16), ]
936
937
938class SM_Security_Request(Packet):
939 name = "Security Request"
940 fields_desc = [BitField("auth_req", 0, 8), ]
941
942
943class SM_Public_Key(Packet):
944 name = "Public Key"
945 fields_desc = [StrFixedLenField("key_x", b'\x00' * 32, 32),
946 StrFixedLenField("key_y", b'\x00' * 32, 32), ]
947
948
949class SM_DHKey_Check(Packet):
950 name = "DHKey Check"
951 fields_desc = [StrFixedLenField("dhkey_check", b'\x00' * 16, 16), ]
952
953
954class SM_Keypress_Notification(Packet):
955 name = "Keypress Notification"
956 fields_desc = [ByteEnumField("notification_type", 0, {
957 0: "Passkey entry started",
958 1: "Passkey digit entered",
959 2: "Passkey digit erased",
960 3: "Passkey cleared",
961 4: "Passkey entry completed",
962 })]
963
964
965class EIR_Hdr(Packet):
966 name = "EIR Header"
967 fields_desc = [
968 LenField("len", None, fmt="B", adjust=lambda x: x + 1), # Add bytes mark # noqa: E501
969 # https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
970 ByteEnumField("type", 0, {
971 0x01: "flags",
972 0x02: "incomplete_list_16_bit_svc_uuids",
973 0x03: "complete_list_16_bit_svc_uuids",
974 0x04: "incomplete_list_32_bit_svc_uuids",
975 0x05: "complete_list_32_bit_svc_uuids",
976 0x06: "incomplete_list_128_bit_svc_uuids",
977 0x07: "complete_list_128_bit_svc_uuids",
978 0x08: "shortened_local_name",
979 0x09: "complete_local_name",
980 0x0a: "tx_power_level",
981 0x0d: "class_of_device",
982 0x0e: "simple_pairing_hash",
983 0x0f: "simple_pairing_rand",
984
985 0x10: "sec_mgr_tk",
986 0x11: "sec_mgr_oob_flags",
987 0x12: "slave_conn_intvl_range",
988 0x14: "list_16_bit_svc_sollication_uuids",
989 0x15: "list_128_bit_svc_sollication_uuids",
990 0x16: "svc_data_16_bit_uuid",
991 0x17: "pub_target_addr",
992 0x18: "rand_target_addr",
993 0x19: "appearance",
994 0x1a: "adv_intvl",
995 0x1b: "le_addr",
996 0x1c: "le_role",
997 0x1d: "simple_pairing_hash_256",
998 0x1e: "simple_pairing_rand_256",
999 0x1f: "list_32_bit_svc_sollication_uuids",
1000
1001 0x20: "svc_data_32_bit_uuid",
1002 0x21: "svc_data_128_bit_uuid",
1003 0x22: "sec_conn_confirm",
1004 0x23: "sec_conn_rand",
1005 0x24: "uri",
1006 0x25: "indoor_positioning",
1007 0x26: "transport_discovery",
1008 0x27: "le_supported_features",
1009 0x28: "channel_map_update",
1010 0x29: "mesh_pb_adv",
1011 0x2a: "mesh_message",
1012 0x2b: "mesh_beacon",
1013
1014 0x30: "broadcast_name",
1015
1016 0x3d: "3d_information",
1017
1018 0xff: "mfg_specific_data",
1019 }),
1020 ]
1021
1022 def mysummary(self):
1023 return self.sprintf("EIR %type%")
1024
1025 def guess_payload_class(self, payload):
1026 if self.len == 0:
1027 # For Extended_Inquiry_Response, stop when len=0
1028 return conf.padding_layer
1029 return super(EIR_Hdr, self).guess_payload_class(payload)
1030
1031
1032class EIR_Element(Packet):
1033 name = "EIR Element"
1034
1035 def extract_padding(self, s):
1036 # Needed to end each EIR_Element packet and make PacketListField work.
1037 return b'', s
1038
1039 @staticmethod
1040 def length_from(pkt):
1041 if not pkt.underlayer:
1042 warning("Missing an upper-layer")
1043 return 0
1044 # 'type' byte is included in the length, so subtract 1:
1045 return pkt.underlayer.len - 1
1046
1047
1048class EIR_Raw(EIR_Element):
1049 name = "EIR Raw"
1050 fields_desc = [
1051 StrLenField("data", "", length_from=EIR_Element.length_from)
1052 ]
1053
1054
1055class EIR_Flags(EIR_Element):
1056 name = "Flags"
1057 fields_desc = [
1058 FlagsField("flags", 0x2, 8,
1059 ["limited_disc_mode", "general_disc_mode",
1060 "br_edr_not_supported", "simul_le_br_edr_ctrl",
1061 "simul_le_br_edr_host"] + 3 * ["reserved"])
1062 ]
1063
1064
1065class EIR_CompleteList16BitServiceUUIDs(EIR_Element):
1066 name = "Complete list of 16-bit service UUIDs"
1067 fields_desc = [
1068 # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members
1069 FieldListField("svc_uuids", None, XLEShortField("uuid", 0),
1070 length_from=EIR_Element.length_from)
1071 ]
1072
1073
1074class EIR_IncompleteList16BitServiceUUIDs(EIR_CompleteList16BitServiceUUIDs):
1075 name = "Incomplete list of 16-bit service UUIDs"
1076
1077
1078class EIR_CompleteList32BitServiceUUIDs(EIR_Element):
1079 name = 'Complete list of 32-bit service UUIDs'
1080 fields_desc = [
1081 # https://www.bluetooth.com/specifications/assigned-numbers
1082 FieldListField('svc_uuids', None, XLEIntField('uuid', 0),
1083 length_from=EIR_Element.length_from)
1084 ]
1085
1086
1087class EIR_IncompleteList32BitServiceUUIDs(EIR_CompleteList32BitServiceUUIDs):
1088 name = 'Incomplete list of 32-bit service UUIDs'
1089
1090
1091class EIR_CompleteList128BitServiceUUIDs(EIR_Element):
1092 name = "Complete list of 128-bit service UUIDs"
1093 fields_desc = [
1094 FieldListField("svc_uuids", None,
1095 UUIDField("uuid", None, uuid_fmt=UUIDField.FORMAT_REV),
1096 length_from=EIR_Element.length_from)
1097 ]
1098
1099
1100class EIR_IncompleteList128BitServiceUUIDs(EIR_CompleteList128BitServiceUUIDs):
1101 name = "Incomplete list of 128-bit service UUIDs"
1102
1103
1104class EIR_CompleteLocalName(EIR_Element):
1105 name = "Complete Local Name"
1106 fields_desc = [
1107 StrLenField("local_name", "", length_from=EIR_Element.length_from)
1108 ]
1109
1110
1111class EIR_ShortenedLocalName(EIR_CompleteLocalName):
1112 name = "Shortened Local Name"
1113
1114
1115class EIR_TX_Power_Level(EIR_Element):
1116 name = "TX Power Level"
1117 fields_desc = [SignedByteField("level", 0)]
1118
1119
1120class EIR_ClassOfDevice(EIR_Element):
1121 name = 'Class of device'
1122 fields_desc = [
1123 FlagsField('major_service_classes', 0, 11, [
1124 'limited_discoverable_mode',
1125 'le_audio',
1126 'reserved',
1127 'positioning',
1128 'networking',
1129 'rendering',
1130 'capturing',
1131 'object_transfer',
1132 'audio',
1133 'telephony',
1134 'information'
1135 ], tot_size=-3),
1136 BitEnumField('major_device_class', 0, 5, {
1137 0x00: 'miscellaneous',
1138 0x01: 'computer',
1139 0x02: 'phone',
1140 0x03: 'lan',
1141 0x04: 'audio_video',
1142 0x05: 'peripheral',
1143 0x06: 'imaging',
1144 0x07: 'wearable',
1145 0x08: 'toy',
1146 0x09: 'health',
1147 0x1f: 'uncategorized'
1148 }),
1149 BitField('minor_device_class', 0, 6),
1150 BitField('fixed', 0, 2, end_tot_size=-3)
1151 ]
1152
1153
1154class EIR_SecureSimplePairingHashC192(EIR_Element):
1155 name = 'Secure Simple Pairing Hash C-192'
1156 fields_desc = [NBytesField('hash', 0, 16)]
1157
1158
1159class EIR_SecureSimplePairingRandomizerR192(EIR_Element):
1160 name = 'Secure Simple Pairing Randomizer R-192'
1161 fields_desc = [NBytesField('randomizer', 0, 16)]
1162
1163
1164class EIR_SecurityManagerOOBFlags(EIR_Element):
1165 name = 'Security Manager Out of Band Flags'
1166 fields_desc = [
1167 BitField('oob_flags_field', 0, 1),
1168 BitField('le_supported', 0, 1),
1169 BitField('previously_used', 0, 1),
1170 BitField('address_type', 0, 1),
1171 BitField('reserved', 0, 4)
1172 ]
1173
1174
1175class EIR_PeripheralConnectionIntervalRange(EIR_Element):
1176 name = 'Peripheral Connection Interval Range'
1177 fields_desc = [
1178 LEShortField('conn_interval_min', 0xFFFF),
1179 LEShortField('conn_interval_max', 0xFFFF)
1180 ]
1181
1182
1183class EIR_Manufacturer_Specific_Data(EIR_Element):
1184 name = "EIR Manufacturer Specific Data"
1185 deprecated_fields = {
1186 "company_id": ("company_identifier", "2.6.2"),
1187 }
1188 fields_desc = [
1189 # https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
1190 LEShortEnumField("company_identifier", None,
1191 BLUETOOTH_CORE_COMPANY_IDENTIFIERS),
1192 ]
1193
1194 registered_magic_payloads = {}
1195
1196 @classmethod
1197 def register_magic_payload(cls, payload_cls, magic_check=None):
1198 """
1199 Registers a payload type that uses magic data.
1200
1201 Traditional payloads require registration of a Bluetooth Company ID
1202 (requires company membership of the Bluetooth SIG), or a Bluetooth
1203 Short UUID (requires a once-off payment).
1204
1205 There are alternatives which don't require registration (such as
1206 128-bit UUIDs), but the biggest consumer of energy in a beacon is the
1207 radio -- so the energy consumption of a beacon is proportional to the
1208 number of bytes in a beacon frame.
1209
1210 Some beacon formats side-step this issue by using the Company ID of
1211 their beacon hardware manufacturer, and adding a "magic data sequence"
1212 at the start of the Manufacturer Specific Data field.
1213
1214 Examples of this are AltBeacon and GeoBeacon.
1215
1216 For an example of this method in use, see ``scapy.contrib.altbeacon``.
1217
1218 :param Type[scapy.packet.Packet] payload_cls:
1219 A reference to a Packet subclass to register as a payload.
1220 :param Callable[[bytes], bool] magic_check:
1221 (optional) callable to use to if a payload should be associated
1222 with this type. If not supplied, ``payload_cls.magic_check`` is
1223 used instead.
1224 :raises TypeError: If ``magic_check`` is not specified,
1225 and ``payload_cls.magic_check`` is not implemented.
1226 """
1227 if magic_check is None:
1228 if hasattr(payload_cls, "magic_check"):
1229 magic_check = payload_cls.magic_check
1230 else:
1231 raise TypeError("magic_check not specified, and {} has no "
1232 "attribute magic_check".format(payload_cls))
1233
1234 cls.registered_magic_payloads[payload_cls] = magic_check
1235
1236 def default_payload_class(self, payload):
1237 for cls, check in (
1238 EIR_Manufacturer_Specific_Data.registered_magic_payloads.items()
1239 ):
1240 if check(payload):
1241 return cls
1242
1243 return Packet.default_payload_class(self, payload)
1244
1245 def extract_padding(self, s):
1246 # Needed to end each EIR_Element packet and make PacketListField work.
1247 plen = EIR_Element.length_from(self) - 2
1248 return s[:plen], s[plen:]
1249
1250
1251class EIR_Device_ID(EIR_Element):
1252 name = "Device ID"
1253 fields_desc = [
1254 XLEShortField("vendor_id_source", 0),
1255 XLEShortField("vendor_id", 0),
1256 XLEShortField("product_id", 0),
1257 XLEShortField("version", 0),
1258 ]
1259
1260
1261class EIR_ServiceSolicitation16BitUUID(EIR_Element):
1262 name = "EIR Service Solicitation - 16-bit UUID"
1263 fields_desc = [
1264 XLEShortField("svc_uuid", None)
1265 ]
1266
1267 def extract_padding(self, s):
1268 # Needed to end each EIR_Element packet and make PacketListField work.
1269 plen = EIR_Element.length_from(self) - 2
1270 return s[:plen], s[plen:]
1271
1272
1273class EIR_ServiceSolicitation128BitUUID(EIR_Element):
1274 name = "EIR Service Solicitation - 128-bit UUID"
1275 fields_desc = [
1276 UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)
1277 ]
1278
1279 def extract_padding(self, s):
1280 # Needed to end each EIR_Element packet and make PacketListField work.
1281 plen = EIR_Element.length_from(self) - 2
1282 return s[:plen], s[plen:]
1283
1284
1285class EIR_ServiceData16BitUUID(EIR_Element):
1286 name = "EIR Service Data - 16-bit UUID"
1287 fields_desc = [
1288 # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members
1289 XLEShortField("svc_uuid", None),
1290 ]
1291
1292 def extract_padding(self, s):
1293 # Needed to end each EIR_Element packet and make PacketListField work.
1294 plen = EIR_Element.length_from(self) - 2
1295 return s[:plen], s[plen:]
1296
1297
1298class EIR_PublicTargetAddress(EIR_Element):
1299 name = "Public Target Address"
1300 fields_desc = [
1301 LEMACField('bd_addr', None)
1302 ]
1303
1304
1305class EIR_RandomTargetAddress(EIR_Element):
1306 name = "Random Target Address"
1307 fields_desc = [
1308 LEMACField('bd_addr', None)
1309 ]
1310
1311
1312class EIR_AdvertisingInterval(EIR_Element):
1313 name = "Advertising Interval"
1314 fields_desc = [
1315 MultipleTypeField(
1316 [
1317 (ByteField("advertising_interval", 0),
1318 lambda p: p.underlayer.len - 1 == 1),
1319 (LEShortField("advertising_interval", 0),
1320 lambda p: p.underlayer.len - 1 == 2),
1321 (LEThreeBytesField("advertising_interval", 0),
1322 lambda p: p.underlayer.len - 1 == 3),
1323 (LEIntField("advertising_interval", 0),
1324 lambda p: p.underlayer.len - 1 == 4),
1325 ],
1326 LEShortField("advertising_interval", 0)
1327 )
1328 ]
1329
1330
1331class EIR_LEBluetoothDeviceAddress(EIR_Element):
1332 name = "LE Bluetooth Device Address"
1333 fields_desc = [
1334 XBitField('reserved', 0, 7, tot_size=-1),
1335 BitEnumField('addr_type', 0, 1, end_tot_size=-1, enum={
1336 0x0: 'Public',
1337 0x1: 'Random'
1338 }),
1339 LEMACField('bd_addr', None)
1340 ]
1341
1342
1343class EIR_LERole(EIR_Element):
1344 name = "LE Role"
1345 fields_desc = [
1346 ByteEnumField("role", 0, {
1347 0: "Only Peripheral Role supported",
1348 1: "Only Central Role supported",
1349 2: "Peripheral and Central Role supported, "
1350 "Peripheral Role preferred for connection establishment",
1351 3: "Peripheral and Central Role supported, "
1352 "Central Role preferred for connection establishment",
1353 }),
1354 ]
1355
1356
1357class EIR_BroadcastName(EIR_Element):
1358 name = "Broadcast Name"
1359 fields_desc = [
1360 StrLenField("broadcast_name", "",
1361 length_from=EIR_Element.length_from)
1362 ]
1363
1364
1365class EIR_3DInformation(EIR_Element):
1366 name = "3D Information"
1367 fields_desc = [
1368 BitField("factory_test_mode", 0, 1, tot_size=-1),
1369 BitField("reserved", 0, 4),
1370 BitField("send_battery_level_on_startup", 0, 1),
1371 BitField("battery_level_reporting", 0, 1),
1372 BitField("association_notification", 0, 1, end_tot_size=-1),
1373 ByteField("path_loss_threshold", 0),
1374 ]
1375
1376
1377class EIR_Appearance(EIR_Element):
1378 name = "EIR_Appearance"
1379 fields_desc = [
1380 BitEnumField('category', 0, 10, tot_size=-2, enum={
1381 0x000: 'Unknown',
1382 0x001: 'Phone',
1383 0x002: 'Computer',
1384 0x003: 'Watch',
1385 0x004: 'Clock',
1386 0x005: 'Display',
1387 0x006: 'Remote Control',
1388 0x007: 'Eyeglasses',
1389 0x008: 'Tag',
1390 0x009: 'Keyring',
1391 0x00A: 'Media Player',
1392 0x00B: 'Barcode Scanner',
1393 0x00C: 'Thermometer',
1394 0x00D: 'Heart Rate Sensor',
1395 0x00E: 'Blood Pressure',
1396 0x00F: 'Human Interface Device',
1397 0x010: 'Glucose Meter',
1398 0x011: 'Running Walking Sensor',
1399 0x012: 'Cycling',
1400 0x013: 'Control Device',
1401 0x014: 'Network Device',
1402 0x015: 'Sensor',
1403 0x016: 'Light Fixtures',
1404 0x017: 'Fan',
1405 0x018: 'HVAC',
1406 0x019: 'Air Conditioning',
1407 0x01A: 'Humidifier',
1408 0x01B: 'Heating',
1409 0x01C: 'Access Control',
1410 0x01D: 'Motorized Device',
1411 0x01E: 'Power Device',
1412 0x01F: 'Light Source',
1413 0x020: 'Window Covering',
1414 0x021: 'Audio Sink',
1415 0x022: 'Audio Source',
1416 0x023: 'Motorized Vehicle',
1417 0x024: 'Domestic Appliance',
1418 0x025: 'Wearable Audio Device',
1419 0x026: 'Aircraft',
1420 0x027: 'AV Equipment',
1421 0x028: 'Display Equipment',
1422 0x029: 'Hearing aid',
1423 0x02A: 'Gaming',
1424 0x02B: 'Signage',
1425 0x031: 'Pulse Oximeter',
1426 0x032: 'Weight Scale',
1427 0x033: 'Personal Mobility Device',
1428 0x034: 'Continuous Glucose Monitor',
1429 0x035: 'Insulin Pump',
1430 0x036: 'Medication Delivery',
1431 0x037: 'Spirometer',
1432 0x051: 'Outdoor Sports Activity'
1433 }),
1434 XBitField('subcategory', 0, 6, end_tot_size=-2)
1435 ]
1436
1437 @property
1438 def appearance(self):
1439 return (self.category << 6) + self.subcategory
1440
1441
1442class EIR_ServiceData32BitUUID(EIR_Element):
1443 name = 'EIR Service Data - 32-bit UUID'
1444 fields_desc = [
1445 XLEIntField('svc_uuid', 0),
1446 ]
1447
1448 def extract_padding(self, s):
1449 # Needed to end each EIR_Element packet and make PacketListField work.
1450 plen = EIR_Element.length_from(self) - 4
1451 return s[:plen], s[plen:]
1452
1453
1454class EIR_ServiceData128BitUUID(EIR_Element):
1455 name = 'EIR Service Data - 128-bit UUID'
1456 fields_desc = [
1457 UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)
1458 ]
1459
1460 def extract_padding(self, s):
1461 # Needed to end each EIR_Element packet and make PacketListField work.
1462 plen = EIR_Element.length_from(self) - 16
1463 return s[:plen], s[plen:]
1464
1465
1466class EIR_URI(EIR_Element):
1467 name = 'EIR URI'
1468 fields_desc = [
1469 ByteEnumField('scheme', 0, {
1470 0x01: '',
1471 0x02: 'aaa:',
1472 0x03: 'aaas:',
1473 0x04: 'about:',
1474 0x05: 'acap:',
1475 0x06: 'acct:',
1476 0x07: 'cap:',
1477 0x08: 'cid:',
1478 0x09: 'coap:',
1479 0x0A: 'coaps:',
1480 0x0B: 'crid:',
1481 0x0C: 'data:',
1482 0x0D: 'dav:',
1483 0x0E: 'dict:',
1484 0x0F: 'dns:',
1485 0x10: 'file:',
1486 0x11: 'ftp:',
1487 0x12: 'geo:',
1488 0x13: 'go:',
1489 0x14: 'gopher:',
1490 0x15: 'h323:',
1491 0x16: 'http:',
1492 0x17: 'https:',
1493 0x18: 'iax:',
1494 0x19: 'icap:',
1495 0x1A: 'im:',
1496 0x1B: 'imap:',
1497 0x1C: 'info:',
1498 0x1D: 'ipp:',
1499 0x1E: 'ipps:',
1500 0x1F: 'iris:',
1501 0x20: 'iris.beep:',
1502 0x21: 'iris.xpc:',
1503 0x22: 'iris.xpcs:',
1504 0x23: 'iris.lwz:',
1505 0x24: 'jabber:',
1506 0x25: 'ldap:',
1507 0x26: 'mailto:',
1508 0x27: 'mid:',
1509 0x28: 'msrp:',
1510 0x29: 'msrps:',
1511 0x2A: 'mtqp:',
1512 0x2B: 'mupdate:',
1513 0x2C: 'news:',
1514 0x2D: 'nfs:',
1515 0x2E: 'ni:',
1516 0x2F: 'nih:',
1517 0x30: 'nntp:',
1518 0x31: 'opaquelocktoken:',
1519 0x32: 'pop:',
1520 0x33: 'pres:',
1521 0x34: 'reload:',
1522 0x35: 'rtsp:',
1523 0x36: 'rtsps:',
1524 0x37: 'rtspu:',
1525 0x38: 'service:',
1526 0x39: 'session:',
1527 0x3A: 'shttp:',
1528 0x3B: 'sieve:',
1529 0x3C: 'sip:',
1530 0x3D: 'sips:',
1531 0x3E: 'sms:',
1532 0x3F: 'snmp:',
1533 0x40: 'soap.beep:',
1534 0x41: 'soap.beeps:',
1535 0x42: 'stun:',
1536 0x43: 'stuns:',
1537 0x44: 'tag:',
1538 0x45: 'tel:',
1539 0x46: 'telnet:',
1540 0x47: 'tftp:',
1541 0x48: 'thismessage:',
1542 0x49: 'tn3270:',
1543 0x4A: 'tip:',
1544 0x4B: 'turn:',
1545 0x4C: 'turns:',
1546 0x4D: 'tv:',
1547 0x4E: 'urn:',
1548 0x4F: 'vemmi:',
1549 0x50: 'ws:',
1550 0x51: 'wss:',
1551 0x52: 'xcon:',
1552 0x53: 'xconuserid:',
1553 0x54: 'xmlrpc.beep:',
1554 0x55: 'xmlrpc.beeps:',
1555 0x56: 'xmpp:',
1556 0x57: 'z39.50r:',
1557 0x58: 'z39.50s:',
1558 0x59: 'acr:',
1559 0x5A: 'adiumxtra:',
1560 0x5B: 'afp:',
1561 0x5C: 'afs:',
1562 0x5D: 'aim:',
1563 0x5E: 'apt:',
1564 0x5F: 'attachment:',
1565 0x60: 'aw:',
1566 0x61: 'barion:',
1567 0x62: 'beshare:',
1568 0x63: 'bitcoin:',
1569 0x64: 'bolo:',
1570 0x65: 'callto:',
1571 0x66: 'chrome:',
1572 0x67: 'chromeextension:',
1573 0x68: 'comeventbriteattendee:',
1574 0x69: 'content:',
1575 0x6A: 'cvs:',
1576 0x6B: 'dlnaplaysingle:',
1577 0x6C: 'dlnaplaycontainer:',
1578 0x6D: 'dtn:',
1579 0x6E: 'dvb:',
1580 0x6F: 'ed2k:',
1581 0x70: 'facetime:',
1582 0x71: 'feed:',
1583 0x72: 'feedready:',
1584 0x73: 'finger:',
1585 0x74: 'fish:',
1586 0x75: 'gg:',
1587 0x76: 'git:',
1588 0x77: 'gizmoproject:',
1589 0x78: 'gtalk:',
1590 0x79: 'ham:',
1591 0x7A: 'hcp:',
1592 0x7B: 'icon:',
1593 0x7C: 'ipn:',
1594 0x7D: 'irc:',
1595 0x7E: 'irc6:',
1596 0x7F: 'ircs:',
1597 0x80: 'itms:',
1598 0x81: 'jar:',
1599 0x82: 'jms:',
1600 0x83: 'keyparc:',
1601 0x84: 'lastfm:',
1602 0x85: 'ldaps:',
1603 0x86: 'magnet:',
1604 0x87: 'maps:',
1605 0x88: 'market:',
1606 0x89: 'message:',
1607 0x8A: 'mms:',
1608 0x8B: 'mshelp:',
1609 0x8C: 'mssettingspower:',
1610 0x8D: 'msnim:',
1611 0x8E: 'mumble:',
1612 0x8F: 'mvn:',
1613 0x90: 'notes:',
1614 0x91: 'oid:',
1615 0x92: 'palm:',
1616 0x93: 'paparazzi:',
1617 0x94: 'pkcs11:',
1618 0x95: 'platform:',
1619 0x96: 'proxy:',
1620 0x97: 'psyc:',
1621 0x98: 'query:',
1622 0x99: 'res:',
1623 0x9A: 'resource:',
1624 0x9B: 'rmi:',
1625 0x9C: 'rsync:',
1626 0x9D: 'rtmfp:',
1627 0x9E: 'rtmp:',
1628 0x9F: 'secondlife:',
1629 0xA0: 'sftp:',
1630 0xA1: 'sgn:',
1631 0xA2: 'skype:',
1632 0xA3: 'smb:',
1633 0xA4: 'smtp:',
1634 0xA5: 'soldat:',
1635 0xA6: 'spotify:',
1636 0xA7: 'ssh:',
1637 0xA8: 'steam:',
1638 0xA9: 'submit:',
1639 0xAA: 'svn:',
1640 0xAB: 'teamspeak:',
1641 0xAC: 'teliaeid:',
1642 0xAD: 'things:',
1643 0xAE: 'udp:',
1644 0xAF: 'unreal:',
1645 0xB0: 'ut2004:',
1646 0xB1: 'ventrilo:',
1647 0xB2: 'viewsource:',
1648 0xB3: 'webcal:',
1649 0xB4: 'wtai:',
1650 0xB5: 'wyciwyg:',
1651 0xB6: 'xfire:',
1652 0xB7: 'xri:',
1653 0xB8: 'ymsgr:',
1654 0xB9: 'example:',
1655 0xBA: 'mssettingscloudstorage:'
1656 }),
1657 StrLenField('uri_hier_part', None, length_from=EIR_Element.length_from)
1658 ]
1659
1660 @property
1661 def uri(self):
1662 return EIR_URI.scheme.i2s[self.scheme] + self.uri_hier_part.decode('utf-8')
1663
1664
1665class HCI_Command_Hdr(Packet):
1666 name = "HCI Command header"
1667 fields_desc = [XBitField("ogf", 0, 6, tot_size=-2),
1668 XBitField("ocf", 0, 10, end_tot_size=-2),
1669 LenField("len", None, fmt="B"), ]
1670
1671 def answers(self, other):
1672 return False
1673
1674 @property
1675 def opcode(self):
1676 return (self.ogf << 10) + self.ocf
1677
1678 def post_build(self, p, pay):
1679 p += pay
1680 if self.len is None:
1681 p = p[:2] + struct.pack("B", len(pay)) + p[3:]
1682 return p
1683
1684
1685# BUETOOTH CORE SPECIFICATION 5.4 | Vol 3, Part C
1686# 8 EXTENDED INQUIRY RESPONSE
1687
1688class HCI_Extended_Inquiry_Response(Packet):
1689 fields_desc = [
1690 PadField(
1691 PacketListField(
1692 "eir_data", [],
1693 next_cls_cb=lambda *args: (
1694 (not args[2] or args[2].len != 0) and EIR_Hdr or conf.raw_layer
1695 )
1696 ),
1697 align=31, padwith=b"\0",
1698 ),
1699 ]
1700
1701
1702# BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E
1703# 7 HCI COMMANDS AND EVENTS
1704# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01
1705
1706class HCI_Cmd_Inquiry(Packet):
1707 """
1708 7.1.1 Inquiry command
1709 """
1710 name = "HCI_Inquiry"
1711 fields_desc = [XLE3BytesField("lap", 0x9E8B33),
1712 ByteField("inquiry_length", 0),
1713 ByteField("num_responses", 0)]
1714
1715
1716class HCI_Cmd_Inquiry_Cancel(Packet):
1717 """
1718 7.1.2 Inquiry Cancel command
1719 """
1720 name = "HCI_Inquiry_Cancel"
1721
1722
1723class HCI_Cmd_Periodic_Inquiry_Mode(Packet):
1724 """
1725 7.1.3 Periodic Inquiry Mode command
1726 """
1727 name = "HCI_Periodic_Inquiry_Mode"
1728 fields_desc = [LEShortField("max_period_length", 0x0003),
1729 LEShortField("min_period_length", 0x0002),
1730 XLE3BytesField("lap", 0x9E8B33),
1731 ByteField("inquiry_length", 0),
1732 ByteField("num_responses", 0)]
1733
1734
1735class HCI_Cmd_Exit_Peiodic_Inquiry_Mode(Packet):
1736 """
1737 7.1.4 Exit Periodic Inquiry Mode command
1738 """
1739 name = "HCI_Exit_Periodic_Inquiry_Mode"
1740
1741
1742class HCI_Cmd_Create_Connection(Packet):
1743 """
1744 7.1.5 Create Connection command
1745 """
1746 name = "HCI_Create_Connection"
1747 fields_desc = [LEMACField("bd_addr", None),
1748 LEShortField("packet_type", 0xcc18),
1749 ByteField("page_scan_repetition_mode", 0x02),
1750 ByteField("reserved", 0x0),
1751 LEShortField("clock_offset", 0x0),
1752 ByteField("allow_role_switch", 0x1), ]
1753
1754
1755class HCI_Cmd_Disconnect(Packet):
1756 """
1757 7.1.6 Disconnect command
1758 """
1759 name = "HCI_Disconnect"
1760 fields_desc = [XLEShortField("handle", 0),
1761 ByteField("reason", 0x13), ]
1762
1763
1764class HCI_Cmd_Create_Connection_Cancel(Packet):
1765 """
1766 7.1.7 Create Connection Cancel command
1767 """
1768 name = "HCI_Create_Connection_Cancel"
1769 fields_desc = [LEMACField("bd_addr", None), ]
1770
1771
1772class HCI_Cmd_Accept_Connection_Request(Packet):
1773 """
1774 7.1.8 Accept Connection Request command
1775 """
1776 name = "HCI_Accept_Connection_Request"
1777 fields_desc = [LEMACField("bd_addr", None),
1778 ByteField("role", 0x1), ]
1779
1780
1781class HCI_Cmd_Reject_Connection_Response(Packet):
1782 """
1783 7.1.9 Reject Connection Request command
1784 """
1785 name = "HCI_Reject_Connection_Response"
1786 fields_desc = [LEMACField("bd_addr", None),
1787 ByteField("reason", 0x1), ]
1788
1789
1790class HCI_Cmd_Link_Key_Request_Reply(Packet):
1791 """
1792 7.1.10 Link Key Request Reply command
1793 """
1794 name = "HCI_Link_Key_Request_Reply"
1795 fields_desc = [LEMACField("bd_addr", None),
1796 NBytesField("link_key", None, 16), ]
1797
1798
1799class HCI_Cmd_Link_Key_Request_Negative_Reply(Packet):
1800 """
1801 7.1.11 Link Key Request Negative Reply command
1802 """
1803 name = "HCI_Link_Key_Request_Negative_Reply"
1804 fields_desc = [LEMACField("bd_addr", None), ]
1805
1806
1807class HCI_Cmd_PIN_Code_Request_Reply(Packet):
1808 """
1809 7.1.12 PIN Code Request Reply command
1810 """
1811 name = "HCI_PIN_Code_Request_Reply"
1812 fields_desc = [LEMACField("bd_addr", None),
1813 ByteField("pin_code_length", 7),
1814 NBytesField("pin_code", b"\x00" * 16, sz=16), ]
1815
1816
1817class HCI_Cmd_PIN_Code_Request_Negative_Reply(Packet):
1818 """
1819 7.1.13 PIN Code Request Negative Reply command
1820 """
1821 name = "HCI_PIN_Code_Request_Negative_Reply"
1822 fields_desc = [LEMACField("bd_addr", None), ]
1823
1824
1825class HCI_Cmd_Change_Connection_Packet_Type(Packet):
1826 """
1827 7.1.14 Change Connection Packet Type command
1828 """
1829 name = "HCI_Cmd_Change_Connection_Packet_Type"
1830 fields_desc = [XLEShortField("connection_handle", None),
1831 LEShortField("packet_type", 0), ]
1832
1833
1834class HCI_Cmd_Authentication_Requested(Packet):
1835 """
1836 7.1.15 Authentication Requested command
1837 """
1838 name = "HCI_Authentication_Requested"
1839 fields_desc = [LEShortField("handle", 0)]
1840
1841
1842class HCI_Cmd_Set_Connection_Encryption(Packet):
1843 """
1844 7.1.16 Set Connection Encryption command
1845 """
1846 name = "HCI_Set_Connection_Encryption"
1847 fields_desc = [LEShortField("handle", 0), ByteField("encryption_enable", 0)]
1848
1849
1850class HCI_Cmd_Change_Connection_Link_Key(Packet):
1851 """
1852 7.1.17 Change Connection Link Key command
1853 """
1854 name = "HCI_Change_Connection_Link_Key"
1855 fields_desc = [LEShortField("handle", 0), ]
1856
1857
1858class HCI_Cmd_Link_Key_Selection(Packet):
1859 """
1860 7.1.18 Change Connection Link Key command
1861 """
1862 name = "HCI_Cmd_Link_Key_Selection"
1863 fields_desc = [ByteEnumField("handle", 0, {0: "Use semi-permanent Link Keys",
1864 1: "Use Temporary Link Key", }), ]
1865
1866
1867class HCI_Cmd_Remote_Name_Request(Packet):
1868 """
1869 7.1.19 Remote Name Request command
1870 """
1871 name = "HCI_Remote_Name_Request"
1872 fields_desc = [LEMACField("bd_addr", None),
1873 ByteField("page_scan_repetition_mode", 0x02),
1874 ByteField("reserved", 0x0),
1875 LEShortField("clock_offset", 0x0), ]
1876
1877
1878class HCI_Cmd_Remote_Name_Request_Cancel(Packet):
1879 """
1880 7.1.20 Remote Name Request Cancel command
1881 """
1882 name = "HCI_Remote_Name_Request_Cancel"
1883 fields_desc = [LEMACField("bd_addr", None), ]
1884
1885
1886class HCI_Cmd_Read_Remote_Supported_Features(Packet):
1887 """
1888 7.1.21 Read Remote Supported Features command
1889 """
1890 name = "HCI_Read_Remote_Supported_Features"
1891 fields_desc = [LEShortField("connection_handle", None), ]
1892
1893
1894class HCI_Cmd_Read_Remote_Extended_Features(Packet):
1895 """
1896 7.1.22 Read Remote Extended Features command
1897 """
1898 name = "HCI_Read_Remote_Supported_Features"
1899 fields_desc = [LEShortField("connection_handle", None),
1900 ByteField("page_number", None), ]
1901
1902
1903class HCI_Cmd_IO_Capability_Request_Reply(Packet):
1904 """
1905 7.1.29 IO Capability Request Reply command
1906 """
1907 name = "HCI_Read_Remote_Supported_Features"
1908 fields_desc = [LEMACField("bd_addr", None),
1909 ByteEnumField("io_capability", None, {0x00: "DisplayOnly",
1910 0x01: "DisplayYesNo",
1911 0x02: "KeyboardOnly",
1912 0x03: "NoInputNoOutput", }),
1913 ByteEnumField("oob_data_present", None, {0x00: "Not Present",
1914 0x01: "P-192",
1915 0x02: "P-256",
1916 0x03: "P-192 + P-256", }),
1917 ByteEnumField("authentication_requirement", None,
1918 {0x00: "MITM Not Required",
1919 0x01: "MITM Required, No Bonding",
1920 0x02: "MITM Not Required + Dedicated Pairing",
1921 0x03: "MITM Required + Dedicated Pairing",
1922 0x04: "MITM Not Required, General Bonding",
1923 0x05: "MITM Required + General Bonding"}), ]
1924
1925
1926class HCI_Cmd_User_Confirmation_Request_Reply(Packet):
1927 """
1928 7.1.30 User Confirmation Request Reply command
1929 """
1930 name = "HCI_User_Confirmation_Request_Reply"
1931 fields_desc = [LEMACField("bd_addr", None), ]
1932
1933
1934class HCI_Cmd_User_Confirmation_Request_Negative_Reply(Packet):
1935 """
1936 7.1.31 User Confirmation Request Negative Reply command
1937 """
1938 name = "HCI_User_Confirmation_Request_Negative_Reply"
1939 fields_desc = [LEMACField("bd_addr", None), ]
1940
1941
1942class HCI_Cmd_User_Passkey_Request_Reply(Packet):
1943 """
1944 7.1.32 User Passkey Request Reply command
1945 """
1946 name = "HCI_User_Passkey_Request_Reply"
1947 fields_desc = [LEMACField("bd_addr", None),
1948 LEIntField("numeric_value", None), ]
1949
1950
1951class HCI_Cmd_User_Passkey_Request_Negative_Reply(Packet):
1952 """
1953 7.1.33 User Passkey Request Negative Reply command
1954 """
1955 name = "HCI_User_Passkey_Request_Negative_Reply"
1956 fields_desc = [LEMACField("bd_addr", None), ]
1957
1958
1959class HCI_Cmd_Remote_OOB_Data_Request_Reply(Packet):
1960 """
1961 7.1.34 Remote OOB Data Request Reply command
1962 """
1963 name = "HCI_Remote_OOB_Data_Request_Reply"
1964 fields_desc = [LEMACField("bd_addr", None),
1965 NBytesField("C", b"\x00" * 16, sz=16),
1966 NBytesField("R", b"\x00" * 16, sz=16), ]
1967
1968
1969class HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply(Packet):
1970 """
1971 7.1.35 Remote OOB Data Request Negative Reply command
1972 """
1973 name = "HCI_Remote_OOB_Data_Request_Negative_Reply"
1974 fields_desc = [LEMACField("bd_addr", None), ]
1975
1976
1977# 7.2 Link Policy commands, the OGF is defined as 0x02
1978
1979class HCI_Cmd_Hold_Mode(Packet):
1980 name = "HCI_Hold_Mode"
1981 fields_desc = [LEShortField("connection_handle", 0),
1982 LEShortField("hold_mode_max_interval", 0x0002),
1983 LEShortField("hold_mode_min_interval", 0x0002), ]
1984
1985
1986# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03
1987
1988class HCI_Cmd_Set_Event_Mask(Packet):
1989 """
1990 7.3.1 Set Event Mask command
1991 """
1992 name = "HCI_Set_Event_Mask"
1993 fields_desc = [StrFixedLenField("mask", b"\xff\xff\xfb\xff\x07\xf8\xbf\x3d", 8)] # noqa: E501
1994
1995
1996class HCI_Cmd_Reset(Packet):
1997 """
1998 7.3.2 Reset command
1999 """
2000 name = "HCI_Reset"
2001
2002
2003class HCI_Cmd_Set_Event_Filter(Packet):
2004 """
2005 7.3.3 Set Event Filter command
2006 """
2007 name = "HCI_Set_Event_Filter"
2008 fields_desc = [ByteEnumField("type", 0, {0: "clear"}), ]
2009
2010
2011class HCI_Cmd_Write_Local_Name(Packet):
2012 """
2013 7.3.11 Write Local Name command
2014 """
2015 name = "HCI_Write_Local_Name"
2016 fields_desc = [StrFixedLenField('name', '', length=248)]
2017
2018
2019class HCI_Cmd_Read_Local_Name(Packet):
2020 """
2021 7.3.12 Read Local Name command
2022 """
2023 name = "HCI_Read_Local_Name"
2024
2025
2026class HCI_Cmd_Write_Connect_Accept_Timeout(Packet):
2027 name = "HCI_Write_Connection_Accept_Timeout"
2028 fields_desc = [LEShortField("timeout", 32000)] # 32000 slots is 20000 msec
2029
2030
2031class HCI_Cmd_Write_Extended_Inquiry_Response(Packet):
2032 name = "HCI_Write_Extended_Inquiry_Response"
2033 fields_desc = [ByteField("fec_required", 0),
2034 HCI_Extended_Inquiry_Response]
2035
2036
2037class HCI_Cmd_Read_LE_Host_Support(Packet):
2038 name = "HCI_Read_LE_Host_Support"
2039
2040
2041class HCI_Cmd_Write_LE_Host_Support(Packet):
2042 name = "HCI_Write_LE_Host_Support"
2043 fields_desc = [ByteField("supported", 1),
2044 ByteField("unused", 1), ]
2045
2046
2047# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04
2048
2049class HCI_Cmd_Read_Local_Version_Information(Packet):
2050 """
2051 7.4.1 Read Local Version Information command
2052 """
2053 name = "HCI_Read_Local_Version_Information"
2054
2055
2056class HCI_Cmd_Read_Local_Extended_Features(Packet):
2057 """
2058 7.4.4 Read Local Extended Features command
2059 """
2060 name = "HCI_Read_Local_Extended_Features"
2061 fields_desc = [ByteField("page_number", 0)]
2062
2063
2064class HCI_Cmd_Read_BD_Addr(Packet):
2065 """
2066 7.4.6 Read BD_ADDR command
2067 """
2068 name = "HCI_Read_BD_ADDR"
2069
2070
2071# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05
2072
2073class HCI_Cmd_Read_Link_Quality(Packet):
2074 name = "HCI_Read_Link_Quality"
2075 fields_desc = [LEShortField("handle", 0)]
2076
2077
2078class HCI_Cmd_Read_RSSI(Packet):
2079 name = "HCI_Read_RSSI"
2080 fields_desc = [LEShortField("handle", 0)]
2081
2082
2083# 7.6 TESTING COMMANDS, the OGF is defined as 0x06
2084
2085class HCI_Cmd_Read_Loopback_Mode(Packet):
2086 name = "HCI_Read_Loopback_Mode"
2087
2088
2089class HCI_Cmd_Write_Loopback_Mode(Packet):
2090 name = "HCI_Write_Loopback_Mode"
2091 fields_desc = [ByteEnumField("loopback_mode", 0,
2092 {0: "no loopback",
2093 1: "enable local loopback",
2094 2: "enable remote loopback"})]
2095
2096
2097# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08
2098
2099class HCI_Cmd_LE_Set_Event_Mask(Packet):
2100 name = 'HCI_LE_Set_Event_Mask'
2101 fields_desc = [StrFixedLenField('mask', b'\xff\xff\xff\xff\xff\x1f\x00\x00', 8)]
2102
2103
2104class HCI_Cmd_LE_Read_Buffer_Size_V1(Packet):
2105 name = "HCI_LE_Read_Buffer_Size [v1]"
2106
2107
2108class HCI_Cmd_LE_Read_Buffer_Size_V2(Packet):
2109 name = "HCI_LE_Read_Buffer_Size [v2]"
2110
2111
2112class HCI_Cmd_LE_Read_Local_Supported_Features(Packet):
2113 name = "HCI_LE_Read_Local_Supported_Features"
2114
2115
2116class HCI_Cmd_LE_Set_Random_Address(Packet):
2117 name = "HCI_LE_Set_Random_Address"
2118 fields_desc = [LEMACField("addr", None)]
2119 deprecated_fields = {"address": ("addr", "2.7.0")}
2120
2121
2122class HCI_Cmd_LE_Set_Advertising_Parameters(Packet):
2123 name = "HCI_LE_Set_Advertising_Parameters"
2124 fields_desc = [LEShortField("interval_min", 0x0800),
2125 LEShortField("interval_max", 0x0800),
2126 ByteEnumField("adv_type", 0, {
2127 0: "ADV_IND",
2128 1: "ADV_DIRECT_IND",
2129 2: "ADV_SCAN_IND",
2130 3: "ADV_NONCONN_IND",
2131 4: "ADV_DIRECT_IND_LOW"}),
2132 ByteEnumField("own_addr_type", 0, {
2133 0: "public",
2134 1: "random"}),
2135 ByteEnumField("peer_addr_type", 0, {
2136 0: "public",
2137 1: "random"}),
2138 LEMACField("peer_addr", None),
2139 ByteField("channel_map", 7),
2140 ByteEnumField("filter_policy", 0, {
2141 0: "all:all",
2142 1: "connect:all scan:whitelist",
2143 2: "connect:whitelist scan:all",
2144 3: "all:whitelist"}), ]
2145 deprecated_fields = {
2146 "oatype": ("own_addr_type", "2.7.0"),
2147 "datype": ("peer_addr_type", "2.7.0"),
2148 "daddr": ("peer_addr", "2.7.0"),
2149 }
2150
2151
2152class HCI_Cmd_LE_Set_Extended_Advertising_Parameters(Packet):
2153 name = 'HCI_LE_Set_Extended_Advertising_Parameters'
2154 fields_desc = [ByteField('handle', 0),
2155 LEShortField('properties', 19),
2156 LEThreeBytesField('pri_interval_min', 160),
2157 LEThreeBytesField('pri_interval_max', 160),
2158 ByteField('pri_channel_map', 7),
2159 ByteEnumField('own_addr_type', 0, {
2160 0: 'public',
2161 1: 'random',
2162 2: 'rpa_pub',
2163 3: 'rpa_rand'}),
2164 ByteEnumField('peer_addr_type', 0, {
2165 0: 'public',
2166 1: 'random',
2167 2: 'rpa_pub',
2168 3: 'rpa_rand'}),
2169 LEMACField('peer_addr', None),
2170 ByteEnumField("filter_policy", 0, {
2171 0: "all:all",
2172 1: "connect:all scan:whitelist",
2173 2: "connect:whitelist scan:all",
2174 3: "all:whitelist"}),
2175 SignedByteField('tx_power', 127),
2176 ByteEnumField('pri_phy', 1, {1: '1M', 3: 'Coded'}),
2177 ByteField('sec_max_skip', 0),
2178 ByteEnumField('sec_phy', 1, {1: '1M', 2: '2M', 3: 'Coded'}),
2179 ByteField('sid', 0),
2180 ByteField('scan_req_notify_enable', 0)]
2181
2182
2183class HCI_Cmd_LE_Set_Advertising_Set_Random_Address(Packet):
2184 name = 'HCI_LE_Set_Advertising_Set_Random_Address'
2185 fields_desc = [ByteField('handle', 0), LEMACField('addr', None)]
2186
2187
2188class HCI_Cmd_LE_Set_Advertising_Data(Packet):
2189 name = "HCI_LE_Set_Advertising_Data"
2190 fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"),
2191 PadField(
2192 PacketListField("data", [], EIR_Hdr,
2193 length_from=lambda pkt: pkt.len),
2194 align=31, padwith=b"\0"), ]
2195
2196
2197class HCI_Cmd_LE_Set_Extended_Advertising_Data(Packet):
2198 name = 'HCI_LE_Set_Extended_Advertising_Data'
2199 fields_desc = [ByteField('handle', 0),
2200 ByteEnumField('operation', 3, {
2201 0: 'intermediate_frag',
2202 1: 'first_frag',
2203 2: 'last_frag',
2204 3: 'complete',
2205 4: 'unchanged_data'}),
2206 ByteEnumField('frag_pref', 1, {0: 'allow_frag', 1: 'no_frag'}),
2207 FieldLenField('len', None, length_of='data', fmt='B'),
2208 PacketListField('data', [], EIR_Hdr, length_from=lambda pkt: pkt.len)] # noqa: E501
2209
2210
2211class HCI_Cmd_LE_Set_Scan_Response_Data(Packet):
2212 name = "HCI_LE_Set_Scan_Response_Data"
2213 fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"),
2214 StrLenField("data", "", length_from=lambda pkt: pkt.len), ]
2215
2216
2217class HCI_Cmd_LE_Set_Advertise_Enable(Packet):
2218 name = "HCI_LE_Set_Advertising_Enable"
2219 fields_desc = [ByteField("enable", 0)]
2220
2221
2222class Extended_Advertise_Set(Packet):
2223 name = 'Extended Advertising Set'
2224 fields_desc = [ByteField('handle', 0),
2225 LEShortField('duration', 0),
2226 ByteField('max_events', 0)]
2227
2228
2229class HCI_Cmd_LE_Set_Extended_Advertise_Enable(Packet):
2230 name = 'HCI_LE_Set_Extended_Advertising_Enable'
2231 fields_desc = [ByteEnumField('enable', 1, {0: 'disable', 1: 'enable'}),
2232 FieldLenField('num_sets', None, count_of='sets', fmt='B'),
2233 PacketListField('sets', [], Extended_Advertise_Set, count_from=lambda pkt: pkt.num_sets)] # noqa: E501
2234
2235
2236class HCI_Cmd_LE_Set_Scan_Parameters(Packet):
2237 name = "HCI_LE_Set_Scan_Parameters"
2238 fields_desc = [ByteEnumField("type", 0, {0: "passive", 1: "active"}),
2239 XLEShortField("interval", 16),
2240 XLEShortField("window", 16),
2241 ByteEnumField("addr_type", 0, {
2242 0: "public",
2243 1: "random",
2244 2: "rpa (pub)",
2245 3: "rpa (random)"}),
2246 ByteEnumField("policy", 0, {0: "all", 1: "whitelist"})]
2247 deprecated_fields = {"atype": ("addr_type", "2.7.0")}
2248
2249
2250class HCI_Cmd_LE_Set_Extended_Scan_Parameters(Packet):
2251 name = 'HCI_LE_Set_Extended_Scan_Parameters'
2252 fields_desc = [
2253 ByteEnumField('own_address_type', 0, {
2254 0: 'public',
2255 1: 'random',
2256 2: 'rpa_pub',
2257 3: 'rpa_rand'}),
2258 ByteEnumField('scanning_filter_policy', 0, {
2259 0: 'basic',
2260 1: 'whitelist',
2261 2: 'basic_rpa',
2262 3: 'whitelist_rpa'}),
2263 ByteField('scanning_phys', 1),
2264 ConditionalField(ByteEnumField('scan_type_1m', 1, {
2265 0: 'passive',
2266 1: 'active'}), lambda pkt: pkt.scanning_phys & 1),
2267 ConditionalField(LEShortField('scan_interval_1m', 16),
2268 lambda pkt: pkt.scanning_phys & 1),
2269 ConditionalField(LEShortField('scan_window_1m', 16),
2270 lambda pkt: pkt.scanning_phys & 1),
2271 ConditionalField(ByteEnumField('scan_type_2m', 1, {
2272 0: 'passive',
2273 1: 'active'}), lambda pkt: pkt.scanning_phys & 2),
2274 ConditionalField(LEShortField('scan_interval_2m', 16),
2275 lambda pkt: pkt.scanning_phys & 2),
2276 ConditionalField(LEShortField('scan_window_2m', 16),
2277 lambda pkt: pkt.scanning_phys & 2),
2278 ConditionalField(ByteEnumField('scan_type_coded', 1, {
2279 0: 'passive',
2280 1: 'active'}), lambda pkt: pkt.scanning_phys & 4),
2281 ConditionalField(LEShortField('scan_interval_coded', 16),
2282 lambda pkt: pkt.scanning_phys & 4),
2283 ConditionalField(LEShortField('scan_window_coded', 16),
2284 lambda pkt: pkt.scanning_phys & 4)]
2285
2286
2287class HCI_Cmd_LE_Set_Scan_Enable(Packet):
2288 name = "HCI_LE_Set_Scan_Enable"
2289 fields_desc = [ByteField("enable", 1),
2290 ByteField("filter_dups", 1), ]
2291
2292
2293class HCI_Cmd_LE_Set_Extended_Scan_Enable(Packet):
2294 name = 'HCI_LE_Set_Extended_Scan_Enable'
2295 fields_desc = [ByteEnumField('enable', 1, {0: 'disabled', 1: 'enabled'}),
2296 ByteEnumField('filter_dups', 1, {
2297 0: 'disabled',
2298 1: 'enabled',
2299 2: 'reset_period'}),
2300 LEShortField('duration', 500),
2301 LEShortField('period', 0)]
2302
2303
2304class HCI_Cmd_LE_Create_Connection(Packet):
2305 name = "HCI_LE_Create_Connection"
2306 fields_desc = [LEShortField("interval", 96),
2307 LEShortField("window", 48),
2308 ByteEnumField("filter", 0, {0: "address"}),
2309 ByteEnumField("peer_addr_type", 0, {0: "public", 1: "random"}),
2310 LEMACField("peer_addr", None),
2311 ByteEnumField("own_addr_type", 0, {0: "public", 1: "random"}),
2312 LEShortField("min_interval", 40),
2313 LEShortField("max_interval", 56),
2314 LEShortField("latency", 0),
2315 LEShortField("timeout", 42),
2316 LEShortField("min_ce", 0),
2317 LEShortField("max_ce", 0), ]
2318 deprecated_fields = {
2319 "patype": ("peer_addr_type", "2.7.0"),
2320 "paddr": ("peer_addr", "2.7.0"),
2321 "atype": ("own_addr_type", "2.7.0"),
2322 }
2323
2324
2325class HCI_Cmd_LE_Extended_Create_Connection(Packet):
2326 name = 'HCI_LE_Extended_Create_Connection'
2327 fields_desc = [ByteEnumField('filter_policy', 0, {0: 'peer_addr', 1: 'accept_list'}), # noqa: E501
2328 ByteEnumField('address_type', 0, {
2329 0: 'public',
2330 1: 'random',
2331 2: 'rpa_pub',
2332 3: 'rpa_rand'}),
2333 ByteEnumField('peer_addr_type', 0, {
2334 0: 'public',
2335 1: 'random',
2336 2: 'rpa_pub',
2337 3: 'rpa_rand'}),
2338 LEMACField('peer_addr', None),
2339 ByteField('phys', 1),
2340 ConditionalField(LEShortField('interval_1m', 96),
2341 lambda pkt: pkt.phys & 1),
2342 ConditionalField(LEShortField('window_1m', 96),
2343 lambda pkt: pkt.phys & 1),
2344 ConditionalField(LEShortField('min_interval_1m', 40),
2345 lambda pkt: pkt.phys & 1),
2346 ConditionalField(LEShortField('max_interval_1m', 56),
2347 lambda pkt: pkt.phys & 1),
2348 ConditionalField(LEShortField('latency_1m', 0),
2349 lambda pkt: pkt.phys & 1),
2350 ConditionalField(LEShortField('timeout_1m', 42),
2351 lambda pkt: pkt.phys & 1),
2352 ConditionalField(LEShortField('min_ce_1m', 0),
2353 lambda pkt: pkt.phys & 1),
2354 ConditionalField(LEShortField('max_ce_1m', 0),
2355 lambda pkt: pkt.phys & 1),
2356 ConditionalField(LEShortField('interval_2m', 96),
2357 lambda pkt: pkt.phys & 2),
2358 ConditionalField(LEShortField('window_2m', 96),
2359 lambda pkt: pkt.phys & 2),
2360 ConditionalField(LEShortField('min_interval_2m', 40),
2361 lambda pkt: pkt.phys & 2),
2362 ConditionalField(LEShortField('max_interval_2m', 56),
2363 lambda pkt: pkt.phys & 2),
2364 ConditionalField(LEShortField('latency_2m', 0),
2365 lambda pkt: pkt.phys & 2),
2366 ConditionalField(LEShortField('timeout_2m', 42),
2367 lambda pkt: pkt.phys & 2),
2368 ConditionalField(LEShortField('min_ce_2m', 0),
2369 lambda pkt: pkt.phys & 2),
2370 ConditionalField(LEShortField('max_ce_2m', 0),
2371 lambda pkt: pkt.phys & 2),
2372 ConditionalField(LEShortField('interval_coded', 96),
2373 lambda pkt: pkt.phys & 4),
2374 ConditionalField(LEShortField('window_coded', 96),
2375 lambda pkt: pkt.phys & 4),
2376 ConditionalField(LEShortField('min_interval_coded', 40),
2377 lambda pkt: pkt.phys & 4),
2378 ConditionalField(LEShortField('max_interval_coded', 56),
2379 lambda pkt: pkt.phys & 4),
2380 ConditionalField(LEShortField('latency_coded', 0),
2381 lambda pkt: pkt.phys & 4),
2382 ConditionalField(LEShortField('timeout_coded', 42),
2383 lambda pkt: pkt.phys & 4),
2384 ConditionalField(LEShortField('min_ce_coded', 0),
2385 lambda pkt: pkt.phys & 4),
2386 ConditionalField(LEShortField('max_ce_coded', 0),
2387 lambda pkt: pkt.phys & 4)]
2388
2389
2390class HCI_Cmd_LE_Create_Connection_Cancel(Packet):
2391 name = "HCI_LE_Create_Connection_Cancel"
2392
2393
2394class HCI_Cmd_LE_Read_Filter_Accept_List_Size(Packet):
2395 name = "HCI_LE_Read_Filter_Accept_List_Size"
2396
2397
2398class HCI_Cmd_LE_Clear_Filter_Accept_List(Packet):
2399 name = "HCI_LE_Clear_Filter_Accept_List"
2400
2401
2402class HCI_Cmd_LE_Add_Device_To_Filter_Accept_List(Packet):
2403 name = "HCI_LE_Add_Device_To_Filter_Accept_List"
2404 fields_desc = [ByteEnumField("addr_type", 0, {0: "public",
2405 1: "random",
2406 0xff: "anonymous"}),
2407 LEMACField("addr", None)]
2408
2409
2410class HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List(HCI_Cmd_LE_Add_Device_To_Filter_Accept_List): # noqa: E501
2411 name = "HCI_LE_Remove_Device_From_Filter_Accept_List"
2412
2413
2414class HCI_Cmd_LE_Connection_Update(Packet):
2415 name = "HCI_LE_Connection_Update"
2416 fields_desc = [XLEShortField("handle", 0),
2417 XLEShortField("min_interval", 0),
2418 XLEShortField("max_interval", 0),
2419 XLEShortField("latency", 0),
2420 XLEShortField("timeout", 0),
2421 LEShortField("min_ce", 0),
2422 LEShortField("max_ce", 0xffff), ]
2423
2424
2425class HCI_Cmd_LE_Read_Remote_Features(Packet):
2426 name = "HCI_LE_Read_Remote_Features"
2427 fields_desc = [LEShortField("handle", 64)]
2428
2429
2430class HCI_Cmd_LE_Enable_Encryption(Packet):
2431 name = "HCI_LE_Enable_Encryption"
2432 fields_desc = [LEShortField("handle", 0),
2433 StrFixedLenField("rand", None, 8),
2434 XLEShortField("ediv", 0),
2435 StrFixedLenField("ltk", b'\x00' * 16, 16), ]
2436
2437
2438class HCI_Cmd_LE_Long_Term_Key_Request_Reply(Packet):
2439 name = "HCI_LE_Long_Term_Key_Request_Reply"
2440 fields_desc = [LEShortField("handle", 0),
2441 StrFixedLenField("ltk", b'\x00' * 16, 16), ]
2442
2443
2444class HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply(Packet):
2445 name = "HCI_LE_Long_Term_Key_Request _Negative_Reply"
2446 fields_desc = [LEShortField("handle", 0), ]
2447
2448
2449class HCI_Event_Hdr(Packet):
2450 name = "HCI Event header"
2451 fields_desc = [XByteField("code", 0),
2452 LenField("len", None, fmt="B"), ]
2453
2454 def answers(self, other):
2455 if HCI_Command_Hdr not in other:
2456 return False
2457
2458 # Delegate answers to event types
2459 return self.payload.answers(other)
2460
2461
2462class HCI_Event_Inquiry_Complete(Packet):
2463 """
2464 7.7.1 Inquiry Complete event
2465 """
2466 name = "HCI_Inquiry_Complete"
2467 fields_desc = [
2468 ByteEnumField('status', 0, _bluetooth_error_codes)
2469 ]
2470
2471
2472class HCI_Event_Inquiry_Result(Packet):
2473 """
2474 7.7.2 Inquiry Result event
2475 """
2476 name = "HCI_Inquiry_Result"
2477 fields_desc = [
2478 ByteField("num_response", 0x00),
2479 FieldListField("addr", None, LEMACField("addr", None),
2480 count_from=lambda p: p.num_response),
2481 FieldListField("page_scan_repetition_mode", None,
2482 ByteField("page_scan_repetition_mode", 0),
2483 count_from=lambda p: p.num_response),
2484 FieldListField("reserved", None, LEShortField("reserved", 0),
2485 count_from=lambda p: p.num_response),
2486 FieldListField("device_class", None, XLE3BytesField("device_class", 0),
2487 count_from=lambda p: p.num_response),
2488 FieldListField("clock_offset", None, LEShortField("clock_offset", 0),
2489 count_from=lambda p: p.num_response)
2490 ]
2491
2492
2493class HCI_Event_Connection_Complete(Packet):
2494 """
2495 7.7.3 Connection Complete event
2496 """
2497 name = "HCI_Connection_Complete"
2498 fields_desc = [ByteEnumField('status', 0, _bluetooth_error_codes),
2499 LEShortField("handle", 0x0100),
2500 LEMACField("bd_addr", None),
2501 ByteEnumField("link_type", 0, {0: "SCO connection",
2502 1: "ACL connection", }),
2503 ByteEnumField("encryption_enabled", 0,
2504 {0: "link level encryption disabled",
2505 1: "link level encryption enabled", }), ]
2506
2507
2508class HCI_Event_Connection_Request(Packet):
2509 """
2510 7.7.4 Connection Request event
2511 """
2512 name = "HCI_Connection_Request"
2513 fields_desc = [LEMACField("bd_addr", None),
2514 XLE3BytesField("device_class", 0),
2515 ByteEnumField("link_type", 0, {0: "SCO connection",
2516 1: "ACL connection",
2517 2: "eSCO connection", }), ]
2518
2519
2520class HCI_Event_Disconnection_Complete(Packet):
2521 """
2522 7.7.5 Disconnection Complete event
2523 """
2524 name = "HCI_Disconnection_Complete"
2525 fields_desc = [ByteEnumField("status", 0, _bluetooth_error_codes),
2526 LEShortField("handle", 0),
2527 XByteField("reason", 0), ]
2528
2529
2530class HCI_Event_Remote_Name_Request_Complete(Packet):
2531 """
2532 7.7.7 Remote Name Request Complete event
2533 """
2534 name = "HCI_Remote_Name_Request_Complete"
2535 fields_desc = [ByteEnumField("status", 0, _bluetooth_error_codes),
2536 LEMACField("bd_addr", None),
2537 StrFixedLenField("remote_name", b"\x00", 248), ]
2538
2539
2540class HCI_Event_Encryption_Change(Packet):
2541 """
2542 7.7.8 Encryption Change event
2543 """
2544 name = "HCI_Encryption_Change"
2545 fields_desc = [ByteEnumField("status", 0, {0: "change has occurred"}),
2546 LEShortField("handle", 0),
2547 ByteEnumField("enabled", 0, {0: "OFF", 1: "ON (LE)", 2: "ON (BR/EDR)"}), ] # noqa: E501
2548
2549
2550class HCI_Event_Read_Remote_Supported_Features_Complete(Packet):
2551 """
2552 7.7.11 Read Remote Supported Features Complete event
2553 """
2554 name = "HCI_Read_Remote_Supported_Features_Complete"
2555 fields_desc = [
2556 ByteEnumField('status', 0, _bluetooth_error_codes),
2557 LEShortField('handle', 0),
2558 FlagsField('lmp_features', 0, -64, _bluetooth_features)
2559 ]
2560
2561
2562class HCI_Event_Remote_Host_Supported_Features_Notification(Packet):
2563 """
2564 7.7.50 Remote Host Supported Features Notification event
2565 """
2566 name = "HCI_Remote_Host_Supported_Features_Notification"
2567 fields_desc = [
2568 LEMACField('bd_addr', None),
2569 XLELongField('host_supported_features', 0)
2570 ]
2571
2572
2573class HCI_Event_Read_Remote_Version_Information_Complete(Packet):
2574 """
2575 7.7.12 Read Remote Version Information Complete event
2576 """
2577 name = "HCI_Read_Remote_Version_Information"
2578 fields_desc = [
2579 ByteEnumField('status', 0, _bluetooth_error_codes),
2580 LEShortField('handle', 0),
2581 ByteField('version', 0x00),
2582 LEShortField('manufacturer_name', 0x0000),
2583 LEShortField('subversion', 0x0000)
2584 ]
2585
2586
2587class HCI_Event_Command_Complete(Packet):
2588 """
2589 7.7.14 Command Complete event
2590 """
2591 name = "HCI_Command_Complete"
2592 fields_desc = [ByteField("number", 0),
2593 XLEShortField("opcode", 0),
2594 ByteEnumField("status", 0, _bluetooth_error_codes)]
2595
2596 def answers(self, other):
2597 if HCI_Command_Hdr not in other:
2598 return False
2599
2600 return other[HCI_Command_Hdr].opcode == self.opcode
2601
2602
2603class HCI_Event_Command_Status(Packet):
2604 """
2605 7.7.15 Command Status event
2606 """
2607 name = "HCI_Command_Status"
2608 fields_desc = [ByteEnumField("status", 0, {0: "pending"}),
2609 ByteField("number", 0),
2610 XLEShortField("opcode", None), ]
2611
2612 def answers(self, other):
2613 if HCI_Command_Hdr not in other:
2614 return False
2615
2616 return other[HCI_Command_Hdr].opcode == self.opcode
2617
2618
2619class HCI_Event_Number_Of_Completed_Packets(Packet):
2620 """
2621 7.7.19 Number Of Completed Packets event
2622 """
2623 name = "HCI_Number_Of_Completed_Packets"
2624 fields_desc = [ByteField("num_handles", 0),
2625 FieldListField("connection_handle_list", None,
2626 LEShortField("connection_handle", 0),
2627 count_from=lambda p: p.num_handles),
2628 FieldListField("num_completed_packets_list", None,
2629 LEShortField("num_completed_packets", 0),
2630 count_from=lambda p: p.num_handles)]
2631
2632
2633class HCI_Event_Link_Key_Request(Packet):
2634 """
2635 7.7.23 Link Key Request event
2636 """
2637 name = 'HCI_Link_Key_Request'
2638 fields_desc = [
2639 LEMACField('bd_addr', None)
2640 ]
2641
2642
2643class HCI_Event_Inquiry_Result_With_Rssi(Packet):
2644 """
2645 7.7.33 Inquiry Result with RSSI event
2646 """
2647 name = "HCI_Inquiry_Result_with_RSSI"
2648 fields_desc = [
2649 ByteField("num_response", 0x00),
2650 FieldListField("bd_addr", None, LEMACField,
2651 count_from=lambda p: p.num_response),
2652 FieldListField("page_scan_repetition_mode", None, ByteField,
2653 count_from=lambda p: p.num_response),
2654 FieldListField("reserved", None, LEShortField,
2655 count_from=lambda p: p.num_response),
2656 FieldListField("device_class", None, XLE3BytesField,
2657 count_from=lambda p: p.num_response),
2658 FieldListField("clock_offset", None, LEShortField,
2659 count_from=lambda p: p.num_response),
2660 FieldListField("rssi", None, SignedByteField,
2661 count_from=lambda p: p.num_response)
2662 ]
2663
2664
2665class HCI_Event_Read_Remote_Extended_Features_Complete(Packet):
2666 """
2667 7.7.34 Read Remote Extended Features Complete event
2668 """
2669 name = "HCI_Read_Remote_Extended_Features_Complete"
2670 fields_desc = [
2671 ByteEnumField('status', 0, _bluetooth_error_codes),
2672 LEShortField('handle', 0),
2673 ByteField('page', 0x00),
2674 ByteField('max_page', 0x00),
2675 XLELongField('extended_features', 0)
2676 ]
2677
2678
2679class HCI_Event_Extended_Inquiry_Result(Packet):
2680 """
2681 7.7.38 Extended Inquiry Result event
2682 """
2683 name = "HCI_Extended_Inquiry_Result"
2684 fields_desc = [
2685 ByteField('num_response', 0x01),
2686 LEMACField('bd_addr', None),
2687 ByteField('page_scan_repetition_mode', 0x00),
2688 ByteField('reserved', 0x00),
2689 XLE3BytesField('device_class', 0x000000),
2690 LEShortField('clock_offset', 0x0000),
2691 SignedByteField('rssi', 0x00),
2692 HCI_Extended_Inquiry_Response,
2693 ]
2694
2695
2696class HCI_Event_IO_Capability_Response(Packet):
2697 """
2698 7.7.41 IO Capability Response event
2699 """
2700 name = "HCI_IO_Capability_Response"
2701 fields_desc = [
2702 LEMACField('bd_addr', None),
2703 ByteField('io_capability', 0x00),
2704 ByteField('oob_data_present', 0x00),
2705 ByteField('authentication_requirements', 0x00)
2706 ]
2707
2708
2709class HCI_Event_Vendor(Packet):
2710 """
2711 Vendor-Specific Debug event (event code 0xFF).
2712
2713 Bluetooth Core 5.4, Vol 4, Part E, section 5.4.4 reserves 0xFF for
2714 vendor-specific debugging events; the format of the parameters is
2715 vendor-defined, so the data is exposed as a raw byte string.
2716 """
2717 name = "HCI_Vendor_Specific"
2718 fields_desc = [StrLenField("data", b"",
2719 length_from=lambda pkt: pkt.underlayer.len)]
2720
2721
2722class HCI_Event_LE_Meta(Packet):
2723 """
2724 7.7.65 LE Meta event
2725 """
2726 name = "HCI_LE_Meta"
2727 fields_desc = [ByteEnumField("event", 0, {
2728 0x01: "connection_complete",
2729 0x02: "advertising_report",
2730 0x03: "connection_update_complete",
2731 0x04: "read_remote_features_page_0_complete",
2732 0x05: "long_term_key_request",
2733 0x06: "remote_connection_parameter_request",
2734 0x07: "data_length_change",
2735 0x08: "read_local_p256_public_key_complete",
2736 0x09: "generate_dhkey_complete",
2737 0x0a: "enhanced_connection_complete_v1",
2738 0x0b: "directed_advertising_report",
2739 0x0c: "phy_update_complete",
2740 0x0d: "extended_advertising_report",
2741 0x29: "enhanced_connection_complete_v2"
2742 }), ]
2743
2744 def answers(self, other):
2745 if not self.payload:
2746 return False
2747
2748 # Delegate answers to payload
2749 return self.payload.answers(other)
2750
2751
2752class HCI_Cmd_Complete_Read_Local_Name(Packet):
2753 """
2754 7.3.12 Read Local Name command complete
2755 """
2756 name = 'Read Local Name command complete'
2757 fields_desc = [StrFixedLenField('local_name', '', length=248)]
2758
2759
2760class HCI_Cmd_Complete_Read_Local_Version_Information(Packet):
2761 """
2762 7.4.1 Read Local Version Information command complete
2763 """
2764 name = 'Read Local Version Information'
2765 fields_desc = [
2766 ByteEnumField('hci_version', 0, _bluetooth_core_specification_versions),
2767 LEShortField('hci_subversion', 0),
2768 ByteEnumField('lmp_version', 0, _bluetooth_core_specification_versions),
2769 LEShortEnumField('company_identifier', 0, BLUETOOTH_CORE_COMPANY_IDENTIFIERS),
2770 LEShortField('lmp_subversion', 0)]
2771
2772
2773class HCI_Cmd_Complete_Read_Local_Extended_Features(Packet):
2774 """
2775 7.4.4 Read Local Extended Features command complete
2776 """
2777 name = 'Read Local Extended Features command complete'
2778 fields_desc = [
2779 ByteField('page', 0x00),
2780 ByteField('max_page', 0x00),
2781 XLELongField('extended_features', 0)
2782 ]
2783
2784
2785class HCI_Cmd_Complete_Read_BD_Addr(Packet):
2786 """
2787 7.4.6 Read BD_ADDR command complete
2788 """
2789 name = "Read BD Addr"
2790 fields_desc = [LEMACField("addr", None), ]
2791
2792
2793class HCI_Cmd_Complete_LE_Read_White_List_Size(Packet):
2794 name = "LE Read White List Size"
2795 fields_desc = [ByteField("status", 0),
2796 ByteField("size", 0), ]
2797
2798
2799class HCI_LE_Meta_Connection_Complete(Packet):
2800 name = "Connection Complete"
2801 fields_desc = [ByteEnumField("status", 0, {0: "success"}),
2802 LEShortField("handle", 0),
2803 ByteEnumField("role", 0, {0: "master"}),
2804 ByteEnumField("peer_addr_type", 0, {0: "public", 1: "random"}),
2805 LEMACField("peer_addr", None),
2806 LEShortField("interval", 54),
2807 LEShortField("latency", 0),
2808 LEShortField("supervision", 42),
2809 XByteField("master_clock_accuracy", 5)]
2810 deprecated_fields = {
2811 "patype": ("peer_addr_type", "2.7.0"),
2812 "paddr": ("peer_addr", "2.7.0"),
2813 "clock_latency": ("master_clock_accuracy", "2.7.0"),
2814 }
2815
2816 def answers(self, other):
2817 if HCI_Cmd_LE_Create_Connection in other:
2818 cmd = other[HCI_Cmd_LE_Create_Connection]
2819 elif HCI_Cmd_LE_Extended_Create_Connection in other:
2820 cmd = other[HCI_Cmd_LE_Extended_Create_Connection]
2821 else:
2822 return False
2823
2824 return (cmd.peer_addr_type == self.peer_addr_type and
2825 cmd.peer_addr == self.peer_addr)
2826
2827
2828class HCI_LE_Meta_Enhanced_Connection_Complete(Packet):
2829 name = 'LE Enhanced Connection Complete'
2830 fields_desc = [ByteEnumField('status', 0, {0: 'success'}),
2831 LEShortField('handle', 0),
2832 ByteEnumField('role', 0, {0: 'master', 1: 'slave'}),
2833 ByteEnumField('peer_addr_type', 0, {
2834 0: 'public',
2835 1: 'random',
2836 2: 'public_identity',
2837 3: 'random_identity'}),
2838 LEMACField('peer_addr', None),
2839 LEMACField('local_rpa', None),
2840 LEMACField('peer_rpa', None),
2841 LEShortField('interval', 54),
2842 LEShortField('latency', 0),
2843 LEShortField('supervision', 42),
2844 XByteField('master_clock_accuracy', 5)]
2845
2846 def answers(self, other):
2847 if HCI_Cmd_LE_Create_Connection in other:
2848 cmd = other[HCI_Cmd_LE_Create_Connection]
2849 elif HCI_Cmd_LE_Extended_Create_Connection in other:
2850 cmd = other[HCI_Cmd_LE_Extended_Create_Connection]
2851 else:
2852 return False
2853
2854 return cmd.peer_addr_type == self.peer_addr_type and cmd.peer_addr == self.peer_addr # noqa: E501
2855
2856
2857class HCI_LE_Meta_Connection_Update_Complete(Packet):
2858 name = "Connection Update Complete"
2859 fields_desc = [ByteEnumField("status", 0, {0: "success"}),
2860 LEShortField("handle", 0),
2861 LEShortField("interval", 54),
2862 LEShortField("latency", 0),
2863 LEShortField("timeout", 42), ]
2864
2865
2866class HCI_LE_Meta_LE_Read_Remote_Features_Complete(Packet):
2867 name = "LE Read Remote Features Complete"
2868 fields_desc = [ByteEnumField("status", 0, _bluetooth_error_codes),
2869 LEShortField("handle", 0),
2870 XLELongField("le_features", 0)]
2871
2872
2873class HCI_LE_Meta_Advertising_Report(Packet):
2874 name = "Advertising Report"
2875 fields_desc = [ByteEnumField("type", 0, {0: "conn_und", 4: "scan_rsp"}),
2876 ByteEnumField("addr_type", 0, {0: "public", 1: "random"}),
2877 LEMACField("addr", None),
2878 FieldLenField("len", None, length_of="data", fmt="B"),
2879 PacketListField("data", [], EIR_Hdr,
2880 length_from=lambda pkt: pkt.len),
2881 SignedByteField("rssi", 0)]
2882 deprecated_fields = {"atype": ("addr_type", "2.7.0")}
2883
2884 def extract_padding(self, s):
2885 return '', s
2886
2887
2888class HCI_LE_Meta_Advertising_Reports(Packet):
2889 name = "Advertising Reports"
2890 fields_desc = [FieldLenField("len", None, count_of="reports", fmt="B"),
2891 PacketListField("reports", None,
2892 HCI_LE_Meta_Advertising_Report,
2893 count_from=lambda pkt: pkt.len)]
2894
2895
2896class HCI_LE_Meta_Long_Term_Key_Request(Packet):
2897 name = "Long Term Key Request"
2898 fields_desc = [LEShortField("handle", 0),
2899 StrFixedLenField("rand", None, 8),
2900 XLEShortField("ediv", 0), ]
2901
2902
2903class HCI_LE_Meta_Extended_Advertising_Report(Packet):
2904 name = "Extended Advertising Report"
2905 fields_desc = [
2906 BitField("reserved0", 0, 1),
2907 BitEnumField("data_status", 0, 2, {
2908 0b00: "complete",
2909 0b01: "incomplete",
2910 0b10: "incomplete_truncated",
2911 0b11: "reserved"
2912 }),
2913 BitField("legacy", 0, 1),
2914 BitField("scan_response", 0, 1),
2915 BitField("directed", 0, 1),
2916 BitField("scannable", 0, 1),
2917 BitField("connectable", 0, 1),
2918 ByteField("reserved", 0),
2919 ByteEnumField("addr_type", 0, {
2920 0x00: "public_device_address",
2921 0x01: "random_device_address",
2922 0x02: "public_identity_address",
2923 0x03: "random_identity_address",
2924 0xff: "anonymous"
2925 }),
2926 LEMACField('addr', None),
2927 ByteEnumField("primary_phy", 0, {
2928 0x01: "le_1m",
2929 0x03: "le_coded_s8",
2930 0x04: "le_coded_s2"
2931 }),
2932 ByteEnumField("secondary_phy", 0, {
2933 0x01: "le_1m",
2934 0x02: "le_2m",
2935 0x03: "le_coded_s8",
2936 0x04: "le_coded_s2"
2937 }),
2938 ByteField("advertising_sid", 0xff),
2939 ByteField("tx_power", 0x7f),
2940 SignedByteField("rssi", 0x00),
2941 LEShortField("periodic_advertising_interval", 0x0000),
2942 ByteEnumField("direct_addr_type", 0, {
2943 0x00: "public_device_address",
2944 0x01: "non_resolvable_private_address",
2945 0x02: "resolvable_private_address_resolved_0",
2946 0x03: "resolvable_private_address_resolved_1",
2947 0xfe: "resolvable_private_address_unable_resolve"}),
2948 LEMACField("direct_addr", None),
2949 FieldLenField("data_length", None, length_of="data", fmt="B"),
2950 PacketListField("data", [], EIR_Hdr,
2951 length_from=lambda pkt: pkt.data_length),
2952 ]
2953 deprecated_fields = {
2954 "address_type": ("addr_type", "2.7.0"),
2955 "address": ("addr", "2.7.0"),
2956 "direct_address_type": ("direct_addr_type", "2.7.0"),
2957 "direct_address": ("direct_addr", "2.7.0"),
2958 }
2959
2960 def extract_padding(self, s):
2961 return '', s
2962
2963
2964class HCI_LE_Meta_Extended_Advertising_Reports(Packet):
2965 name = "Extended Advertising Reports"
2966 fields_desc = [FieldLenField("num_reports", None, count_of="reports", fmt="B"),
2967 PacketListField("reports", None,
2968 HCI_LE_Meta_Extended_Advertising_Report,
2969 count_from=lambda pkt: pkt.num_reports)]
2970
2971
2972bind_layers(HCI_PHDR_Hdr, HCI_Hdr)
2973
2974bind_layers(HCI_Hdr, HCI_Command_Hdr, type=1)
2975bind_layers(HCI_Hdr, HCI_ACL_Hdr, type=2)
2976bind_layers(HCI_Hdr, HCI_Event_Hdr, type=4)
2977bind_layers(HCI_Hdr, conf.raw_layer,)
2978
2979conf.l2types.register(DLT_BLUETOOTH_HCI_H4, HCI_Hdr)
2980conf.l2types.register(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, HCI_PHDR_Hdr)
2981
2982
2983# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01
2984bind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry, ogf=0x01, ocf=0x0001)
2985bind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry_Cancel, ogf=0x01, ocf=0x0002)
2986bind_layers(HCI_Command_Hdr, HCI_Cmd_Periodic_Inquiry_Mode, ogf=0x01, ocf=0x0003)
2987bind_layers(HCI_Command_Hdr, HCI_Cmd_Exit_Peiodic_Inquiry_Mode, ogf=0x01, ocf=0x0004)
2988bind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection, ogf=0x01, ocf=0x0005)
2989bind_layers(HCI_Command_Hdr, HCI_Cmd_Disconnect, ogf=0x01, ocf=0x0006)
2990bind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection_Cancel, ogf=0x01, ocf=0x0008)
2991bind_layers(HCI_Command_Hdr, HCI_Cmd_Accept_Connection_Request, ogf=0x01, ocf=0x0009)
2992bind_layers(HCI_Command_Hdr, HCI_Cmd_Reject_Connection_Response, ogf=0x01, ocf=0x000a)
2993bind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Reply, ogf=0x01, ocf=0x000b)
2994bind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Negative_Reply,
2995 ogf=0x01, ocf=0x000c)
2996bind_layers(HCI_Command_Hdr, HCI_Cmd_PIN_Code_Request_Reply, ogf=0x01, ocf=0x000d)
2997bind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Packet_Type,
2998 ogf=0x01, ocf=0x000f)
2999bind_layers(HCI_Command_Hdr, HCI_Cmd_Authentication_Requested, ogf=0x01, ocf=0x0011)
3000bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Connection_Encryption, ogf=0x01, ocf=0x0013)
3001bind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Link_Key, ogf=0x01, ocf=0x0017)
3002bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request, ogf=0x01, ocf=0x0019)
3003bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request_Cancel, ogf=0x01, ocf=0x001a)
3004bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Supported_Features,
3005 ogf=0x01, ocf=0x001b)
3006bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Extended_Features,
3007 ogf=0x01, ocf=0x001c)
3008bind_layers(HCI_Command_Hdr, HCI_Cmd_IO_Capability_Request_Reply, ogf=0x01, ocf=0x002b)
3009bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Reply,
3010 ogf=0x01, ocf=0x002c)
3011bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Negative_Reply,
3012 ogf=0x01, ocf=0x002d)
3013bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Reply, ogf=0x01, ocf=0x002e)
3014bind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Negative_Reply,
3015 ogf=0x01, ocf=0x002f)
3016bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Reply,
3017 ogf=0x01, ocf=0x0030)
3018bind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply,
3019 ogf=0x01, ocf=0x0033)
3020
3021# 7.2 Link Policy commands, the OGF is defined as 0x02
3022bind_layers(HCI_Command_Hdr, HCI_Cmd_Hold_Mode, ogf=0x02, ocf=0x0001)
3023
3024# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03
3025bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Mask, ogf=0x03, ocf=0x0001)
3026bind_layers(HCI_Command_Hdr, HCI_Cmd_Reset, ogf=0x03, ocf=0x0003)
3027bind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Filter, ogf=0x03, ocf=0x0005)
3028bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Local_Name, ogf=0x03, ocf=0x0013)
3029bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Name, ogf=0x03, ocf=0x0014)
3030bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Connect_Accept_Timeout, ogf=0x03, ocf=0x0016)
3031bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Extended_Inquiry_Response, ogf=0x03, ocf=0x0052) # noqa: E501
3032bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_LE_Host_Support, ogf=0x03, ocf=0x006c)
3033bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_LE_Host_Support, ogf=0x03, ocf=0x006d)
3034
3035# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04
3036bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Version_Information, ogf=0x04, ocf=0x0001) # noqa: E501
3037bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Extended_Features, ogf=0x04, ocf=0x0004)
3038bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_BD_Addr, ogf=0x04, ocf=0x0009)
3039
3040# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05
3041bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Link_Quality, ogf=0x05, ocf=0x0003)
3042bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_RSSI, ogf=0x05, ocf=0x0005)
3043
3044# 7.6 TESTING COMMANDS, the OGF is defined as 0x06
3045bind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Loopback_Mode, ogf=0x06, ocf=0x0001)
3046bind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Loopback_Mode, ogf=0x06, ocf=0x0002)
3047
3048# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08
3049bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Event_Mask, ogf=0x08, ocf=0x0001)
3050bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V1, ogf=0x08, ocf=0x0002)
3051bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V2, ogf=0x08, ocf=0x0060)
3052bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Local_Supported_Features,
3053 ogf=0x08, ocf=0x0003)
3054bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Random_Address, ogf=0x08, ocf=0x0005)
3055bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Parameters, ogf=0x08, ocf=0x0006) # noqa: E501
3056bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Set_Random_Address, ogf=0x08, ocf=0x0035) # noqa: E501
3057bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Advertising_Parameters, ogf=0x08, ocf=0x0036) # noqa: E501
3058bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Data, ogf=0x08, ocf=0x0008)
3059bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Advertising_Data, ogf=0x08, ocf=0x0037) # noqa: E501
3060bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Response_Data, ogf=0x08, ocf=0x0009)
3061bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertise_Enable, ogf=0x08, ocf=0x000a)
3062bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Advertise_Enable, ogf=0x08, ocf=0x0039) # noqa: E501
3063bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Parameters, ogf=0x08, ocf=0x000b)
3064bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Scan_Parameters, ogf=0x08, ocf=0x0041) # noqa: E501
3065bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Enable, ogf=0x08, ocf=0x000c)
3066bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Extended_Scan_Enable, ogf=0x08, ocf=0x0042)
3067bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection, ogf=0x08, ocf=0x000d)
3068bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Extended_Create_Connection, ogf=0x08, ocf=0x0043) # noqa: E501
3069bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection_Cancel, ogf=0x08, ocf=0x000e) # noqa: E501
3070bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Filter_Accept_List_Size,
3071 ogf=0x08, ocf=0x000f)
3072bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Clear_Filter_Accept_List, ogf=0x08, ocf=0x0010)
3073bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Add_Device_To_Filter_Accept_List, ogf=0x08, ocf=0x0011) # noqa: E501
3074bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List, ogf=0x08, ocf=0x0012) # noqa: E501
3075bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Connection_Update, ogf=0x08, ocf=0x0013)
3076bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Remote_Features, ogf=0x08, ocf=0x0016) # noqa: E501
3077bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Enable_Encryption, ogf=0x08, ocf=0x0019) # noqa: E501
3078bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Reply, ogf=0x08, ocf=0x001a) # noqa: E501
3079bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply, ogf=0x08, ocf=0x001b) # noqa: E501
3080
3081# 7.7 EVENTS
3082bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Complete, code=0x01)
3083bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result, code=0x02)
3084bind_layers(HCI_Event_Hdr, HCI_Event_Connection_Complete, code=0x03)
3085bind_layers(HCI_Event_Hdr, HCI_Event_Connection_Request, code=0x04)
3086bind_layers(HCI_Event_Hdr, HCI_Event_Disconnection_Complete, code=0x05)
3087bind_layers(HCI_Event_Hdr, HCI_Event_Remote_Name_Request_Complete, code=0x07)
3088bind_layers(HCI_Event_Hdr, HCI_Event_Encryption_Change, code=0x08)
3089bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Supported_Features_Complete, code=0x0b)
3090bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Version_Information_Complete, code=0x0c) # noqa: E501
3091bind_layers(HCI_Event_Hdr, HCI_Event_Command_Complete, code=0x0e)
3092bind_layers(HCI_Event_Hdr, HCI_Event_Command_Status, code=0x0f)
3093bind_layers(HCI_Event_Hdr, HCI_Event_Number_Of_Completed_Packets, code=0x13)
3094bind_layers(HCI_Event_Hdr, HCI_Event_Link_Key_Request, code=0x17)
3095bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result_With_Rssi, code=0x22)
3096bind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Extended_Features_Complete, code=0x23)
3097bind_layers(HCI_Event_Hdr, HCI_Event_Extended_Inquiry_Result, code=0x2f)
3098bind_layers(HCI_Event_Hdr, HCI_Event_IO_Capability_Response, code=0x32)
3099bind_layers(HCI_Event_Hdr, HCI_Event_Remote_Host_Supported_Features_Notification, code=0x3d) # noqa: E501
3100bind_layers(HCI_Event_Hdr, HCI_Event_LE_Meta, code=0x3e)
3101bind_layers(HCI_Event_Hdr, HCI_Event_Vendor, code=0xff)
3102
3103bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Name, opcode=0x0c14) # noqa: E501
3104bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Version_Information, opcode=0x1001) # noqa: E501
3105bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Extended_Features, opcode=0x1004) # noqa: E501
3106bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_BD_Addr, opcode=0x1009) # noqa: E501
3107bind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_LE_Read_White_List_Size, opcode=0x200f) # noqa: E501
3108
3109bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Complete, event=0x01)
3110bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Enhanced_Connection_Complete, event=0x0a)
3111bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Advertising_Reports, event=0x02)
3112bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Update_Complete, event=0x03)
3113bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_LE_Read_Remote_Features_Complete, event=0x04) # noqa: E501
3114bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Long_Term_Key_Request, event=0x05)
3115bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Extended_Advertising_Reports, event=0x0d)
3116
3117bind_layers(EIR_Hdr, EIR_Flags, type=0x01)
3118bind_layers(EIR_Hdr, EIR_IncompleteList16BitServiceUUIDs, type=0x02)
3119bind_layers(EIR_Hdr, EIR_CompleteList16BitServiceUUIDs, type=0x03)
3120bind_layers(EIR_Hdr, EIR_IncompleteList32BitServiceUUIDs, type=0x04)
3121bind_layers(EIR_Hdr, EIR_CompleteList32BitServiceUUIDs, type=0x05)
3122bind_layers(EIR_Hdr, EIR_IncompleteList128BitServiceUUIDs, type=0x06)
3123bind_layers(EIR_Hdr, EIR_CompleteList128BitServiceUUIDs, type=0x07)
3124bind_layers(EIR_Hdr, EIR_ShortenedLocalName, type=0x08)
3125bind_layers(EIR_Hdr, EIR_CompleteLocalName, type=0x09)
3126bind_layers(EIR_Hdr, EIR_Device_ID, type=0x10)
3127bind_layers(EIR_Hdr, EIR_TX_Power_Level, type=0x0a)
3128bind_layers(EIR_Hdr, EIR_ClassOfDevice, type=0x0d)
3129bind_layers(EIR_Hdr, EIR_SecureSimplePairingHashC192, type=0x0e)
3130bind_layers(EIR_Hdr, EIR_SecureSimplePairingRandomizerR192, type=0x0f)
3131bind_layers(EIR_Hdr, EIR_SecurityManagerOOBFlags, type=0x11)
3132bind_layers(EIR_Hdr, EIR_PeripheralConnectionIntervalRange, type=0x12)
3133bind_layers(EIR_Hdr, EIR_ServiceSolicitation16BitUUID, type=0x14)
3134bind_layers(EIR_Hdr, EIR_ServiceSolicitation128BitUUID, type=0x15)
3135bind_layers(EIR_Hdr, EIR_ServiceData16BitUUID, type=0x16)
3136bind_layers(EIR_Hdr, EIR_PublicTargetAddress, type=0x17)
3137bind_layers(EIR_Hdr, EIR_RandomTargetAddress, type=0x18)
3138bind_layers(EIR_Hdr, EIR_Appearance, type=0x19)
3139bind_layers(EIR_Hdr, EIR_AdvertisingInterval, type=0x1a)
3140bind_layers(EIR_Hdr, EIR_LEBluetoothDeviceAddress, type=0x1b)
3141bind_layers(EIR_Hdr, EIR_LERole, type=0x1c)
3142bind_layers(EIR_Hdr, EIR_ServiceData32BitUUID, type=0x20)
3143bind_layers(EIR_Hdr, EIR_ServiceData128BitUUID, type=0x21)
3144bind_layers(EIR_Hdr, EIR_URI, type=0x24)
3145bind_layers(EIR_Hdr, EIR_BroadcastName, type=0x30)
3146bind_layers(EIR_Hdr, EIR_3DInformation, type=0x3d)
3147bind_layers(EIR_Hdr, EIR_Manufacturer_Specific_Data, type=0xff)
3148bind_layers(EIR_Hdr, EIR_Raw)
3149
3150bind_layers(HCI_ACL_Hdr, L2CAP_Hdr,)
3151bind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=1)
3152bind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=5) # LE L2CAP Signaling Channel
3153bind_layers(L2CAP_CmdHdr, L2CAP_CmdRej, code=1)
3154bind_layers(L2CAP_CmdHdr, L2CAP_ConnReq, code=2)
3155bind_layers(L2CAP_CmdHdr, L2CAP_ConnResp, code=3)
3156bind_layers(L2CAP_CmdHdr, L2CAP_ConfReq, code=4)
3157bind_layers(L2CAP_CmdHdr, L2CAP_ConfResp, code=5)
3158bind_layers(L2CAP_CmdHdr, L2CAP_DisconnReq, code=6)
3159bind_layers(L2CAP_CmdHdr, L2CAP_DisconnResp, code=7)
3160bind_layers(L2CAP_CmdHdr, L2CAP_EchoReq, code=8)
3161bind_layers(L2CAP_CmdHdr, L2CAP_EchoResp, code=9)
3162bind_layers(L2CAP_CmdHdr, L2CAP_InfoReq, code=10)
3163bind_layers(L2CAP_CmdHdr, L2CAP_InfoResp, code=11)
3164bind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Request, code=12)
3165bind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Response, code=13)
3166bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Request, code=14)
3167bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Response, code=15)
3168bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Request, code=16)
3169bind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Response, code=17)
3170bind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Request, code=18)
3171bind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Response, code=19)
3172bind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Request, code=20)
3173bind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Response, code=21)
3174bind_layers(L2CAP_CmdHdr, L2CAP_Flow_Control_Credit_Ind, code=22)
3175bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Request, code=23)
3176bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Response, code=24)
3177bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Request, code=25)
3178bind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Response, code=26)
3179bind_layers(L2CAP_Hdr, ATT_Hdr, cid=4)
3180bind_layers(ATT_Hdr, ATT_Error_Response, opcode=0x1)
3181bind_layers(ATT_Hdr, ATT_Exchange_MTU_Request, opcode=0x2)
3182bind_layers(ATT_Hdr, ATT_Exchange_MTU_Response, opcode=0x3)
3183bind_layers(ATT_Hdr, ATT_Find_Information_Request, opcode=0x4)
3184bind_layers(ATT_Hdr, ATT_Find_Information_Response, opcode=0x5)
3185bind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Request, opcode=0x6)
3186bind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Response, opcode=0x7)
3187bind_layers(ATT_Hdr, ATT_Read_By_Type_Request_128bit, opcode=0x8)
3188bind_layers(ATT_Hdr, ATT_Read_By_Type_Request, opcode=0x8)
3189bind_layers(ATT_Hdr, ATT_Read_By_Type_Response, opcode=0x9)
3190bind_layers(ATT_Hdr, ATT_Read_Request, opcode=0xa)
3191bind_layers(ATT_Hdr, ATT_Read_Response, opcode=0xb)
3192bind_layers(ATT_Hdr, ATT_Read_Blob_Request, opcode=0xc)
3193bind_layers(ATT_Hdr, ATT_Read_Blob_Response, opcode=0xd)
3194bind_layers(ATT_Hdr, ATT_Read_Multiple_Request, opcode=0xe)
3195bind_layers(ATT_Hdr, ATT_Read_Multiple_Response, opcode=0xf)
3196bind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Request, opcode=0x10)
3197bind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Response, opcode=0x11)
3198bind_layers(ATT_Hdr, ATT_Write_Request, opcode=0x12)
3199bind_layers(ATT_Hdr, ATT_Write_Response, opcode=0x13)
3200bind_layers(ATT_Hdr, ATT_Prepare_Write_Request, opcode=0x16)
3201bind_layers(ATT_Hdr, ATT_Prepare_Write_Response, opcode=0x17)
3202bind_layers(ATT_Hdr, ATT_Execute_Write_Request, opcode=0x18)
3203bind_layers(ATT_Hdr, ATT_Execute_Write_Response, opcode=0x19)
3204bind_layers(ATT_Hdr, ATT_Write_Command, opcode=0x52)
3205bind_layers(ATT_Hdr, ATT_Handle_Value_Notification, opcode=0x1b)
3206bind_layers(ATT_Hdr, ATT_Handle_Value_Indication, opcode=0x1d)
3207bind_layers(L2CAP_Hdr, SM_Hdr, cid=6)
3208bind_layers(SM_Hdr, SM_Pairing_Request, sm_command=0x01)
3209bind_layers(SM_Hdr, SM_Pairing_Response, sm_command=0x02)
3210bind_layers(SM_Hdr, SM_Confirm, sm_command=0x03)
3211bind_layers(SM_Hdr, SM_Random, sm_command=0x04)
3212bind_layers(SM_Hdr, SM_Failed, sm_command=0x05)
3213bind_layers(SM_Hdr, SM_Encryption_Information, sm_command=0x06)
3214bind_layers(SM_Hdr, SM_Master_Identification, sm_command=0x07)
3215bind_layers(SM_Hdr, SM_Identity_Information, sm_command=0x08)
3216bind_layers(SM_Hdr, SM_Identity_Address_Information, sm_command=0x09)
3217bind_layers(SM_Hdr, SM_Signing_Information, sm_command=0x0a)
3218bind_layers(SM_Hdr, SM_Security_Request, sm_command=0x0b)
3219bind_layers(SM_Hdr, SM_Public_Key, sm_command=0x0c)
3220bind_layers(SM_Hdr, SM_DHKey_Check, sm_command=0x0d)
3221bind_layers(SM_Hdr, SM_Keypress_Notification, sm_command=0x0e)
3222
3223
3224###############
3225# HCI Monitor #
3226###############
3227
3228
3229# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L27
3230class HCI_Mon_Hdr(Packet):
3231 name = 'Bluetooth Linux Monitor Transport Header'
3232 fields_desc = [
3233 LEShortEnumField('opcode', None, {
3234 0: "New index",
3235 1: "Delete index",
3236 2: "Command pkt",
3237 3: "Event pkt",
3238 4: "ACL TX pkt",
3239 5: "ACL RX pkt",
3240 6: "SCO TX pkt",
3241 7: "SCO RX pkt",
3242 8: "Open index",
3243 9: "Close index",
3244 10: "Index info",
3245 11: "Vendor diag",
3246 12: "System note",
3247 13: "User logging",
3248 14: "Ctrl open",
3249 15: "Ctrl close",
3250 16: "Ctrl command",
3251 17: "Ctrl event",
3252 18: "ISO TX pkt",
3253 19: "ISO RX pkt",
3254 }),
3255 LEShortField('adapter_id', None),
3256 LEShortField('len', None)
3257 ]
3258
3259
3260# https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LINUX_MONITOR.html
3261class HCI_Mon_Pcap_Hdr(HCI_Mon_Hdr):
3262 name = 'Bluetooth Linux Monitor Transport Pcap Header'
3263 fields_desc = [
3264 ShortField('adapter_id', None),
3265 ShortField('opcode', None)
3266 ]
3267
3268
3269class HCI_Mon_New_Index(Packet):
3270 name = 'Bluetooth Linux Monitor Transport New Index Packet'
3271 fields_desc = [
3272 ByteEnumField('bus', 0, {
3273 0x00: "BR/EDR",
3274 0x01: "AMP"
3275 }),
3276 ByteEnumField('type', 0, {
3277 0x00: "Virtual",
3278 0x01: "USB",
3279 0x02: "PC Card",
3280 0x03: "UART",
3281 0x04: "RS232",
3282 0x05: "PCI",
3283 0x06: "SDIO"
3284 }),
3285 LEMACField('addr', None),
3286 StrFixedLenField('devname', None, 8)
3287 ]
3288
3289
3290class HCI_Mon_Index_Info(Packet):
3291 name = 'Bluetooth Linux Monitor Transport Index Info Packet'
3292 fields_desc = [
3293 LEMACField('addr', None),
3294 XLEShortField('manufacturer', None)
3295 ]
3296
3297
3298class HCI_Mon_System_Note(Packet):
3299 name = 'Bluetooth Linux Monitor Transport System Note Packet'
3300 fields_desc = [
3301 StrNullField('note', None)
3302 ]
3303
3304
3305# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L34
3306bind_layers(HCI_Mon_Hdr, HCI_Mon_New_Index, opcode=0)
3307bind_layers(HCI_Mon_Hdr, HCI_Command_Hdr, opcode=2)
3308bind_layers(HCI_Mon_Hdr, HCI_Event_Hdr, opcode=3)
3309bind_layers(HCI_Mon_Hdr, HCI_ACL_Hdr, opcode=5)
3310bind_layers(HCI_Mon_Hdr, HCI_Mon_Index_Info, opcode=10)
3311bind_layers(HCI_Mon_Hdr, HCI_Mon_System_Note, opcode=12)
3312
3313conf.l2types.register(DLT_BLUETOOTH_LINUX_MONITOR, HCI_Mon_Pcap_Hdr)
3314
3315
3316###########
3317# Helpers #
3318###########
3319
3320class LowEnergyBeaconHelper:
3321 """
3322 Helpers for building packets for Bluetooth Low Energy Beacons.
3323
3324 Implementers provide a :meth:`build_eir` implementation.
3325
3326 This is designed to be used as a mix-in -- see
3327 ``scapy.contrib.eddystone`` and ``scapy.contrib.ibeacon`` for examples.
3328 """
3329
3330 # Basic flags that should be used by most beacons.
3331 base_eir = [EIR_Hdr() / EIR_Flags(flags=[
3332 "general_disc_mode", "br_edr_not_supported"]), ]
3333
3334 def build_eir(self):
3335 """
3336 Builds a list of EIR messages to wrap this frame.
3337
3338 Users of this helper must implement this method.
3339
3340 :return: List of HCI_Hdr with payloads that describe this beacon type
3341 :rtype: list[scapy.bluetooth.HCI_Hdr]
3342 """
3343 raise NotImplementedError("build_eir")
3344
3345 def build_advertising_report(self):
3346 """
3347 Builds a HCI_LE_Meta_Advertising_Report containing this frame.
3348
3349 :rtype: scapy.bluetooth.HCI_LE_Meta_Advertising_Report
3350 """
3351
3352 return HCI_LE_Meta_Advertising_Report(
3353 type=0, # Undirected
3354 addr_type=1, # Random address
3355 data=self.build_eir()
3356 )
3357
3358 def build_set_advertising_data(self):
3359 """Builds a HCI_Cmd_LE_Set_Advertising_Data containing this frame.
3360
3361 This includes the :class:`HCI_Hdr` and :class:`HCI_Command_Hdr` layers.
3362
3363 :rtype: scapy.bluetooth.HCI_Hdr
3364 """
3365
3366 return HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Set_Advertising_Data(
3367 data=self.build_eir()
3368 )
3369
3370
3371###########
3372# Sockets #
3373###########
3374
3375class BluetoothSocketError(BaseException):
3376 pass
3377
3378
3379class BluetoothCommandError(BaseException):
3380 pass
3381
3382
3383class BluetoothL2CAPSocket(SuperSocket):
3384 desc = "read/write packets on a connected L2CAP socket"
3385
3386 def __init__(self, bt_address):
3387 if WINDOWS:
3388 warning("Not available on Windows")
3389 return
3390 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
3391 socket.BTPROTO_L2CAP)
3392 s.connect((bt_address, 0))
3393 self.ins = self.outs = s
3394
3395 def recv(self, x=MTU):
3396 return L2CAP_CmdHdr(self.ins.recv(x))
3397
3398
3399class BluetoothRFCommSocket(BluetoothL2CAPSocket):
3400 """read/write packets on a connected RFCOMM socket"""
3401
3402 def __init__(self, bt_address, port=0):
3403 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
3404 socket.BTPROTO_RFCOMM)
3405 s.connect((bt_address, port))
3406 self.ins = self.outs = s
3407
3408
3409class BluetoothHCISocket(SuperSocket):
3410 desc = "read/write on a BlueTooth HCI socket"
3411
3412 def __init__(self, iface=0x10000, type=None):
3413 if WINDOWS:
3414 warning("Not available on Windows")
3415 return
3416 s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) # noqa: E501
3417 s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR, 1)
3418 s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP, 1)
3419 s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffff, 0xffffffff, 0xffffffff, 0)) # type mask, event mask, event mask, opcode # noqa: E501
3420 s.bind((iface,))
3421 self.ins = self.outs = s
3422# s.connect((peer,0))
3423
3424 def recv(self, x=MTU):
3425 return HCI_Hdr(self.ins.recv(x))
3426
3427
3428class sockaddr_hci(ctypes.Structure):
3429 _fields_ = [
3430 ("sin_family", ctypes.c_ushort),
3431 ("hci_dev", ctypes.c_ushort),
3432 ("hci_channel", ctypes.c_ushort),
3433 ]
3434
3435
3436class _BluetoothLibcSocket(SuperSocket):
3437 def __init__(self, socket_domain, socket_type, socket_protocol, sock_address):
3438 # type: (int, int, int, sockaddr_hci) -> None
3439 if WINDOWS:
3440 warning("Not available on Windows")
3441 return
3442 # Python socket and bind implementations do not allow us to pass down
3443 # the correct parameters. We must call libc functions directly via
3444 # ctypes.
3445 sockaddr_hcip = ctypes.POINTER(sockaddr_hci)
3446 from ctypes.util import find_library
3447 libc = ctypes.cdll.LoadLibrary(find_library("c"))
3448
3449 socket_c = libc.socket
3450 socket_c.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_int)
3451 socket_c.restype = ctypes.c_int
3452
3453 bind = libc.bind
3454 bind.argtypes = (ctypes.c_int,
3455 ctypes.POINTER(sockaddr_hci),
3456 ctypes.c_int)
3457 bind.restype = ctypes.c_int
3458
3459 # Socket
3460 s = socket_c(socket_domain, socket_type, socket_protocol)
3461 if s < 0:
3462 raise BluetoothSocketError(
3463 f"Unable to open socket({socket_domain}, {socket_type}, "
3464 f"{socket_protocol})")
3465
3466 # Bind
3467 r = bind(s, sockaddr_hcip(sock_address), sizeof(sock_address))
3468 if r != 0:
3469 raise BluetoothSocketError("Unable to bind")
3470
3471 self.hci_fd = s
3472 self.ins = self.outs = socket.fromfd(
3473 s, socket_domain, socket_type, socket_protocol)
3474
3475 def readable(self, timeout=0):
3476 (ins, _, _) = select.select([self.ins], [], [], timeout)
3477 return len(ins) > 0
3478
3479 def flush(self):
3480 while self.readable():
3481 self.recv()
3482
3483 def close(self):
3484 if self.closed:
3485 return
3486
3487 # Properly close socket so we can free the device
3488 from ctypes.util import find_library
3489 libc = ctypes.cdll.LoadLibrary(find_library("c"))
3490
3491 close = libc.close
3492 close.restype = ctypes.c_int
3493 self.closed = True
3494 if hasattr(self, "outs"):
3495 if not hasattr(self, "ins") or self.ins != self.outs:
3496 if self.outs and (WINDOWS or self.outs.fileno() != -1):
3497 close(self.outs.fileno())
3498 if hasattr(self, "ins"):
3499 if self.ins and (WINDOWS or self.ins.fileno() != -1):
3500 close(self.ins.fileno())
3501 if hasattr(self, "hci_fd"):
3502 close(self.hci_fd)
3503
3504
3505class BluetoothUserSocket(_BluetoothLibcSocket):
3506 desc = "read/write H4 over a Bluetooth user channel"
3507
3508 def __init__(self, adapter_index=0):
3509 sa = sockaddr_hci()
3510 sa.sin_family = socket.AF_BLUETOOTH
3511 sa.hci_dev = adapter_index
3512 sa.hci_channel = HCI_CHANNEL_USER
3513 super().__init__(
3514 socket_domain=socket.AF_BLUETOOTH,
3515 socket_type=socket.SOCK_RAW,
3516 socket_protocol=socket.BTPROTO_HCI,
3517 sock_address=sa)
3518
3519 def send_command(self, cmd):
3520 opcode = cmd[HCI_Command_Hdr].opcode
3521 self.send(cmd)
3522 while True:
3523 r = self.recv()
3524 if r.type == 0x04 and r.code in (0xe, 0xf) and r.opcode == opcode:
3525 if hasattr(r, 'status') and r.status != 0:
3526 raise BluetoothCommandError("Command %x failed with %x" % (opcode, r.status)) # noqa: E501
3527 return r
3528
3529 def recv(self, x=MTU):
3530 return HCI_Hdr(self.ins.recv(x))
3531
3532
3533class BluetoothMonitorSocket(_BluetoothLibcSocket):
3534 desc = "Read/write over a Bluetooth monitor channel"
3535
3536 def __init__(self):
3537 sa = sockaddr_hci()
3538 sa.sin_family = socket.AF_BLUETOOTH
3539 sa.hci_dev = HCI_DEV_NONE
3540 sa.hci_channel = HCI_CHANNEL_MONITOR
3541 super().__init__(
3542 socket_domain=socket.AF_BLUETOOTH,
3543 socket_type=socket.SOCK_RAW,
3544 socket_protocol=socket.BTPROTO_HCI,
3545 sock_address=sa)
3546
3547 def recv(self, x=MTU):
3548 return HCI_Mon_Hdr(self.ins.recv(x))
3549
3550
3551conf.BTsocket = BluetoothRFCommSocket
3552
3553# Bluetooth
3554
3555
3556@conf.commands.register
3557def srbt(bt_address, pkts, inter=0.1, *args, **kargs):
3558 """send and receive using a bluetooth socket"""
3559 if "port" in kargs:
3560 s = conf.BTsocket(bt_address=bt_address, port=kargs.pop("port"))
3561 else:
3562 s = conf.BTsocket(bt_address=bt_address)
3563 a, b = sndrcv(s, pkts, inter=inter, *args, **kargs)
3564 s.close()
3565 return a, b
3566
3567
3568@conf.commands.register
3569def srbt1(bt_address, pkts, *args, **kargs):
3570 """send and receive 1 packet using a bluetooth socket"""
3571 a, b = srbt(bt_address, pkts, *args, **kargs)
3572 if len(a) > 0:
3573 return a[0][1]