xref: /aosp_15_r20/external/scapy/scapy/layers/bluetooth.py (revision 7dc08ffc4802948ccbc861daaf1e81c405c2c4bd)
1*7dc08ffcSJunyu Lai## This file is part of Scapy
2*7dc08ffcSJunyu Lai## See http://www.secdev.org/projects/scapy for more informations
3*7dc08ffcSJunyu Lai## Copyright (C) Philippe Biondi <[email protected]>
4*7dc08ffcSJunyu Lai## Copyright (C) Mike Ryan <[email protected]>
5*7dc08ffcSJunyu Lai## This program is published under a GPLv2 license
6*7dc08ffcSJunyu Lai
7*7dc08ffcSJunyu Lai"""
8*7dc08ffcSJunyu LaiBluetooth layers, sockets and send/receive functions.
9*7dc08ffcSJunyu Lai"""
10*7dc08ffcSJunyu Lai
11*7dc08ffcSJunyu Laiimport socket,struct,array
12*7dc08ffcSJunyu Laifrom ctypes import *
13*7dc08ffcSJunyu Laifrom select import select
14*7dc08ffcSJunyu Lai
15*7dc08ffcSJunyu Laifrom scapy.config import conf
16*7dc08ffcSJunyu Laifrom scapy.data import DLT_BLUETOOTH_HCI_H4
17*7dc08ffcSJunyu Laifrom scapy.packet import *
18*7dc08ffcSJunyu Laifrom scapy.fields import *
19*7dc08ffcSJunyu Laifrom scapy.supersocket import SuperSocket
20*7dc08ffcSJunyu Laifrom scapy.sendrecv import sndrcv
21*7dc08ffcSJunyu Laifrom scapy.data import MTU
22*7dc08ffcSJunyu Laifrom scapy.consts import WINDOWS
23*7dc08ffcSJunyu Laifrom scapy.error import warning, log_loading
24*7dc08ffcSJunyu Lai
25*7dc08ffcSJunyu Lai
26*7dc08ffcSJunyu Lai##########
27*7dc08ffcSJunyu Lai# Fields #
28*7dc08ffcSJunyu Lai##########
29*7dc08ffcSJunyu Lai
30*7dc08ffcSJunyu Laiclass XLEShortField(LEShortField):
31*7dc08ffcSJunyu Lai    def i2repr(self, pkt, x):
32*7dc08ffcSJunyu Lai        return lhex(self.i2h(pkt, x))
33*7dc08ffcSJunyu Lai
34*7dc08ffcSJunyu Laiclass XLELongField(LEShortField):
35*7dc08ffcSJunyu Lai    def __init__(self, name, default):
36*7dc08ffcSJunyu Lai        Field.__init__(self, name, default, "<Q")
37*7dc08ffcSJunyu Lai    def i2repr(self, pkt, x):
38*7dc08ffcSJunyu Lai        return lhex(self.i2h(pkt, x))
39*7dc08ffcSJunyu Lai
40*7dc08ffcSJunyu Lai
41*7dc08ffcSJunyu Laiclass LEMACField(Field):
42*7dc08ffcSJunyu Lai    def __init__(self, name, default):
43*7dc08ffcSJunyu Lai        Field.__init__(self, name, default, "6s")
44*7dc08ffcSJunyu Lai    def i2m(self, pkt, x):
45*7dc08ffcSJunyu Lai        if x is None:
46*7dc08ffcSJunyu Lai            return b"\0\0\0\0\0\0"
47*7dc08ffcSJunyu Lai        return mac2str(x)[::-1]
48*7dc08ffcSJunyu Lai    def m2i(self, pkt, x):
49*7dc08ffcSJunyu Lai        return str2mac(x[::-1])
50*7dc08ffcSJunyu Lai    def any2i(self, pkt, x):
51*7dc08ffcSJunyu Lai        if isinstance(x, str) and len(x) is 6:
52*7dc08ffcSJunyu Lai            x = self.m2i(pkt, x)
53*7dc08ffcSJunyu Lai        return x
54*7dc08ffcSJunyu Lai    def i2repr(self, pkt, x):
55*7dc08ffcSJunyu Lai        x = self.i2h(pkt, x)
56*7dc08ffcSJunyu Lai        if self in conf.resolve:
57*7dc08ffcSJunyu Lai            x = conf.manufdb._resolve_MAC(x)
58*7dc08ffcSJunyu Lai        return x
59*7dc08ffcSJunyu Lai    def randval(self):
60*7dc08ffcSJunyu Lai        return RandMAC()
61*7dc08ffcSJunyu Lai
62*7dc08ffcSJunyu Lai_bluetooth_packet_types = {
63*7dc08ffcSJunyu Lai        0: "Acknowledgement",
64*7dc08ffcSJunyu Lai        1: "Command",
65*7dc08ffcSJunyu Lai        2: "ACL Data",
66*7dc08ffcSJunyu Lai        3: "Synchronous",
67*7dc08ffcSJunyu Lai        4: "Event",
68*7dc08ffcSJunyu Lai        5: "Reserve",
69*7dc08ffcSJunyu Lai        14: "Vendor",
70*7dc08ffcSJunyu Lai        15: "Link Control"
71*7dc08ffcSJunyu Lai    }
72*7dc08ffcSJunyu Lai
73*7dc08ffcSJunyu Laiclass HCI_Hdr(Packet):
74*7dc08ffcSJunyu Lai    name = "HCI header"
75*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("type", 2, _bluetooth_packet_types) ]
76*7dc08ffcSJunyu Lai
77*7dc08ffcSJunyu Lai    def mysummary(self):
78*7dc08ffcSJunyu Lai        return self.sprintf("HCI %type%")
79*7dc08ffcSJunyu Lai
80*7dc08ffcSJunyu Laiclass HCI_ACL_Hdr(Packet):
81*7dc08ffcSJunyu Lai    name = "HCI ACL header"
82*7dc08ffcSJunyu Lai    fields_desc = [ BitField("handle",0,12),    # TODO: Create and use LEBitField
83*7dc08ffcSJunyu Lai                    BitField("PB",0,2),      # They are recieved as a **combined** LE Short
84*7dc08ffcSJunyu Lai                    BitField("BC",0,2),      # Handle is 12 bits, eacg flag is 2 bits.
85*7dc08ffcSJunyu Lai                    LEShortField("len",None), ]
86*7dc08ffcSJunyu Lai
87*7dc08ffcSJunyu Lai    def pre_dissect(self, s):
88*7dc08ffcSJunyu Lai        # Recieve data as LE stored as
89*7dc08ffcSJunyu Lai        # .... 1111 0100 1100 = handle
90*7dc08ffcSJunyu Lai        # 1010 .... .... .... = flags
91*7dc08ffcSJunyu Lai        # And turn it into
92*7dc08ffcSJunyu Lai        # 1111 0100 1100 .... = handle
93*7dc08ffcSJunyu Lai        # .... .... .... 1010 = flags
94*7dc08ffcSJunyu Lai        hf = socket.ntohs(struct.unpack("!H", s[:2])[0])
95*7dc08ffcSJunyu Lai        r = ((hf & 0x0fff) << 4) + (hf >> 12)
96*7dc08ffcSJunyu Lai        return struct.pack("!H", r) + s[2:]
97*7dc08ffcSJunyu Lai
98*7dc08ffcSJunyu Lai    def post_dissect(self, s):
99*7dc08ffcSJunyu Lai        self.raw_packet_cache = None # Reset packet to allow post_build
100*7dc08ffcSJunyu Lai        return s
101*7dc08ffcSJunyu Lai
102*7dc08ffcSJunyu Lai    def post_build(self, p, pay):
103*7dc08ffcSJunyu Lai        p += pay
104*7dc08ffcSJunyu Lai        if self.len is None:
105*7dc08ffcSJunyu Lai            p = p[:2] + struct.pack("<H", len(pay)) + p[4:]
106*7dc08ffcSJunyu Lai        # Reverse, opposite of pre_dissect
107*7dc08ffcSJunyu Lai        hf = struct.unpack("!H", p[:2])[0]
108*7dc08ffcSJunyu Lai        r = socket.ntohs(((hf & 0xf) << 12) + (hf >> 4))
109*7dc08ffcSJunyu Lai        return struct.pack("!H", r) + p[2:]
110*7dc08ffcSJunyu Lai
111*7dc08ffcSJunyu Lai
112*7dc08ffcSJunyu Laiclass L2CAP_Hdr(Packet):
113*7dc08ffcSJunyu Lai    name = "L2CAP header"
114*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("len",None),
115*7dc08ffcSJunyu Lai            LEShortEnumField("cid",0,{1:"control", 4:"attribute"}),]
116*7dc08ffcSJunyu Lai
117*7dc08ffcSJunyu Lai    def post_build(self, p, pay):
118*7dc08ffcSJunyu Lai        p += pay
119*7dc08ffcSJunyu Lai        if self.len is None:
120*7dc08ffcSJunyu Lai            p = struct.pack("<H", len(pay)) + p[2:]
121*7dc08ffcSJunyu Lai        return p
122*7dc08ffcSJunyu Lai
123*7dc08ffcSJunyu Lai
124*7dc08ffcSJunyu Lai
125*7dc08ffcSJunyu Laiclass L2CAP_CmdHdr(Packet):
126*7dc08ffcSJunyu Lai    name = "L2CAP command header"
127*7dc08ffcSJunyu Lai    fields_desc = [
128*7dc08ffcSJunyu Lai        ByteEnumField("code",8,{1:"rej",2:"conn_req",3:"conn_resp",
129*7dc08ffcSJunyu Lai                                4:"conf_req",5:"conf_resp",6:"disconn_req",
130*7dc08ffcSJunyu Lai                                7:"disconn_resp",8:"echo_req",9:"echo_resp",
131*7dc08ffcSJunyu Lai                                10:"info_req",11:"info_resp", 18:"conn_param_update_req",
132*7dc08ffcSJunyu Lai                                19:"conn_param_update_resp"}),
133*7dc08ffcSJunyu Lai        ByteField("id",0),
134*7dc08ffcSJunyu Lai        LEShortField("len",None) ]
135*7dc08ffcSJunyu Lai    def post_build(self, p, pay):
136*7dc08ffcSJunyu Lai        p += pay
137*7dc08ffcSJunyu Lai        if self.len is None:
138*7dc08ffcSJunyu Lai            p = p[:2] + struct.pack("<H", len(pay)) + p[4:]
139*7dc08ffcSJunyu Lai        return p
140*7dc08ffcSJunyu Lai    def answers(self, other):
141*7dc08ffcSJunyu Lai        if other.id == self.id:
142*7dc08ffcSJunyu Lai            if self.code == 1:
143*7dc08ffcSJunyu Lai                return 1
144*7dc08ffcSJunyu Lai            if other.code in [2,4,6,8,10,18] and self.code == other.code+1:
145*7dc08ffcSJunyu Lai                if other.code == 8:
146*7dc08ffcSJunyu Lai                    return 1
147*7dc08ffcSJunyu Lai                return self.payload.answers(other.payload)
148*7dc08ffcSJunyu Lai        return 0
149*7dc08ffcSJunyu Lai
150*7dc08ffcSJunyu Laiclass L2CAP_ConnReq(Packet):
151*7dc08ffcSJunyu Lai    name = "L2CAP Conn Req"
152*7dc08ffcSJunyu Lai    fields_desc = [ LEShortEnumField("psm",0,{1:"SDP",3:"RFCOMM",5:"telephony control"}),
153*7dc08ffcSJunyu Lai                    LEShortField("scid",0),
154*7dc08ffcSJunyu Lai                    ]
155*7dc08ffcSJunyu Lai
156*7dc08ffcSJunyu Laiclass L2CAP_ConnResp(Packet):
157*7dc08ffcSJunyu Lai    name = "L2CAP Conn Resp"
158*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("dcid",0),
159*7dc08ffcSJunyu Lai                    LEShortField("scid",0),
160*7dc08ffcSJunyu Lai                    LEShortEnumField("result",0,["success", "pend", "cr_bad_psm", "cr_sec_block", "cr_no_mem", "reserved","cr_inval_scid", "cr_scid_in_use"]),
161*7dc08ffcSJunyu Lai                    LEShortEnumField("status",0,["no_info", "authen_pend", "author_pend", "reserved"]),
162*7dc08ffcSJunyu Lai                    ]
163*7dc08ffcSJunyu Lai    def answers(self, other):
164*7dc08ffcSJunyu Lai        return isinstance(other, L2CAP_ConnReq) and self.dcid == other.scid
165*7dc08ffcSJunyu Lai
166*7dc08ffcSJunyu Laiclass L2CAP_CmdRej(Packet):
167*7dc08ffcSJunyu Lai    name = "L2CAP Command Rej"
168*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("reason",0),
169*7dc08ffcSJunyu Lai                    ]
170*7dc08ffcSJunyu Lai
171*7dc08ffcSJunyu Lai
172*7dc08ffcSJunyu Laiclass L2CAP_ConfReq(Packet):
173*7dc08ffcSJunyu Lai    name = "L2CAP Conf Req"
174*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("dcid",0),
175*7dc08ffcSJunyu Lai                    LEShortField("flags",0),
176*7dc08ffcSJunyu Lai                    ]
177*7dc08ffcSJunyu Lai
178*7dc08ffcSJunyu Laiclass L2CAP_ConfResp(Packet):
179*7dc08ffcSJunyu Lai    name = "L2CAP Conf Resp"
180*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("scid",0),
181*7dc08ffcSJunyu Lai                    LEShortField("flags",0),
182*7dc08ffcSJunyu Lai                    LEShortEnumField("result",0,["success","unaccept","reject","unknown"]),
183*7dc08ffcSJunyu Lai                    ]
184*7dc08ffcSJunyu Lai    def answers(self, other):
185*7dc08ffcSJunyu Lai        return isinstance(other, L2CAP_ConfReq) and self.scid == other.dcid
186*7dc08ffcSJunyu Lai
187*7dc08ffcSJunyu Lai
188*7dc08ffcSJunyu Laiclass L2CAP_DisconnReq(Packet):
189*7dc08ffcSJunyu Lai    name = "L2CAP Disconn Req"
190*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("dcid",0),
191*7dc08ffcSJunyu Lai                    LEShortField("scid",0), ]
192*7dc08ffcSJunyu Lai
193*7dc08ffcSJunyu Laiclass L2CAP_DisconnResp(Packet):
194*7dc08ffcSJunyu Lai    name = "L2CAP Disconn Resp"
195*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("dcid",0),
196*7dc08ffcSJunyu Lai                    LEShortField("scid",0), ]
197*7dc08ffcSJunyu Lai    def answers(self, other):
198*7dc08ffcSJunyu Lai        return self.scid == other.scid
199*7dc08ffcSJunyu Lai
200*7dc08ffcSJunyu Lai
201*7dc08ffcSJunyu Lai
202*7dc08ffcSJunyu Laiclass L2CAP_InfoReq(Packet):
203*7dc08ffcSJunyu Lai    name = "L2CAP Info Req"
204*7dc08ffcSJunyu Lai    fields_desc = [ LEShortEnumField("type",0,{1:"CL_MTU",2:"FEAT_MASK"}),
205*7dc08ffcSJunyu Lai                    StrField("data","")
206*7dc08ffcSJunyu Lai                    ]
207*7dc08ffcSJunyu Lai
208*7dc08ffcSJunyu Lai
209*7dc08ffcSJunyu Laiclass L2CAP_InfoResp(Packet):
210*7dc08ffcSJunyu Lai    name = "L2CAP Info Resp"
211*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("type",0),
212*7dc08ffcSJunyu Lai                    LEShortEnumField("result",0,["success","not_supp"]),
213*7dc08ffcSJunyu Lai                    StrField("data",""), ]
214*7dc08ffcSJunyu Lai    def answers(self, other):
215*7dc08ffcSJunyu Lai        return self.type == other.type
216*7dc08ffcSJunyu Lai
217*7dc08ffcSJunyu Lai
218*7dc08ffcSJunyu Laiclass L2CAP_Connection_Parameter_Update_Request(Packet):
219*7dc08ffcSJunyu Lai    name = "L2CAP Connection Parameter Update Request"
220*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("min_interval", 0),
221*7dc08ffcSJunyu Lai                    LEShortField("max_interval", 0),
222*7dc08ffcSJunyu Lai                    LEShortField("slave_latency", 0),
223*7dc08ffcSJunyu Lai                    LEShortField("timeout_mult", 0), ]
224*7dc08ffcSJunyu Lai
225*7dc08ffcSJunyu Lai
226*7dc08ffcSJunyu Laiclass L2CAP_Connection_Parameter_Update_Response(Packet):
227*7dc08ffcSJunyu Lai    name = "L2CAP Connection Parameter Update Response"
228*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("move_result", 0), ]
229*7dc08ffcSJunyu Lai
230*7dc08ffcSJunyu Lai
231*7dc08ffcSJunyu Laiclass ATT_Hdr(Packet):
232*7dc08ffcSJunyu Lai    name = "ATT header"
233*7dc08ffcSJunyu Lai    fields_desc = [ XByteField("opcode", None), ]
234*7dc08ffcSJunyu Lai
235*7dc08ffcSJunyu Lai
236*7dc08ffcSJunyu Laiclass ATT_Error_Response(Packet):
237*7dc08ffcSJunyu Lai    name = "Error Response"
238*7dc08ffcSJunyu Lai    fields_desc = [ XByteField("request", 0),
239*7dc08ffcSJunyu Lai                    LEShortField("handle", 0),
240*7dc08ffcSJunyu Lai                    XByteField("ecode", 0), ]
241*7dc08ffcSJunyu Lai
242*7dc08ffcSJunyu Laiclass ATT_Exchange_MTU_Request(Packet):
243*7dc08ffcSJunyu Lai    name = "Exchange MTU Request"
244*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("mtu", 0), ]
245*7dc08ffcSJunyu Lai
246*7dc08ffcSJunyu Laiclass ATT_Exchange_MTU_Response(Packet):
247*7dc08ffcSJunyu Lai    name = "Exchange MTU Response"
248*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("mtu", 0), ]
249*7dc08ffcSJunyu Lai
250*7dc08ffcSJunyu Laiclass ATT_Find_Information_Request(Packet):
251*7dc08ffcSJunyu Lai    name = "Find Information Request"
252*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("start", 0x0000),
253*7dc08ffcSJunyu Lai                    XLEShortField("end", 0xffff), ]
254*7dc08ffcSJunyu Lai
255*7dc08ffcSJunyu Laiclass ATT_Find_Information_Response(Packet):
256*7dc08ffcSJunyu Lai    name = "Find Information Reponse"
257*7dc08ffcSJunyu Lai    fields_desc = [ XByteField("format", 1),
258*7dc08ffcSJunyu Lai                    StrField("data", "") ]
259*7dc08ffcSJunyu Lai
260*7dc08ffcSJunyu Laiclass ATT_Find_By_Type_Value_Request(Packet):
261*7dc08ffcSJunyu Lai    name = "Find By Type Value Request"
262*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("start", 0x0001),
263*7dc08ffcSJunyu Lai                    XLEShortField("end", 0xffff),
264*7dc08ffcSJunyu Lai                    XLEShortField("uuid", None),
265*7dc08ffcSJunyu Lai                    StrField("data", ""), ]
266*7dc08ffcSJunyu Lai
267*7dc08ffcSJunyu Laiclass ATT_Find_By_Type_Value_Response(Packet):
268*7dc08ffcSJunyu Lai    name = "Find By Type Value Response"
269*7dc08ffcSJunyu Lai    fields_desc = [ StrField("handles", ""), ]
270*7dc08ffcSJunyu Lai
271*7dc08ffcSJunyu Laiclass ATT_Read_By_Type_Request_128bit(Packet):
272*7dc08ffcSJunyu Lai    name = "Read By Type Request"
273*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("start", 0x0001),
274*7dc08ffcSJunyu Lai                    XLEShortField("end", 0xffff),
275*7dc08ffcSJunyu Lai                    XLELongField("uuid1", None),
276*7dc08ffcSJunyu Lai                    XLELongField("uuid2", None)]
277*7dc08ffcSJunyu Lai    @classmethod
278*7dc08ffcSJunyu Lai    def dispatch_hook(cls, _pkt=None, *args, **kargs):
279*7dc08ffcSJunyu Lai        if _pkt and len(_pkt) == 6:
280*7dc08ffcSJunyu Lai            return ATT_Read_By_Type_Request
281*7dc08ffcSJunyu Lai        return ATT_Read_By_Type_Request_128bit
282*7dc08ffcSJunyu Lai
283*7dc08ffcSJunyu Laiclass ATT_Read_By_Type_Request(Packet):
284*7dc08ffcSJunyu Lai    name = "Read By Type Request"
285*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("start", 0x0001),
286*7dc08ffcSJunyu Lai                    XLEShortField("end", 0xffff),
287*7dc08ffcSJunyu Lai                    XLEShortField("uuid", None)]
288*7dc08ffcSJunyu Lai
289*7dc08ffcSJunyu Laiclass ATT_Read_By_Type_Response(Packet):
290*7dc08ffcSJunyu Lai    name = "Read By Type Response"
291*7dc08ffcSJunyu Lai    # fields_desc = [ FieldLenField("len", None, length_of="data", fmt="B"),
292*7dc08ffcSJunyu Lai    #                 StrLenField("data", "", length_from=lambda pkt:pkt.len), ]
293*7dc08ffcSJunyu Lai    fields_desc = [ StrField("data", "") ]
294*7dc08ffcSJunyu Lai
295*7dc08ffcSJunyu Laiclass ATT_Read_Request(Packet):
296*7dc08ffcSJunyu Lai    name = "Read Request"
297*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("gatt_handle", 0), ]
298*7dc08ffcSJunyu Lai
299*7dc08ffcSJunyu Laiclass ATT_Read_Response(Packet):
300*7dc08ffcSJunyu Lai    name = "Read Response"
301*7dc08ffcSJunyu Lai    fields_desc = [ StrField("value", ""), ]
302*7dc08ffcSJunyu Lai
303*7dc08ffcSJunyu Laiclass ATT_Read_By_Group_Type_Request(Packet):
304*7dc08ffcSJunyu Lai    name = "Read By Group Type Request"
305*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("start", 0),
306*7dc08ffcSJunyu Lai                    XLEShortField("end", 0xffff),
307*7dc08ffcSJunyu Lai                    XLEShortField("uuid", 0), ]
308*7dc08ffcSJunyu Lai
309*7dc08ffcSJunyu Laiclass ATT_Read_By_Group_Type_Response(Packet):
310*7dc08ffcSJunyu Lai    name = "Read By Group Type Response"
311*7dc08ffcSJunyu Lai    fields_desc = [ XByteField("length", 0),
312*7dc08ffcSJunyu Lai                    StrField("data", ""), ]
313*7dc08ffcSJunyu Lai
314*7dc08ffcSJunyu Laiclass ATT_Write_Request(Packet):
315*7dc08ffcSJunyu Lai    name = "Write Request"
316*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("gatt_handle", 0),
317*7dc08ffcSJunyu Lai                    StrField("data", ""), ]
318*7dc08ffcSJunyu Lai
319*7dc08ffcSJunyu Laiclass ATT_Write_Command(Packet):
320*7dc08ffcSJunyu Lai    name = "Write Request"
321*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("gatt_handle", 0),
322*7dc08ffcSJunyu Lai                    StrField("data", ""), ]
323*7dc08ffcSJunyu Lai
324*7dc08ffcSJunyu Laiclass ATT_Write_Response(Packet):
325*7dc08ffcSJunyu Lai    name = "Write Response"
326*7dc08ffcSJunyu Lai    fields_desc = [ ]
327*7dc08ffcSJunyu Lai
328*7dc08ffcSJunyu Laiclass ATT_Handle_Value_Notification(Packet):
329*7dc08ffcSJunyu Lai    name = "Handle Value Notification"
330*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("handle", 0),
331*7dc08ffcSJunyu Lai                    StrField("value", ""), ]
332*7dc08ffcSJunyu Lai
333*7dc08ffcSJunyu Lai
334*7dc08ffcSJunyu Laiclass SM_Hdr(Packet):
335*7dc08ffcSJunyu Lai    name = "SM header"
336*7dc08ffcSJunyu Lai    fields_desc = [ ByteField("sm_command", None) ]
337*7dc08ffcSJunyu Lai
338*7dc08ffcSJunyu Lai
339*7dc08ffcSJunyu Laiclass SM_Pairing_Request(Packet):
340*7dc08ffcSJunyu Lai    name = "Pairing Request"
341*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("iocap", 3, {0:"DisplayOnly", 1:"DisplayYesNo", 2:"KeyboardOnly", 3:"NoInputNoOutput", 4:"KeyboardDisplay"}),
342*7dc08ffcSJunyu Lai                    ByteEnumField("oob", 0, {0:"Not Present", 1:"Present (from remote device)"}),
343*7dc08ffcSJunyu Lai                    BitField("authentication", 0, 8),
344*7dc08ffcSJunyu Lai                    ByteField("max_key_size", 16),
345*7dc08ffcSJunyu Lai                    ByteField("initiator_key_distribution", 0),
346*7dc08ffcSJunyu Lai                    ByteField("responder_key_distribution", 0), ]
347*7dc08ffcSJunyu Lai
348*7dc08ffcSJunyu Laiclass SM_Pairing_Response(Packet):
349*7dc08ffcSJunyu Lai    name = "Pairing Response"
350*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("iocap", 3, {0:"DisplayOnly", 1:"DisplayYesNo", 2:"KeyboardOnly", 3:"NoInputNoOutput", 4:"KeyboardDisplay"}),
351*7dc08ffcSJunyu Lai                    ByteEnumField("oob", 0, {0:"Not Present", 1:"Present (from remote device)"}),
352*7dc08ffcSJunyu Lai                    BitField("authentication", 0, 8),
353*7dc08ffcSJunyu Lai                    ByteField("max_key_size", 16),
354*7dc08ffcSJunyu Lai                    ByteField("initiator_key_distribution", 0),
355*7dc08ffcSJunyu Lai                    ByteField("responder_key_distribution", 0), ]
356*7dc08ffcSJunyu Lai
357*7dc08ffcSJunyu Lai
358*7dc08ffcSJunyu Laiclass SM_Confirm(Packet):
359*7dc08ffcSJunyu Lai    name = "Pairing Confirm"
360*7dc08ffcSJunyu Lai    fields_desc = [ StrFixedLenField("confirm", b'\x00' * 16, 16) ]
361*7dc08ffcSJunyu Lai
362*7dc08ffcSJunyu Laiclass SM_Random(Packet):
363*7dc08ffcSJunyu Lai    name = "Pairing Random"
364*7dc08ffcSJunyu Lai    fields_desc = [ StrFixedLenField("random", b'\x00' * 16, 16) ]
365*7dc08ffcSJunyu Lai
366*7dc08ffcSJunyu Laiclass SM_Failed(Packet):
367*7dc08ffcSJunyu Lai    name = "Pairing Failed"
368*7dc08ffcSJunyu Lai    fields_desc = [ XByteField("reason", 0) ]
369*7dc08ffcSJunyu Lai
370*7dc08ffcSJunyu Laiclass SM_Encryption_Information(Packet):
371*7dc08ffcSJunyu Lai    name = "Encryption Information"
372*7dc08ffcSJunyu Lai    fields_desc = [ StrFixedLenField("ltk", b"\x00" * 16, 16), ]
373*7dc08ffcSJunyu Lai
374*7dc08ffcSJunyu Laiclass SM_Master_Identification(Packet):
375*7dc08ffcSJunyu Lai    name = "Master Identification"
376*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("ediv", 0),
377*7dc08ffcSJunyu Lai                    StrFixedLenField("rand", b'\x00' * 8, 8), ]
378*7dc08ffcSJunyu Lai
379*7dc08ffcSJunyu Laiclass SM_Identity_Information(Packet):
380*7dc08ffcSJunyu Lai    name = "Identity Information"
381*7dc08ffcSJunyu Lai    fields_desc = [ StrFixedLenField("irk", b'\x00' * 16, 16), ]
382*7dc08ffcSJunyu Lai
383*7dc08ffcSJunyu Laiclass SM_Identity_Address_Information(Packet):
384*7dc08ffcSJunyu Lai    name = "Identity Address Information"
385*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("atype", 0, {0:"public"}),
386*7dc08ffcSJunyu Lai                    LEMACField("address", None), ]
387*7dc08ffcSJunyu Lai
388*7dc08ffcSJunyu Laiclass SM_Signing_Information(Packet):
389*7dc08ffcSJunyu Lai    name = "Signing Information"
390*7dc08ffcSJunyu Lai    fields_desc = [ StrFixedLenField("csrk", b'\x00' * 16, 16), ]
391*7dc08ffcSJunyu Lai
392*7dc08ffcSJunyu Lai
393*7dc08ffcSJunyu Laiclass EIR_Hdr(Packet):
394*7dc08ffcSJunyu Lai    name = "EIR Header"
395*7dc08ffcSJunyu Lai    fields_desc = [
396*7dc08ffcSJunyu Lai        LenField("len", None, fmt="B", adjust=lambda x: x+1), # Add bytes mark
397*7dc08ffcSJunyu Lai        ByteEnumField("type", 0, {
398*7dc08ffcSJunyu Lai            0x01: "flags",
399*7dc08ffcSJunyu Lai            0x02: "incomplete_list_16_bit_svc_uuids",
400*7dc08ffcSJunyu Lai            0x03: "complete_list_16_bit_svc_uuids",
401*7dc08ffcSJunyu Lai            0x04: "incomplete_list_32_bit_svc_uuids",
402*7dc08ffcSJunyu Lai            0x05: "complete_list_32_bit_svc_uuids",
403*7dc08ffcSJunyu Lai            0x06: "incomplete_list_128_bit_svc_uuids",
404*7dc08ffcSJunyu Lai            0x07: "complete_list_128_bit_svc_uuids",
405*7dc08ffcSJunyu Lai            0x08: "shortened_local_name",
406*7dc08ffcSJunyu Lai            0x09: "complete_local_name",
407*7dc08ffcSJunyu Lai            0x0a: "tx_power_level",
408*7dc08ffcSJunyu Lai            0x0d: "class_of_device",
409*7dc08ffcSJunyu Lai            0x0e: "simple_pairing_hash",
410*7dc08ffcSJunyu Lai            0x0f: "simple_pairing_rand",
411*7dc08ffcSJunyu Lai            0x10: "sec_mgr_tk",
412*7dc08ffcSJunyu Lai            0x11: "sec_mgr_oob_flags",
413*7dc08ffcSJunyu Lai            0x12: "slave_conn_intvl_range",
414*7dc08ffcSJunyu Lai            0x17: "pub_target_addr",
415*7dc08ffcSJunyu Lai            0x18: "rand_target_addr",
416*7dc08ffcSJunyu Lai            0x19: "appearance",
417*7dc08ffcSJunyu Lai            0x1a: "adv_intvl",
418*7dc08ffcSJunyu Lai            0x1b: "le_addr",
419*7dc08ffcSJunyu Lai            0x1c: "le_role",
420*7dc08ffcSJunyu Lai            0x14: "list_16_bit_svc_sollication_uuids",
421*7dc08ffcSJunyu Lai            0x1f: "list_32_bit_svc_sollication_uuids",
422*7dc08ffcSJunyu Lai            0x15: "list_128_bit_svc_sollication_uuids",
423*7dc08ffcSJunyu Lai            0x16: "svc_data_16_bit_uuid",
424*7dc08ffcSJunyu Lai            0x20: "svc_data_32_bit_uuid",
425*7dc08ffcSJunyu Lai            0x21: "svc_data_128_bit_uuid",
426*7dc08ffcSJunyu Lai            0x22: "sec_conn_confirm",
427*7dc08ffcSJunyu Lai            0x22: "sec_conn_rand",
428*7dc08ffcSJunyu Lai            0x24: "uri",
429*7dc08ffcSJunyu Lai            0xff: "mfg_specific_data",
430*7dc08ffcSJunyu Lai        }),
431*7dc08ffcSJunyu Lai    ]
432*7dc08ffcSJunyu Lai
433*7dc08ffcSJunyu Lai    def mysummary(self):
434*7dc08ffcSJunyu Lai        return self.sprintf("EIR %type%")
435*7dc08ffcSJunyu Lai
436*7dc08ffcSJunyu Laiclass EIR_Element(Packet):
437*7dc08ffcSJunyu Lai    name = "EIR Element"
438*7dc08ffcSJunyu Lai
439*7dc08ffcSJunyu Lai    def extract_padding(self, s):
440*7dc08ffcSJunyu Lai        # Needed to end each EIR_Element packet and make PacketListField work.
441*7dc08ffcSJunyu Lai        return '', s
442*7dc08ffcSJunyu Lai
443*7dc08ffcSJunyu Lai    @staticmethod
444*7dc08ffcSJunyu Lai    def length_from(pkt):
445*7dc08ffcSJunyu Lai        if not pkt.underlayer:
446*7dc08ffcSJunyu Lai            warning("Missing an upper-layer")
447*7dc08ffcSJunyu Lai            return 0
448*7dc08ffcSJunyu Lai        # 'type' byte is included in the length, so substract 1:
449*7dc08ffcSJunyu Lai        return pkt.underlayer.len - 1
450*7dc08ffcSJunyu Lai
451*7dc08ffcSJunyu Laiclass EIR_Raw(EIR_Element):
452*7dc08ffcSJunyu Lai    name = "EIR Raw"
453*7dc08ffcSJunyu Lai    fields_desc = [
454*7dc08ffcSJunyu Lai        StrLenField("data", "", length_from=EIR_Element.length_from)
455*7dc08ffcSJunyu Lai    ]
456*7dc08ffcSJunyu Lai
457*7dc08ffcSJunyu Laiclass EIR_Flags(EIR_Element):
458*7dc08ffcSJunyu Lai    name = "Flags"
459*7dc08ffcSJunyu Lai    fields_desc = [
460*7dc08ffcSJunyu Lai        FlagsField("flags", 0x2, 8,
461*7dc08ffcSJunyu Lai                   ["limited_disc_mode", "general_disc_mode",
462*7dc08ffcSJunyu Lai                    "br_edr_not_supported", "simul_le_br_edr_ctrl",
463*7dc08ffcSJunyu Lai                    "simul_le_br_edr_host"] + 3*["reserved"])
464*7dc08ffcSJunyu Lai    ]
465*7dc08ffcSJunyu Lai
466*7dc08ffcSJunyu Laiclass EIR_CompleteList16BitServiceUUIDs(EIR_Element):
467*7dc08ffcSJunyu Lai    name = "Complete list of 16-bit service UUIDs"
468*7dc08ffcSJunyu Lai    fields_desc = [
469*7dc08ffcSJunyu Lai        FieldListField("svc_uuids", None, XLEShortField("uuid", 0),
470*7dc08ffcSJunyu Lai                       length_from=EIR_Element.length_from)
471*7dc08ffcSJunyu Lai    ]
472*7dc08ffcSJunyu Lai
473*7dc08ffcSJunyu Laiclass EIR_IncompleteList16BitServiceUUIDs(EIR_CompleteList16BitServiceUUIDs):
474*7dc08ffcSJunyu Lai    name = "Incomplete list of 16-bit service UUIDs"
475*7dc08ffcSJunyu Lai
476*7dc08ffcSJunyu Laiclass EIR_CompleteLocalName(EIR_Element):
477*7dc08ffcSJunyu Lai    name = "Complete Local Name"
478*7dc08ffcSJunyu Lai    fields_desc = [
479*7dc08ffcSJunyu Lai        StrLenField("local_name", "", length_from=EIR_Element.length_from)
480*7dc08ffcSJunyu Lai    ]
481*7dc08ffcSJunyu Lai
482*7dc08ffcSJunyu Laiclass EIR_ShortenedLocalName(EIR_CompleteLocalName):
483*7dc08ffcSJunyu Lai    name = "Shortened Local Name"
484*7dc08ffcSJunyu Lai
485*7dc08ffcSJunyu Laiclass EIR_TX_Power_Level(EIR_Element):
486*7dc08ffcSJunyu Lai    name = "TX Power Level"
487*7dc08ffcSJunyu Lai    fields_desc = [SignedByteField("level", 0)]
488*7dc08ffcSJunyu Lai
489*7dc08ffcSJunyu Laiclass EIR_Manufacturer_Specific_Data(EIR_Element):
490*7dc08ffcSJunyu Lai    name = "EIR Manufacturer Specific Data"
491*7dc08ffcSJunyu Lai    fields_desc = [
492*7dc08ffcSJunyu Lai        XLEShortField("company_id", 0),
493*7dc08ffcSJunyu Lai        StrLenField("data", "",
494*7dc08ffcSJunyu Lai                    length_from=lambda pkt: EIR_Element.length_from(pkt) - 2)
495*7dc08ffcSJunyu Lai    ]
496*7dc08ffcSJunyu Lai
497*7dc08ffcSJunyu Lai
498*7dc08ffcSJunyu Laiclass HCI_Command_Hdr(Packet):
499*7dc08ffcSJunyu Lai    name = "HCI Command header"
500*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("opcode", 0),
501*7dc08ffcSJunyu Lai                    ByteField("len", None), ]
502*7dc08ffcSJunyu Lai
503*7dc08ffcSJunyu Lai    def post_build(self, p, pay):
504*7dc08ffcSJunyu Lai        p += pay
505*7dc08ffcSJunyu Lai        if self.len is None:
506*7dc08ffcSJunyu Lai            p = p[:2] + struct.pack("B", len(pay)) + p[3:]
507*7dc08ffcSJunyu Lai        return p
508*7dc08ffcSJunyu Lai
509*7dc08ffcSJunyu Laiclass HCI_Cmd_Reset(Packet):
510*7dc08ffcSJunyu Lai    name = "Reset"
511*7dc08ffcSJunyu Lai
512*7dc08ffcSJunyu Laiclass HCI_Cmd_Set_Event_Filter(Packet):
513*7dc08ffcSJunyu Lai    name = "Set Event Filter"
514*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("type", 0, {0:"clear"}), ]
515*7dc08ffcSJunyu Lai
516*7dc08ffcSJunyu Laiclass HCI_Cmd_Connect_Accept_Timeout(Packet):
517*7dc08ffcSJunyu Lai    name = "Connection Attempt Timeout"
518*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("timeout", 32000) ] # 32000 slots is 20000 msec
519*7dc08ffcSJunyu Lai
520*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Host_Supported(Packet):
521*7dc08ffcSJunyu Lai    name = "LE Host Supported"
522*7dc08ffcSJunyu Lai    fields_desc = [ ByteField("supported", 1),
523*7dc08ffcSJunyu Lai                    ByteField("simultaneous", 1), ]
524*7dc08ffcSJunyu Lai
525*7dc08ffcSJunyu Laiclass HCI_Cmd_Set_Event_Mask(Packet):
526*7dc08ffcSJunyu Lai    name = "Set Event Mask"
527*7dc08ffcSJunyu Lai    fields_desc = [ StrFixedLenField("mask", b"\xff\xff\xfb\xff\x07\xf8\xbf\x3d", 8) ]
528*7dc08ffcSJunyu Lai
529*7dc08ffcSJunyu Laiclass HCI_Cmd_Read_BD_Addr(Packet):
530*7dc08ffcSJunyu Lai    name = "Read BD Addr"
531*7dc08ffcSJunyu Lai
532*7dc08ffcSJunyu Lai
533*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Set_Scan_Parameters(Packet):
534*7dc08ffcSJunyu Lai    name = "LE Set Scan Parameters"
535*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("type", 1, {1:"active"}),
536*7dc08ffcSJunyu Lai                    XLEShortField("interval", 16),
537*7dc08ffcSJunyu Lai                    XLEShortField("window", 16),
538*7dc08ffcSJunyu Lai                    ByteEnumField("atype", 0, {0:"public"}),
539*7dc08ffcSJunyu Lai                    ByteEnumField("policy", 0, {0:"all"}), ]
540*7dc08ffcSJunyu Lai
541*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Set_Scan_Enable(Packet):
542*7dc08ffcSJunyu Lai    name = "LE Set Scan Enable"
543*7dc08ffcSJunyu Lai    fields_desc = [ ByteField("enable", 1),
544*7dc08ffcSJunyu Lai                    ByteField("filter_dups", 1), ]
545*7dc08ffcSJunyu Lai
546*7dc08ffcSJunyu Laiclass HCI_Cmd_Disconnect(Packet):
547*7dc08ffcSJunyu Lai    name = "Disconnect"
548*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("handle", 0),
549*7dc08ffcSJunyu Lai                    ByteField("reason", 0x13), ]
550*7dc08ffcSJunyu Lai
551*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Create_Connection(Packet):
552*7dc08ffcSJunyu Lai    name = "LE Create Connection"
553*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("interval", 96),
554*7dc08ffcSJunyu Lai                    LEShortField("window", 48),
555*7dc08ffcSJunyu Lai                    ByteEnumField("filter", 0, {0:"address"}),
556*7dc08ffcSJunyu Lai                    ByteEnumField("patype", 0, {0:"public", 1:"random"}),
557*7dc08ffcSJunyu Lai                    LEMACField("paddr", None),
558*7dc08ffcSJunyu Lai                    ByteEnumField("atype", 0, {0:"public", 1:"random"}),
559*7dc08ffcSJunyu Lai                    LEShortField("min_interval", 40),
560*7dc08ffcSJunyu Lai                    LEShortField("max_interval", 56),
561*7dc08ffcSJunyu Lai                    LEShortField("latency", 0),
562*7dc08ffcSJunyu Lai                    LEShortField("timeout", 42),
563*7dc08ffcSJunyu Lai                    LEShortField("min_ce", 0),
564*7dc08ffcSJunyu Lai                    LEShortField("max_ce", 0), ]
565*7dc08ffcSJunyu Lai
566*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Create_Connection_Cancel(Packet):
567*7dc08ffcSJunyu Lai    name = "LE Create Connection Cancel"
568*7dc08ffcSJunyu Lai
569*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Connection_Update(Packet):
570*7dc08ffcSJunyu Lai    name = "LE Connection Update"
571*7dc08ffcSJunyu Lai    fields_desc = [ XLEShortField("handle", 0),
572*7dc08ffcSJunyu Lai                    XLEShortField("min_interval", 0),
573*7dc08ffcSJunyu Lai                    XLEShortField("max_interval", 0),
574*7dc08ffcSJunyu Lai                    XLEShortField("latency", 0),
575*7dc08ffcSJunyu Lai                    XLEShortField("timeout", 0),
576*7dc08ffcSJunyu Lai                    LEShortField("min_ce", 0),
577*7dc08ffcSJunyu Lai                    LEShortField("max_ce", 0xffff), ]
578*7dc08ffcSJunyu Lai
579*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Read_Buffer_Size(Packet):
580*7dc08ffcSJunyu Lai    name = "LE Read Buffer Size"
581*7dc08ffcSJunyu Lai
582*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Set_Random_Address(Packet):
583*7dc08ffcSJunyu Lai    name = "LE Set Random Address"
584*7dc08ffcSJunyu Lai    fields_desc = [ LEMACField("address", None) ]
585*7dc08ffcSJunyu Lai
586*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Set_Advertising_Parameters(Packet):
587*7dc08ffcSJunyu Lai    name = "LE Set Advertising Parameters"
588*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("interval_min", 0x0800),
589*7dc08ffcSJunyu Lai                    LEShortField("interval_max", 0x0800),
590*7dc08ffcSJunyu Lai                    ByteEnumField("adv_type", 0, {0:"ADV_IND", 1:"ADV_DIRECT_IND", 2:"ADV_SCAN_IND", 3:"ADV_NONCONN_IND", 4:"ADV_DIRECT_IND_LOW"}),
591*7dc08ffcSJunyu Lai                    ByteEnumField("oatype", 0, {0:"public", 1:"random"}),
592*7dc08ffcSJunyu Lai                    ByteEnumField("datype", 0, {0:"public", 1:"random"}),
593*7dc08ffcSJunyu Lai                    LEMACField("daddr", None),
594*7dc08ffcSJunyu Lai                    ByteField("channel_map", 7),
595*7dc08ffcSJunyu Lai                    ByteEnumField("filter_policy", 0, {0:"all:all", 1:"connect:all scan:whitelist", 2:"connect:whitelist scan:all", 3:"all:whitelist"}), ]
596*7dc08ffcSJunyu Lai
597*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Set_Advertising_Data(Packet):
598*7dc08ffcSJunyu Lai    name = "LE Set Advertising Data"
599*7dc08ffcSJunyu Lai    fields_desc = [ FieldLenField("len", None, length_of="data", fmt="B"),
600*7dc08ffcSJunyu Lai                    StrLenField("data", "", length_from=lambda pkt:pkt.len), ]
601*7dc08ffcSJunyu Lai
602*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Set_Advertise_Enable(Packet):
603*7dc08ffcSJunyu Lai    name = "LE Set Advertise Enable"
604*7dc08ffcSJunyu Lai    fields_desc = [ ByteField("enable", 0) ]
605*7dc08ffcSJunyu Lai
606*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Start_Encryption_Request(Packet):
607*7dc08ffcSJunyu Lai    name = "LE Start Encryption"
608*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("handle", 0),
609*7dc08ffcSJunyu Lai                    StrFixedLenField("rand", None, 8),
610*7dc08ffcSJunyu Lai                    XLEShortField("ediv", 0),
611*7dc08ffcSJunyu Lai                    StrFixedLenField("ltk", b'\x00' * 16, 16), ]
612*7dc08ffcSJunyu Lai
613*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply(Packet):
614*7dc08ffcSJunyu Lai    name = "LE Long Term Key Request Negative Reply"
615*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("handle", 0), ]
616*7dc08ffcSJunyu Lai
617*7dc08ffcSJunyu Laiclass HCI_Cmd_LE_Long_Term_Key_Request_Reply(Packet):
618*7dc08ffcSJunyu Lai    name = "LE Long Term Key Request Reply"
619*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("handle", 0),
620*7dc08ffcSJunyu Lai                    StrFixedLenField("ltk", b'\x00' * 16, 16), ]
621*7dc08ffcSJunyu Lai
622*7dc08ffcSJunyu Laiclass HCI_Event_Hdr(Packet):
623*7dc08ffcSJunyu Lai    name = "HCI Event header"
624*7dc08ffcSJunyu Lai    fields_desc = [ XByteField("code", 0),
625*7dc08ffcSJunyu Lai                    ByteField("length", 0), ]
626*7dc08ffcSJunyu Lai
627*7dc08ffcSJunyu Lai
628*7dc08ffcSJunyu Laiclass HCI_Event_Disconnection_Complete(Packet):
629*7dc08ffcSJunyu Lai    name = "Disconnection Complete"
630*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("status", 0, {0:"success"}),
631*7dc08ffcSJunyu Lai                    LEShortField("handle", 0),
632*7dc08ffcSJunyu Lai                    XByteField("reason", 0), ]
633*7dc08ffcSJunyu Lai
634*7dc08ffcSJunyu Lai
635*7dc08ffcSJunyu Laiclass HCI_Event_Encryption_Change(Packet):
636*7dc08ffcSJunyu Lai    name = "Encryption Change"
637*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("status", 0, {0:"change has occurred"}),
638*7dc08ffcSJunyu Lai                    LEShortField("handle", 0),
639*7dc08ffcSJunyu Lai                    ByteEnumField("enabled", 0, {0:"OFF", 1:"ON (LE)", 2:"ON (BR/EDR)"}), ]
640*7dc08ffcSJunyu Lai
641*7dc08ffcSJunyu Laiclass HCI_Event_Command_Complete(Packet):
642*7dc08ffcSJunyu Lai    name = "Command Complete"
643*7dc08ffcSJunyu Lai    fields_desc = [ ByteField("number", 0),
644*7dc08ffcSJunyu Lai                    XLEShortField("opcode", 0),
645*7dc08ffcSJunyu Lai                    ByteEnumField("status", 0, {0:"success"}), ]
646*7dc08ffcSJunyu Lai
647*7dc08ffcSJunyu Lai
648*7dc08ffcSJunyu Laiclass HCI_Cmd_Complete_Read_BD_Addr(Packet):
649*7dc08ffcSJunyu Lai    name = "Read BD Addr"
650*7dc08ffcSJunyu Lai    fields_desc = [ LEMACField("addr", None), ]
651*7dc08ffcSJunyu Lai
652*7dc08ffcSJunyu Lai
653*7dc08ffcSJunyu Lai
654*7dc08ffcSJunyu Laiclass HCI_Event_Command_Status(Packet):
655*7dc08ffcSJunyu Lai    name = "Command Status"
656*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("status", 0, {0:"pending"}),
657*7dc08ffcSJunyu Lai                    ByteField("number", 0),
658*7dc08ffcSJunyu Lai                    XLEShortField("opcode", None), ]
659*7dc08ffcSJunyu Lai
660*7dc08ffcSJunyu Laiclass HCI_Event_Number_Of_Completed_Packets(Packet):
661*7dc08ffcSJunyu Lai    name = "Number Of Completed Packets"
662*7dc08ffcSJunyu Lai    fields_desc = [ ByteField("number", 0) ]
663*7dc08ffcSJunyu Lai
664*7dc08ffcSJunyu Laiclass HCI_Event_LE_Meta(Packet):
665*7dc08ffcSJunyu Lai    name = "LE Meta"
666*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("event", 0, {2:"advertising_report"}) ]
667*7dc08ffcSJunyu Lai
668*7dc08ffcSJunyu Laiclass HCI_LE_Meta_Connection_Complete(Packet):
669*7dc08ffcSJunyu Lai    name = "Connection Complete"
670*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("status", 0, {0:"success"}),
671*7dc08ffcSJunyu Lai                    LEShortField("handle", 0),
672*7dc08ffcSJunyu Lai                    ByteEnumField("role", 0, {0:"master"}),
673*7dc08ffcSJunyu Lai                    ByteEnumField("patype", 0, {0:"public", 1:"random"}),
674*7dc08ffcSJunyu Lai                    LEMACField("paddr", None),
675*7dc08ffcSJunyu Lai                    LEShortField("interval", 54),
676*7dc08ffcSJunyu Lai                    LEShortField("latency", 0),
677*7dc08ffcSJunyu Lai                    LEShortField("supervision", 42),
678*7dc08ffcSJunyu Lai                    XByteField("clock_latency", 5), ]
679*7dc08ffcSJunyu Lai
680*7dc08ffcSJunyu Laiclass HCI_LE_Meta_Connection_Update_Complete(Packet):
681*7dc08ffcSJunyu Lai    name = "Connection Update Complete"
682*7dc08ffcSJunyu Lai    fields_desc = [ ByteEnumField("status", 0, {0:"success"}),
683*7dc08ffcSJunyu Lai                    LEShortField("handle", 0),
684*7dc08ffcSJunyu Lai                    LEShortField("interval", 54),
685*7dc08ffcSJunyu Lai                    LEShortField("latency", 0),
686*7dc08ffcSJunyu Lai                    LEShortField("timeout", 42), ]
687*7dc08ffcSJunyu Lai
688*7dc08ffcSJunyu Laiclass HCI_LE_Meta_Advertising_Report(Packet):
689*7dc08ffcSJunyu Lai    name = "Advertising Report"
690*7dc08ffcSJunyu Lai    fields_desc = [ ByteField("number", 0),
691*7dc08ffcSJunyu Lai                    ByteEnumField("type", 0, {0:"conn_und", 4:"scan_rsp"}),
692*7dc08ffcSJunyu Lai                    ByteEnumField("atype", 0, {0:"public", 1:"random"}),
693*7dc08ffcSJunyu Lai                    LEMACField("addr", None),
694*7dc08ffcSJunyu Lai                    FieldLenField("len", None, length_of="data", fmt="B"),
695*7dc08ffcSJunyu Lai                    PacketListField("data", [], EIR_Hdr,
696*7dc08ffcSJunyu Lai                                    length_from=lambda pkt:pkt.len),
697*7dc08ffcSJunyu Lai                    SignedByteField("rssi", 0)]
698*7dc08ffcSJunyu Lai
699*7dc08ffcSJunyu Lai
700*7dc08ffcSJunyu Laiclass HCI_LE_Meta_Long_Term_Key_Request(Packet):
701*7dc08ffcSJunyu Lai    name = "Long Term Key Request"
702*7dc08ffcSJunyu Lai    fields_desc = [ LEShortField("handle", 0),
703*7dc08ffcSJunyu Lai                    StrFixedLenField("rand", None, 8),
704*7dc08ffcSJunyu Lai                    XLEShortField("ediv", 0), ]
705*7dc08ffcSJunyu Lai
706*7dc08ffcSJunyu Lai
707*7dc08ffcSJunyu Laibind_layers( HCI_Hdr,       HCI_Command_Hdr,    type=1)
708*7dc08ffcSJunyu Laibind_layers( HCI_Hdr,       HCI_ACL_Hdr,        type=2)
709*7dc08ffcSJunyu Laibind_layers( HCI_Hdr,       HCI_Event_Hdr,      type=4)
710*7dc08ffcSJunyu Laibind_layers( HCI_Hdr,       conf.raw_layer,           )
711*7dc08ffcSJunyu Lai
712*7dc08ffcSJunyu Laiconf.l2types.register(DLT_BLUETOOTH_HCI_H4, HCI_Hdr)
713*7dc08ffcSJunyu Lai
714*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_Reset, opcode=0x0c03)
715*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_Set_Event_Mask, opcode=0x0c01)
716*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_Set_Event_Filter, opcode=0x0c05)
717*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_Connect_Accept_Timeout, opcode=0x0c16)
718*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Host_Supported, opcode=0x0c6d)
719*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_Read_BD_Addr, opcode=0x1009)
720*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size, opcode=0x2002)
721*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Set_Random_Address, opcode=0x2005)
722*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Parameters, opcode=0x2006)
723*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Data, opcode=0x2008)
724*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertise_Enable, opcode=0x200a)
725*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Parameters, opcode=0x200b)
726*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Enable, opcode=0x200c)
727*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_Disconnect, opcode=0x406)
728*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection, opcode=0x200d)
729*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection_Cancel, opcode=0x200e)
730*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Connection_Update, opcode=0x2013)
731*7dc08ffcSJunyu Lai
732*7dc08ffcSJunyu Lai
733*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Start_Encryption_Request, opcode=0x2019)
734*7dc08ffcSJunyu Lai
735*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Reply, opcode=0x201a)
736*7dc08ffcSJunyu Laibind_layers( HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply, opcode=0x201b)
737*7dc08ffcSJunyu Lai
738*7dc08ffcSJunyu Laibind_layers( HCI_Event_Hdr, HCI_Event_Disconnection_Complete, code=0x5)
739*7dc08ffcSJunyu Laibind_layers( HCI_Event_Hdr, HCI_Event_Encryption_Change, code=0x8)
740*7dc08ffcSJunyu Laibind_layers( HCI_Event_Hdr, HCI_Event_Command_Complete, code=0xe)
741*7dc08ffcSJunyu Laibind_layers( HCI_Event_Hdr, HCI_Event_Command_Status, code=0xf)
742*7dc08ffcSJunyu Laibind_layers( HCI_Event_Hdr, HCI_Event_Number_Of_Completed_Packets, code=0x13)
743*7dc08ffcSJunyu Laibind_layers( HCI_Event_Hdr, HCI_Event_LE_Meta, code=0x3e)
744*7dc08ffcSJunyu Lai
745*7dc08ffcSJunyu Laibind_layers( HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_BD_Addr, opcode=0x1009)
746*7dc08ffcSJunyu Lai
747*7dc08ffcSJunyu Laibind_layers( HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Complete, event=1)
748*7dc08ffcSJunyu Laibind_layers( HCI_Event_LE_Meta, HCI_LE_Meta_Advertising_Report, event=2)
749*7dc08ffcSJunyu Laibind_layers( HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Update_Complete, event=3)
750*7dc08ffcSJunyu Laibind_layers( HCI_Event_LE_Meta, HCI_LE_Meta_Long_Term_Key_Request, event=5)
751*7dc08ffcSJunyu Lai
752*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_Flags, type=0x01)
753*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_IncompleteList16BitServiceUUIDs, type=0x02)
754*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_CompleteList16BitServiceUUIDs, type=0x03)
755*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_ShortenedLocalName, type=0x08)
756*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_CompleteLocalName, type=0x09)
757*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_TX_Power_Level, type=0x0a)
758*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_Manufacturer_Specific_Data, type=0xff)
759*7dc08ffcSJunyu Laibind_layers(EIR_Hdr, EIR_Raw)
760*7dc08ffcSJunyu Lai
761*7dc08ffcSJunyu Laibind_layers( HCI_ACL_Hdr,   L2CAP_Hdr,     )
762*7dc08ffcSJunyu Laibind_layers( L2CAP_Hdr,     L2CAP_CmdHdr,      cid=1)
763*7dc08ffcSJunyu Laibind_layers( L2CAP_Hdr,     L2CAP_CmdHdr,      cid=5) #LE L2CAP Signaling Channel
764*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_CmdRej,      code=1)
765*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_ConnReq,     code=2)
766*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_ConnResp,    code=3)
767*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_ConfReq,     code=4)
768*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_ConfResp,    code=5)
769*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_DisconnReq,  code=6)
770*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_DisconnResp, code=7)
771*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_InfoReq,     code=10)
772*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_InfoResp,    code=11)
773*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_Connection_Parameter_Update_Request,    code=18)
774*7dc08ffcSJunyu Laibind_layers( L2CAP_CmdHdr,  L2CAP_Connection_Parameter_Update_Response,    code=19)
775*7dc08ffcSJunyu Laibind_layers( L2CAP_Hdr,     ATT_Hdr,           cid=4)
776*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Error_Response, opcode=0x1)
777*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Exchange_MTU_Request, opcode=0x2)
778*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Exchange_MTU_Response, opcode=0x3)
779*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Find_Information_Request, opcode=0x4)
780*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Find_Information_Response, opcode=0x5)
781*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Find_By_Type_Value_Request, opcode=0x6)
782*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Find_By_Type_Value_Response, opcode=0x7)
783*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Read_By_Type_Request_128bit, opcode=0x8)
784*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Read_By_Type_Request, opcode=0x8)
785*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Read_By_Type_Response, opcode=0x9)
786*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Read_Request, opcode=0xa)
787*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Read_Response, opcode=0xb)
788*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Read_By_Group_Type_Request, opcode=0x10)
789*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Read_By_Group_Type_Response, opcode=0x11)
790*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Write_Request, opcode=0x12)
791*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Write_Response, opcode=0x13)
792*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Write_Command, opcode=0x52)
793*7dc08ffcSJunyu Laibind_layers( ATT_Hdr,       ATT_Handle_Value_Notification, opcode=0x1b)
794*7dc08ffcSJunyu Laibind_layers( L2CAP_Hdr,     SM_Hdr,            cid=6)
795*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Pairing_Request, sm_command=1)
796*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Pairing_Response, sm_command=2)
797*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Confirm,        sm_command=3)
798*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Random,         sm_command=4)
799*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Failed,         sm_command=5)
800*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Encryption_Information, sm_command=6)
801*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Master_Identification, sm_command=7)
802*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Identity_Information, sm_command=8)
803*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Identity_Address_Information, sm_command=9)
804*7dc08ffcSJunyu Laibind_layers( SM_Hdr,        SM_Signing_Information, sm_command=0x0a)
805*7dc08ffcSJunyu Lai
806*7dc08ffcSJunyu Laiclass BluetoothSocketError(BaseException):
807*7dc08ffcSJunyu Lai    pass
808*7dc08ffcSJunyu Lai
809*7dc08ffcSJunyu Laiclass BluetoothCommandError(BaseException):
810*7dc08ffcSJunyu Lai    pass
811*7dc08ffcSJunyu Lai
812*7dc08ffcSJunyu Laiclass BluetoothL2CAPSocket(SuperSocket):
813*7dc08ffcSJunyu Lai    desc = "read/write packets on a connected L2CAP socket"
814*7dc08ffcSJunyu Lai    def __init__(self, bt_address):
815*7dc08ffcSJunyu Lai        if WINDOWS:
816*7dc08ffcSJunyu Lai            warning("Not available on Windows")
817*7dc08ffcSJunyu Lai            return
818*7dc08ffcSJunyu Lai        s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
819*7dc08ffcSJunyu Lai                          socket.BTPROTO_L2CAP)
820*7dc08ffcSJunyu Lai        s.connect((bt_address,0))
821*7dc08ffcSJunyu Lai        self.ins = self.outs = s
822*7dc08ffcSJunyu Lai
823*7dc08ffcSJunyu Lai    def recv(self, x=MTU):
824*7dc08ffcSJunyu Lai        return L2CAP_CmdHdr(self.ins.recv(x))
825*7dc08ffcSJunyu Lai
826*7dc08ffcSJunyu Laiclass BluetoothRFCommSocket(BluetoothL2CAPSocket):
827*7dc08ffcSJunyu Lai    """read/write packets on a connected RFCOMM socket"""
828*7dc08ffcSJunyu Lai    def __init__(self, bt_address, port=0):
829*7dc08ffcSJunyu Lai        s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
830*7dc08ffcSJunyu Lai                          socket.BTPROTO_RFCOMM)
831*7dc08ffcSJunyu Lai        s.connect((bt_address,port))
832*7dc08ffcSJunyu Lai        self.ins = self.outs = s
833*7dc08ffcSJunyu Lai
834*7dc08ffcSJunyu Laiclass BluetoothHCISocket(SuperSocket):
835*7dc08ffcSJunyu Lai    desc = "read/write on a BlueTooth HCI socket"
836*7dc08ffcSJunyu Lai    def __init__(self, iface=0x10000, type=None):
837*7dc08ffcSJunyu Lai        if WINDOWS:
838*7dc08ffcSJunyu Lai            warning("Not available on Windows")
839*7dc08ffcSJunyu Lai            return
840*7dc08ffcSJunyu Lai        s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
841*7dc08ffcSJunyu Lai        s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR,1)
842*7dc08ffcSJunyu Lai        s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP,1)
843*7dc08ffcSJunyu Lai        s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffff,0xffffffff,0xffffffff,0)) #type mask, event mask, event mask, opcode
844*7dc08ffcSJunyu Lai        s.bind((iface,))
845*7dc08ffcSJunyu Lai        self.ins = self.outs = s
846*7dc08ffcSJunyu Lai#        s.connect((peer,0))
847*7dc08ffcSJunyu Lai
848*7dc08ffcSJunyu Lai
849*7dc08ffcSJunyu Lai    def recv(self, x):
850*7dc08ffcSJunyu Lai        return HCI_Hdr(self.ins.recv(x))
851*7dc08ffcSJunyu Lai
852*7dc08ffcSJunyu Laiclass sockaddr_hci(Structure):
853*7dc08ffcSJunyu Lai    _fields_ = [
854*7dc08ffcSJunyu Lai        ("sin_family",      c_ushort),
855*7dc08ffcSJunyu Lai        ("hci_dev",         c_ushort),
856*7dc08ffcSJunyu Lai        ("hci_channel",     c_ushort),
857*7dc08ffcSJunyu Lai    ]
858*7dc08ffcSJunyu Lai
859*7dc08ffcSJunyu Laiclass BluetoothUserSocket(SuperSocket):
860*7dc08ffcSJunyu Lai    desc = "read/write H4 over a Bluetooth user channel"
861*7dc08ffcSJunyu Lai    def __init__(self, adapter_index=0):
862*7dc08ffcSJunyu Lai        if WINDOWS:
863*7dc08ffcSJunyu Lai            warning("Not available on Windows")
864*7dc08ffcSJunyu Lai            return
865*7dc08ffcSJunyu Lai        # s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
866*7dc08ffcSJunyu Lai        # s.bind((0,1))
867*7dc08ffcSJunyu Lai
868*7dc08ffcSJunyu Lai        # yeah, if only
869*7dc08ffcSJunyu Lai        # thanks to Python's weak ass socket and bind implementations, we have
870*7dc08ffcSJunyu Lai        # to call down into libc with ctypes
871*7dc08ffcSJunyu Lai
872*7dc08ffcSJunyu Lai        sockaddr_hcip = POINTER(sockaddr_hci)
873*7dc08ffcSJunyu Lai        cdll.LoadLibrary("libc.so.6")
874*7dc08ffcSJunyu Lai        libc = CDLL("libc.so.6")
875*7dc08ffcSJunyu Lai
876*7dc08ffcSJunyu Lai        socket_c = libc.socket
877*7dc08ffcSJunyu Lai        socket_c.argtypes = (c_int, c_int, c_int);
878*7dc08ffcSJunyu Lai        socket_c.restype = c_int
879*7dc08ffcSJunyu Lai
880*7dc08ffcSJunyu Lai        bind = libc.bind
881*7dc08ffcSJunyu Lai        bind.argtypes = (c_int, POINTER(sockaddr_hci), c_int)
882*7dc08ffcSJunyu Lai        bind.restype = c_int
883*7dc08ffcSJunyu Lai
884*7dc08ffcSJunyu Lai        ########
885*7dc08ffcSJunyu Lai        ## actual code
886*7dc08ffcSJunyu Lai
887*7dc08ffcSJunyu Lai        s = socket_c(31, 3, 1) # (AF_BLUETOOTH, SOCK_RAW, HCI_CHANNEL_USER)
888*7dc08ffcSJunyu Lai        if s < 0:
889*7dc08ffcSJunyu Lai            raise BluetoothSocketError("Unable to open PF_BLUETOOTH socket")
890*7dc08ffcSJunyu Lai
891*7dc08ffcSJunyu Lai        sa = sockaddr_hci()
892*7dc08ffcSJunyu Lai        sa.sin_family = 31  # AF_BLUETOOTH
893*7dc08ffcSJunyu Lai        sa.hci_dev = adapter_index # adapter index
894*7dc08ffcSJunyu Lai        sa.hci_channel = 1   # HCI_USER_CHANNEL
895*7dc08ffcSJunyu Lai
896*7dc08ffcSJunyu Lai        r = bind(s, sockaddr_hcip(sa), sizeof(sa))
897*7dc08ffcSJunyu Lai        if r != 0:
898*7dc08ffcSJunyu Lai            raise BluetoothSocketError("Unable to bind")
899*7dc08ffcSJunyu Lai
900*7dc08ffcSJunyu Lai        self.ins = self.outs = socket.fromfd(s, 31, 3, 1)
901*7dc08ffcSJunyu Lai
902*7dc08ffcSJunyu Lai    def send_command(self, cmd):
903*7dc08ffcSJunyu Lai        opcode = cmd.opcode
904*7dc08ffcSJunyu Lai        self.send(cmd)
905*7dc08ffcSJunyu Lai        while True:
906*7dc08ffcSJunyu Lai            r = self.recv()
907*7dc08ffcSJunyu Lai            if r.type == 0x04 and r.code == 0xe and r.opcode == opcode:
908*7dc08ffcSJunyu Lai                if r.status != 0:
909*7dc08ffcSJunyu Lai                    raise BluetoothCommandError("Command %x failed with %x" % (opcode, r.status))
910*7dc08ffcSJunyu Lai                return r
911*7dc08ffcSJunyu Lai
912*7dc08ffcSJunyu Lai    def recv(self, x=512):
913*7dc08ffcSJunyu Lai        return HCI_Hdr(self.ins.recv(x))
914*7dc08ffcSJunyu Lai
915*7dc08ffcSJunyu Lai    def readable(self, timeout=0):
916*7dc08ffcSJunyu Lai        (ins, outs, foo) = select([self.ins], [], [], timeout)
917*7dc08ffcSJunyu Lai        return len(ins) > 0
918*7dc08ffcSJunyu Lai
919*7dc08ffcSJunyu Lai    def flush(self):
920*7dc08ffcSJunyu Lai        while self.readable():
921*7dc08ffcSJunyu Lai            self.recv()
922*7dc08ffcSJunyu Lai
923*7dc08ffcSJunyu Laiconf.BTsocket = BluetoothRFCommSocket
924*7dc08ffcSJunyu Lai
925*7dc08ffcSJunyu Lai## Bluetooth
926*7dc08ffcSJunyu Lai
927*7dc08ffcSJunyu Lai@conf.commands.register
928*7dc08ffcSJunyu Laidef srbt(bt_address, pkts, inter=0.1, *args, **kargs):
929*7dc08ffcSJunyu Lai    """send and receive using a bluetooth socket"""
930*7dc08ffcSJunyu Lai    if "port" in kargs.keys():
931*7dc08ffcSJunyu Lai        s = conf.BTsocket(bt_address=bt_address, port=kargs.pop("port"))
932*7dc08ffcSJunyu Lai    else:
933*7dc08ffcSJunyu Lai        s = conf.BTsocket(bt_address=bt_address)
934*7dc08ffcSJunyu Lai    a,b = sndrcv(s,pkts,inter=inter,*args,**kargs)
935*7dc08ffcSJunyu Lai    s.close()
936*7dc08ffcSJunyu Lai    return a,b
937*7dc08ffcSJunyu Lai
938*7dc08ffcSJunyu Lai@conf.commands.register
939*7dc08ffcSJunyu Laidef srbt1(bt_address, pkts, *args, **kargs):
940*7dc08ffcSJunyu Lai    """send and receive 1 packet using a bluetooth socket"""
941*7dc08ffcSJunyu Lai    a,b = srbt(bt_address, pkts, *args, **kargs)
942*7dc08ffcSJunyu Lai    if len(a) > 0:
943*7dc08ffcSJunyu Lai        return a[0][1]
944