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