1# Lint as: python2, python3 2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6from __future__ import absolute_import 7from __future__ import division 8from __future__ import print_function 9import array 10import btsocket 11import fcntl 12import logging 13import socket 14import struct 15import six 16 17 18# Constants from lib/mgmt.h in BlueZ source 19MGMT_INDEX_NONE = 0xFFFF 20 21MGMT_HDR_SIZE = 6 22 23MGMT_STATUS_SUCCESS = 0x00 24MGMT_STATUS_UNKNOWN_COMMAND = 0x01 25MGMT_STATUS_NOT_CONNECTED = 0x02 26MGMT_STATUS_FAILED = 0x03 27MGMT_STATUS_CONNECT_FAILED = 0x04 28MGMT_STATUS_AUTH_FAILED = 0x05 29MGMT_STATUS_NOT_PAIRED = 0x06 30MGMT_STATUS_NO_RESOURCES = 0x07 31MGMT_STATUS_TIMEOUT = 0x08 32MGMT_STATUS_ALREADY_CONNECTED = 0x09 33MGMT_STATUS_BUSY = 0x0a 34MGMT_STATUS_REJECTED = 0x0b 35MGMT_STATUS_NOT_SUPPORTED = 0x0c 36MGMT_STATUS_INVALID_PARAMS = 0x0d 37MGMT_STATUS_DISCONNECTED = 0x0e 38MGMT_STATUS_NOT_POWERED = 0x0f 39MGMT_STATUS_CANCELLED = 0x10 40MGMT_STATUS_INVALID_INDEX = 0x11 41MGMT_STATUS_RFKILLED = 0x12 42 43MGMT_OP_READ_VERSION = 0x0001 44MGMT_OP_READ_COMMANDS = 0x0002 45MGMT_OP_READ_INDEX_LIST = 0x0003 46MGMT_OP_READ_INFO = 0x0004 47MGMT_OP_SET_POWERED = 0x0005 48MGMT_OP_SET_DISCOVERABLE = 0x0006 49MGMT_OP_SET_CONNECTABLE = 0x0007 50MGMT_OP_SET_FAST_CONNECTABLE = 0x0008 51MGMT_OP_SET_PAIRABLE = 0x0009 52MGMT_OP_SET_LINK_SECURITY = 0x000A 53MGMT_OP_SET_SSP = 0x000B 54MGMT_OP_SET_HS = 0x000C 55MGMT_OP_SET_LE = 0x000D 56MGMT_OP_SET_DEV_CLASS = 0x000E 57MGMT_OP_SET_LOCAL_NAME = 0x000F 58MGMT_OP_ADD_UUID = 0x0010 59MGMT_OP_REMOVE_UUID = 0x0011 60MGMT_OP_LOAD_LINK_KEYS = 0x0012 61MGMT_OP_LOAD_LONG_TERM_KEYS = 0x0013 62MGMT_OP_DISCONNECT = 0x0014 63MGMT_OP_GET_CONNECTIONS = 0x0015 64MGMT_OP_PIN_CODE_REPLY = 0x0016 65MGMT_OP_PIN_CODE_NEG_REPLY = 0x0017 66MGMT_OP_SET_IO_CAPABILITY = 0x0018 67MGMT_OP_PAIR_DEVICE = 0x0019 68MGMT_OP_CANCEL_PAIR_DEVICE = 0x001A 69MGMT_OP_UNPAIR_DEVICE = 0x001B 70MGMT_OP_USER_CONFIRM_REPLY = 0x001C 71MGMT_OP_USER_CONFIRM_NEG_REPLY = 0x001D 72MGMT_OP_USER_PASSKEY_REPLY = 0x001E 73MGMT_OP_USER_PASSKEY_NEG_REPLY = 0x001F 74MGMT_OP_READ_LOCAL_OOB_DATA = 0x0020 75MGMT_OP_ADD_REMOTE_OOB_DATA = 0x0021 76MGMT_OP_REMOVE_REMOTE_OOB_DATA = 0x0022 77MGMT_OP_START_DISCOVERY = 0x0023 78MGMT_OP_STOP_DISCOVERY = 0x0024 79MGMT_OP_CONFIRM_NAME = 0x0025 80MGMT_OP_BLOCK_DEVICE = 0x0026 81MGMT_OP_UNBLOCK_DEVICE = 0x0027 82MGMT_OP_SET_DEVICE_ID = 0x0028 83MGMT_OP_SET_ADVERTISING = 0x0029 84MGMT_OP_SET_BREDR = 0x002A 85MGMT_OP_SET_STATIC_ADDRESS = 0x002B 86MGMT_OP_SET_SCAN_PARAMS = 0x002C 87MGMT_OP_SET_SECURE_CONN = 0x002D 88MGMT_OP_SET_DEBUG_KEYS = 0x002E 89MGMT_OP_SET_PRIVACY = 0x002F 90MGMT_OP_LOAD_IRKS = 0x0030 91MGMT_OP_GET_CONN_INFO = 0x0031 92MGMT_OP_GET_CLOCK_INFO = 0x0032 93MGMT_OP_ADD_DEVICE = 0x0033 94MGMT_OP_REMOVE_DEVICE = 0x0034 95MGMT_OP_LOAD_CONN_PARAM = 0x0035 96MGMT_OP_READ_UNCONF_INDEX_LIST = 0x0036 97MGMT_OP_READ_CONFIG_INFO = 0x0037 98MGMT_OP_SET_EXTERNAL_CONFIG = 0x0038 99MGMT_OP_SET_PUBLIC_ADDRESS = 0x0039 100 101MGMT_EV_CMD_COMPLETE = 0x0001 102MGMT_EV_CMD_STATUS = 0x0002 103MGMT_EV_CONTROLLER_ERROR = 0x0003 104MGMT_EV_INDEX_ADDED = 0x0004 105MGMT_EV_INDEX_REMOVED = 0x0005 106MGMT_EV_NEW_SETTINGS = 0x0006 107MGMT_EV_CLASS_OF_DEV_CHANGED = 0x0007 108MGMT_EV_LOCAL_NAME_CHANGED = 0x0008 109MGMT_EV_NEW_LINK_KEY = 0x0009 110MGMT_EV_NEW_LONG_TERM_KEY = 0x000A 111MGMT_EV_DEVICE_CONNECTED = 0x000B 112MGMT_EV_DEVICE_DISCONNECTED = 0x000C 113MGMT_EV_CONNECT_FAILED = 0x000D 114MGMT_EV_PIN_CODE_REQUEST = 0x000E 115MGMT_EV_USER_CONFIRM_REQUEST = 0x000F 116MGMT_EV_USER_PASSKEY_REQUEST = 0x0010 117MGMT_EV_AUTH_FAILED = 0x0011 118MGMT_EV_DEVICE_FOUND = 0x0012 119MGMT_EV_DISCOVERING = 0x0013 120MGMT_EV_DEVICE_BLOCKED = 0x0014 121MGMT_EV_DEVICE_UNBLOCKED = 0x0015 122MGMT_EV_DEVICE_UNPAIRED = 0x0016 123MGMT_EV_PASSKEY_NOTIFY = 0x0017 124MGMT_EV_NEW_IRK = 0x0018 125MGMT_EV_NEW_CSRK = 0x0019 126MGMT_EV_DEVICE_ADDED = 0x001a 127MGMT_EV_DEVICE_REMOVED = 0x001b 128MGMT_EV_NEW_CONN_PARAM = 0x001c 129MGMT_EV_UNCONF_INDEX_ADDED = 0x001d 130MGMT_EV_UNCONF_INDEX_REMOVED = 0x001e 131MGMT_EV_NEW_CONFIG_OPTIONS = 0x001f 132 133# Settings returned by MGMT_OP_READ_INFO 134MGMT_SETTING_POWERED = 0x00000001 135MGMT_SETTING_CONNECTABLE = 0x00000002 136MGMT_SETTING_FAST_CONNECTABLE = 0x00000004 137MGMT_SETTING_DISCOVERABLE = 0x00000008 138MGMT_SETTING_PAIRABLE = 0x00000010 139MGMT_SETTING_LINK_SECURITY = 0x00000020 140MGMT_SETTING_SSP = 0x00000040 141MGMT_SETTING_BREDR = 0x00000080 142MGMT_SETTING_HS = 0x00000100 143MGMT_SETTING_LE = 0x00000200 144MGMT_SETTING_ADVERTISING = 0x00000400 145MGMT_SETTING_SECURE_CONNECTIONS = 0x00000800 146MGMT_SETTING_DEBUG_KEYS = 0x00001000 147MGMT_SETTING_PRIVACY = 0x00002000 148MGMT_SETTING_CONTROLLER_CONFIG = 0x00004000 149 150# Options returned by MGMT_OP_READ_CONFIG_INFO 151MGMT_OPTION_EXTERNAL_CONFIG = 0x00000001 152MGMT_OPTION_PUBLIC_ADDRESS = 0x00000002 153 154# Disconnect reason returned in MGMT_EV_DEVICE_DISCONNECTED 155MGMT_DEV_DISCONN_UNKNOWN = 0x00 156MGMT_DEV_DISCONN_TIMEOUT = 0x01 157MGMT_DEV_DISCONN_LOCAL_HOST = 0x02 158MGMT_DEV_DISCONN_REMOTE = 0x03 159 160# Flags returned in MGMT_EV_DEVICE_FOUND 161MGMT_DEV_FOUND_CONFIRM_NAME = 0x01 162MGMT_DEV_FOUND_LEGACY_PAIRING = 0x02 163 164 165# EIR Data field types 166EIR_FLAGS = 0x01 167EIR_UUID16_SOME = 0x02 168EIR_UUID16_ALL = 0x03 169EIR_UUID32_SOME = 0x04 170EIR_UUID32_ALL = 0x05 171EIR_UUID128_SOME = 0x06 172EIR_UUID128_ALL = 0x07 173EIR_NAME_SHORT = 0x08 174EIR_NAME_COMPLETE = 0x09 175EIR_TX_POWER = 0x0A 176EIR_CLASS_OF_DEV = 0x0D 177EIR_SSP_HASH = 0x0E 178EIR_SSP_RANDOMIZER = 0x0F 179EIR_DEVICE_ID = 0x10 180EIR_GAP_APPEARANCE = 0x19 181 182 183# Derived from lib/hci.h 184HCIGETDEVLIST = 0x800448d2 185HCIGETDEVINFO = 0x800448d3 186 187HCI_UP = 1 << 0 188HCI_INIT = 1 << 1 189HCI_RUNNING = 1 << 2 190HCI_PSCAN = 1 << 3 191HCI_ISCAN = 1 << 4 192HCI_AUTH = 1 << 5 193HCI_ENCRYPT = 1 << 6 194HCI_INQUIRY = 1 << 7 195HCI_RAW = 1 << 8 196 197 198def parse_eir(eirdata): 199 """Parse Bluetooth Extended Inquiry Result (EIR) data structuree. 200 201 @param eirdata: Encoded eir data structure. 202 203 @return Dictionary equivalent to the expanded structure keyed by EIR_* 204 fields, with any data members parsed to useful formats. 205 206 """ 207 fields = {} 208 pos = 0 209 while pos < len(eirdata): 210 # Byte at the current position is the field length, which should be 211 # zero at the end of the structure. 212 (field_len, ) = struct.unpack('B', memoryview(eirdata)[pos:pos + 1]) 213 if field_len == 0: 214 break 215 # Next byte is the field type, and the rest of the field is the data. 216 # Note that the length field doesn't include itself so that's why the 217 # offsets and lengths look a little odd. 218 (field_type, ) = struct.unpack('B', 219 memoryview(eirdata)[pos + 1:pos + 2]) 220 data = eirdata[pos+2:pos+field_len+1] 221 pos += field_len + 1 222 # Parse the individual fields to make the data meaningful. 223 if field_type == EIR_NAME_SHORT or field_type == EIR_NAME_COMPLETE: 224 data = data.rstrip('\0') 225 # Place in the dictionary keyed by type. 226 fields[field_type] = data 227 228 return fields 229 230 231 232class BluetoothSocketError(Exception): 233 """Error raised for general issues with BluetoothSocket.""" 234 pass 235 236class BluetoothInvalidPacketError(Exception): 237 """Error raised when an invalid packet is received from the socket.""" 238 pass 239 240class BluetoothControllerError(Exception): 241 """Error raised when the Controller Error event is received.""" 242 pass 243 244 245class BluetoothSocket(btsocket.socket): 246 """Bluetooth Socket. 247 248 BluetoothSocket wraps the btsocket.socket() class, and thus the system 249 socket.socket() class, to implement the necessary send and receive methods 250 for the HCI Control and Monitor protocols (aka mgmt_ops) of the 251 Linux Kernel. 252 253 Instantiate either BluetoothControlSocket or BluetoothRawSocket rather 254 than this class directly. 255 256 See bluez/doc/mgmt_api.txt for details. 257 258 """ 259 260 def __init__(self): 261 super(BluetoothSocket, self).__init__(family=btsocket.AF_BLUETOOTH, 262 type=socket.SOCK_RAW, 263 proto=btsocket.BTPROTO_HCI) 264 self.events = [] 265 266 267 def send_command(self, code, index, data=b''): 268 """Send a command to the socket. 269 270 To send a command, wait for the reply event, and parse it use 271 send_command_and_wait() instead. 272 273 @param code: Command Code. 274 @param index: Controller index, may be MGMT_INDEX_NONE. 275 @param data: Parameters as bytearray or str (optional). 276 277 """ 278 # Send the command to the kernel 279 msg = struct.pack('<HHH', code, index, len(data)) + data 280 281 length = self.send(msg) 282 if length != len(msg): 283 raise BluetoothSocketError('Short write on socket') 284 285 286 def recv_event(self): 287 """Receive a single event from the socket. 288 289 The event data is not parsed; in the case of command complete events 290 this means it includes both the data for the event and the response 291 for the command. 292 293 Use settimeout() to set whether this method will block if there is no 294 data, return immediately or wait for a specific length of time before 295 timing out and raising TimeoutError. 296 297 @return tuple of (event, index, data) 298 299 """ 300 # Read the message from the socket 301 hdr = bytearray(MGMT_HDR_SIZE) 302 data = bytearray(512) 303 try: 304 (nbytes, ancdata, msg_flags, address) = self.recvmsg_into( 305 (hdr, data)) 306 except btsocket.timeout as e: 307 raise BluetoothSocketError('Error receiving event: %s' % e) 308 if nbytes < MGMT_HDR_SIZE: 309 raise BluetoothInvalidPacketError('Packet shorter than header') 310 311 # Parse the header 312 (event, index, length) = struct.unpack_from('<HHH', memoryview(hdr)) 313 if nbytes < MGMT_HDR_SIZE + length: 314 raise BluetoothInvalidPacketError('Packet shorter than length') 315 316 return (event, index, data[:length]) 317 318 319 def send_command_and_wait(self, 320 cmd_code, 321 cmd_index, 322 cmd_data=b'', 323 expected_length=None): 324 """Send a command to the socket and wait for the reply. 325 326 Additional events are appended to the events list of the socket object. 327 328 @param cmd_code: Command Code. 329 @param cmd_index: Controller index, may be btsocket.HCI_DEV_NONE. 330 @param cmd_data: Parameters as bytearray or str. 331 @param expected_length: May be set to verify the length of the data. 332 333 Use settimeout() to set whether this method will block if there is no 334 reply, return immediately or wait for a specific length of time before 335 timing out and raising TimeoutError. 336 337 @return tuple of (status, data) 338 339 """ 340 self.send_command(cmd_code, cmd_index, cmd_data) 341 342 while True: 343 (event, index, data) = self.recv_event() 344 345 if event == MGMT_EV_CMD_COMPLETE: 346 if index != cmd_index: 347 raise BluetoothInvalidPacketError( 348 ('Response for wrong controller index received: ' + 349 '0x%04d (expected 0x%04d)' % (index, cmd_index))) 350 if len(data) < 3: 351 raise BluetoothInvalidPacketError( 352 ('Incorrect command complete event data length: ' + 353 '%d (expected at least 3)' % len(data))) 354 355 (code, status) = struct.unpack_from('<HB', 356 memoryview(data)[0:3]) 357 logging.debug('[0x%04x] command 0x%04x complete: 0x%02x', 358 index, code, status) 359 360 if code != cmd_code: 361 raise BluetoothInvalidPacketError( 362 ('Response for wrong command code received: ' + 363 '0x%04d (expected 0x%04d)' % (code, cmd_code))) 364 365 response_length = len(data) - 3 366 if (expected_length is not None and 367 response_length != expected_length): 368 raise BluetoothInvalidPacketError( 369 ('Incorrect length of data for response: ' + 370 '%d (expected %d)' % (response_length, 371 expected_length))) 372 373 return (status, data[3:]) 374 375 elif event == MGMT_EV_CMD_STATUS: 376 if index != cmd_index: 377 raise BluetoothInvalidPacketError( 378 ('Response for wrong controller index received: ' + 379 '0x%04d (expected 0x%04d)' % (index, cmd_index))) 380 if len(data) != 3: 381 raise BluetoothInvalidPacketError( 382 ('Incorrect command status event data length: ' + 383 '%d (expected 3)' % len(data))) 384 385 (code, status) = struct.unpack_from('<HB', 386 memoryview(data)[0:3]) 387 logging.debug('[0x%04x] command 0x%02x status: 0x%02x', 388 index, code, status) 389 390 if code != cmd_code: 391 raise BluetoothInvalidPacketError( 392 ('Response for wrong command code received: ' + 393 '0x%04d (expected 0x%04d)' % (code, cmd_code))) 394 395 return (status, None) 396 397 elif event == MGMT_EV_CONTROLLER_ERROR: 398 if len(data) != 1: 399 raise BluetoothInvalidPacketError( 400 ('Incorrect controller error event data length: ' + 401 '%d (expected 1)' % len(data))) 402 403 (error_code) = struct.unpack_from('<B', memoryview(data)[0:1]) 404 405 raise BluetoothControllerError('Controller error: %d' % 406 error_code) 407 408 else: 409 logging.debug('[0x%04x] event 0x%02x length: %d', 410 index, event, len(data)) 411 self.events.append((event, index, data)) 412 413 414 def wait_for_events(self, index, events): 415 """Wait for and return the first of a set of events specified. 416 417 @param index: Controller index of event, may be btsocket.HCI_DEV_NONE. 418 @param events: List of event codes to wait for. 419 420 Use settimeout() to set whether this method will block if there is no 421 event received, return immediately or wait for a specific length of 422 time before timing out and raising TimeoutError. 423 424 @return Tuple of (event, data) 425 426 """ 427 while True: 428 for idx, (event, event_index, data) in enumerate(self.events): 429 if event_index == index and event in events: 430 self.events.pop(idx) 431 return (event, data) 432 433 (event, event_index, data) = self.recv_event() 434 if event_index == index and event in events: 435 return (event, data) 436 elif event == MGMT_EV_CMD_COMPLETE: 437 if len(data) < 3: 438 raise BluetoothInvalidPacketError( 439 ('Incorrect command complete event data length: ' + 440 '%d (expected at least 3)' % len(data))) 441 442 (code, status) = struct.unpack_from('<HB', 443 memoryview(data)[0:3]) 444 logging.debug('[0x%04x] command 0x%04x complete: 0x%02x ' 445 '(Ignored)', index, code, status) 446 447 elif event == MGMT_EV_CMD_STATUS: 448 if len(data) != 3: 449 raise BluetoothInvalidPacketError( 450 ('Incorrect command status event data length: ' + 451 '%d (expected 3)' % len(data))) 452 453 (code, status) = struct.unpack_from('<HB', 454 memoryview(data)[0:3]) 455 logging.debug('[0x%04x] command 0x%02x status: 0x%02x ' 456 '(Ignored)', index, code, status) 457 458 elif event == MGMT_EV_CONTROLLER_ERROR: 459 if len(data) != 1: 460 raise BluetoothInvalidPacketError( 461 ('Incorrect controller error event data length: ' + 462 '%d (expected 1)' % len(data))) 463 464 (error_code) = struct.unpack_from('<B', memoryview(data)[0:1]) 465 logging.debug('[0x%04x] controller error: %d (Ignored)', 466 index, error_code) 467 468 else: 469 self.events.append((event, index, data)) 470 471 472class BluetoothControlSocket(BluetoothSocket): 473 """Bluetooth Control Socket. 474 475 BluetoothControlSocket provides convenient methods mapping to each mgmt_ops 476 command that send an appropriately formatted command and parse the response. 477 478 """ 479 480 DEFAULT_TIMEOUT = 15 481 482 def __init__(self): 483 super(BluetoothControlSocket, self).__init__() 484 self.bind((btsocket.HCI_DEV_NONE, btsocket.HCI_CHANNEL_CONTROL)) 485 self.settimeout(self.DEFAULT_TIMEOUT) 486 487 # Certain features will depend on the management version and revision, 488 # so check those now. 489 (version, revision) = self.read_version() 490 logging.debug('MGMT API %d.%d', version, revision) 491 self._kernel_confirms_name = ( 492 (version > 1) or ((version == 1) and (revision >= 5))) 493 494 def read_version(self): 495 """Read the version of the management interface. 496 497 @return tuple (version, revision) on success, None on failure. 498 499 """ 500 (status, data) = self.send_command_and_wait( 501 MGMT_OP_READ_VERSION, 502 MGMT_INDEX_NONE, 503 expected_length=3) 504 if status != MGMT_STATUS_SUCCESS: 505 return None 506 507 (version, revision) = struct.unpack_from('<BH', memoryview(data)) 508 return (version, revision) 509 510 511 def read_supported_commands(self): 512 """Read the supported management commands and events. 513 514 @return tuple (commands, events) on success, None on failure. 515 516 """ 517 (status, data) = self.send_command_and_wait( 518 MGMT_OP_READ_COMMANDS, 519 MGMT_INDEX_NONE) 520 if status != MGMT_STATUS_SUCCESS: 521 return None 522 if len(data) < 4: 523 raise BluetoothInvalidPacketError( 524 ('Incorrect length of data for response: ' + 525 '%d (expected at least 4)' % len(data))) 526 527 (ncommands, nevents) = struct.unpack_from('<HH', memoryview(data)[0:4]) 528 offset = 4 529 expected_length = offset + (ncommands * 2) + (nevents * 2) 530 if len(data) != expected_length: 531 raise BluetoothInvalidPacketError( 532 ('Incorrect length of data for response: ' + 533 '%d (expected %d)' % (len(data), expected_length))) 534 535 commands = [] 536 while len(commands) < ncommands: 537 commands.extend( 538 struct.unpack_from('<H', 539 memoryview(data)[offset:offset + 2])) 540 offset += 2 541 542 events = [] 543 while len(events) < nevents: 544 events.extend( 545 struct.unpack_from('<H', 546 memoryview(data)[offset:offset + 2])) 547 offset += 2 548 549 return (commands, events) 550 551 552 def read_index_list(self): 553 """Read the list of currently known controllers. 554 555 @return array of controller indexes on success, None on failure. 556 557 """ 558 (status, data) = self.send_command_and_wait( 559 MGMT_OP_READ_INDEX_LIST, 560 MGMT_INDEX_NONE) 561 if status != MGMT_STATUS_SUCCESS: 562 return None 563 if len(data) < 2: 564 raise BluetoothInvalidPacketError( 565 ('Incorrect length of data for response: ' + 566 '%d (expected at least 2)' % len(data))) 567 568 (nindexes, ) = struct.unpack_from('<H', memoryview(data)[0:2]) 569 offset = 2 570 expected_length = offset + (nindexes * 2) 571 if len(data) != expected_length: 572 raise BluetoothInvalidPacketError( 573 ('Incorrect length of data for response: ' + 574 '%d (expected %d)' % (len(data), expected_length))) 575 576 indexes = [] 577 while len(indexes) < nindexes: 578 indexes.extend( 579 struct.unpack_from('<H', 580 memoryview(data)[offset:offset + 2])) 581 offset += 2 582 583 return indexes 584 585 586 def read_info(self, index): 587 """Read the state and basic information of a controller. 588 589 Address is returned as a string in upper-case hex to match the 590 BlueZ property. 591 592 @param index: Controller index. 593 594 @return tuple (address, bluetooth_version, manufacturer, 595 supported_settings, current_settings, 596 class_of_device, name, short_name) on success, 597 None on failure. 598 599 """ 600 (status, data) = self.send_command_and_wait( 601 MGMT_OP_READ_INFO, 602 index, 603 expected_length=280) 604 if status != MGMT_STATUS_SUCCESS: 605 return None 606 607 (address, bluetooth_version, manufacturer, supported_settings, 608 current_settings, class_of_device_lo, class_of_device_mid, 609 class_of_device_hi, name, 610 short_name) = struct.unpack_from('<6sBHLL3B249s11s', memoryview(data)) 611 612 return (':'.join('%02X' % x 613 for x in reversed(struct.unpack('6B', address))), 614 bluetooth_version, manufacturer, supported_settings, 615 current_settings, 616 (class_of_device_lo | 617 (class_of_device_mid << 8) | (class_of_device_hi << 16)), 618 six.ensure_text(name).rstrip('\0'), 619 six.ensure_text(short_name).rstrip('\0')) 620 621 622 def set_powered(self, index, powered): 623 """Set the powered state of a controller. 624 625 @param index: Controller index. 626 @param powered: Whether controller radio should be powered. 627 628 @return New controller settings on success, None on failure. 629 630 """ 631 msg_data = struct.pack('<B', bool(powered)) 632 (status, data) = self.send_command_and_wait( 633 MGMT_OP_SET_POWERED, 634 index, 635 msg_data, 636 expected_length=4) 637 if status != MGMT_STATUS_SUCCESS: 638 return None 639 640 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 641 return current_settings 642 643 644 def set_discoverable(self, index, discoverable, timeout=0): 645 """Set the discoverable state of a controller. 646 647 @param index: Controller index. 648 @param discoverable: Whether controller should be discoverable. 649 @param timeout: Timeout in seconds before disabling discovery again, 650 ignored when discoverable is False, must not be zero when 651 discoverable is True. 652 653 @return New controller settings on success, 0 if the feature is not 654 supported and the parameter was False, None otherwise. 655 656 """ 657 msg_data = struct.pack('<BH', bool(discoverable), timeout) 658 (status, data) = self.send_command_and_wait( 659 MGMT_OP_SET_DISCOVERABLE, 660 index, 661 msg_data, 662 expected_length=4) 663 if status == MGMT_STATUS_NOT_SUPPORTED and not discoverable: 664 return 0 665 elif status != MGMT_STATUS_SUCCESS: 666 return None 667 668 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 669 return current_settings 670 671 672 def set_connectable(self, index, connectable): 673 """Set the connectable state of a controller. 674 675 @param index: Controller index. 676 @param connectable: Whether controller should be connectable. 677 678 @return New controller settings on success, 0 if the feature is not 679 supported and the parameter was False, None otherwise. 680 681 """ 682 msg_data = struct.pack('<B', bool(connectable)) 683 (status, data) = self.send_command_and_wait( 684 MGMT_OP_SET_CONNECTABLE, 685 index, 686 msg_data, 687 expected_length=4) 688 if status == MGMT_STATUS_NOT_SUPPORTED and not connectable: 689 return 0 690 elif status != MGMT_STATUS_SUCCESS: 691 return None 692 693 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 694 return current_settings 695 696 697 def set_fast_connectable(self, index, connectable): 698 """Set the fast connectable state of a controller. 699 700 Fast Connectable is a state where page scan parameters are set to favor 701 faster connect times at the expense of higher power consumption. 702 703 Unlike most other set_* commands, this may only be used when the 704 controller is powered. 705 706 @param index: Controller index. 707 @param connectable: Whether controller should be fast connectable. 708 709 @return New controller settings on success, 0 if the feature is not 710 supported and the parameter was False or the controller is 711 powered down, None otherwise. 712 713 """ 714 msg_data = struct.pack('<B', bool(connectable)) 715 (status, data) = self.send_command_and_wait( 716 MGMT_OP_SET_FAST_CONNECTABLE, 717 index, 718 msg_data) 719 if status == MGMT_STATUS_NOT_SUPPORTED and not connectable: 720 return 0 721 elif status != MGMT_STATUS_SUCCESS: 722 return None 723 # This is documented as returning current settings, but doesn't in 724 # our kernel version (probably a bug), so if no data is returned, 725 # pretend that was success. 726 if len(data) == 0: 727 return 0 728 elif len(data) != 4: 729 raise BluetoothInvalidPacketError( 730 ('Incorrect length of data for response: ' + 731 '%d (expected 4)' % len(data))) 732 733 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 734 return current_settings 735 736 737 def set_pairable(self, index, pairable): 738 """Set the pairable state of a controller. 739 740 @param index: Controller index. 741 @param pairable: Whether controller should be pairable. 742 743 @return New controller settings on success, 0 if the feature is not 744 supported and the parameter was False, None otherwise. 745 746 """ 747 msg_data = struct.pack('<B', bool(pairable)) 748 (status, data) = self.send_command_and_wait( 749 MGMT_OP_SET_PAIRABLE, 750 index, 751 msg_data, 752 expected_length=4) 753 if status != MGMT_STATUS_SUCCESS: 754 return None 755 756 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 757 return current_settings 758 759 760 def set_link_security(self, index, link_security): 761 """Set the link security state of a controller. 762 763 Toggles the use of link level security (aka Security Mode 3) for a 764 controller. 765 766 @param index: Controller index. 767 @param link_security: Whether controller should be link_security. 768 769 @return New controller settings on success, 0 if the feature is not 770 supported and the parameter was False, None otherwise. 771 772 """ 773 msg_data = struct.pack('<B', bool(link_security)) 774 (status, data) = self.send_command_and_wait( 775 MGMT_OP_SET_LINK_SECURITY, 776 index, 777 msg_data, 778 expected_length=4) 779 if status == MGMT_STATUS_NOT_SUPPORTED and not link_security: 780 return 0 781 elif status != MGMT_STATUS_SUCCESS: 782 return None 783 784 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 785 return current_settings 786 787 788 def set_ssp(self, index, ssp): 789 """Set the whether a controller supports Simple Secure Pairing. 790 791 @param index: Controller index. 792 @param ssp: Whether controller should support SSP. 793 794 @return New controller settings on success, 0 if the feature is not 795 supported and the parameter was False, None otherwise. 796 797 """ 798 msg_data = struct.pack('<B', bool(ssp)) 799 (status, data) = self.send_command_and_wait( 800 MGMT_OP_SET_SSP, 801 index, 802 msg_data, 803 expected_length=4) 804 if status == MGMT_STATUS_NOT_SUPPORTED and not ssp: 805 return 0 806 elif status != MGMT_STATUS_SUCCESS: 807 return None 808 809 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 810 return current_settings 811 812 813 def set_hs(self, index, hs): 814 """Set the whether a controller supports Bluetooth High Speed. 815 816 @param index: Controller index. 817 @param hs: Whether controller should support High Speed. 818 819 @return New controller settings on success, 0 if the feature is not 820 supported and the parameter was False, None otherwise. 821 822 """ 823 msg_data = struct.pack('<B', bool(hs)) 824 (status, data) = self.send_command_and_wait( 825 MGMT_OP_SET_HS, 826 index, 827 msg_data, 828 expected_length=4) 829 if status == MGMT_STATUS_NOT_SUPPORTED and not hs: 830 return 0 831 elif status != MGMT_STATUS_SUCCESS: 832 return None 833 834 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 835 return current_settings 836 837 838 def set_le(self, index, le): 839 """Set the whether a controller supports Bluetooth Low Energy. 840 841 @param index: Controller index. 842 @param le: Whether controller should support Low Energy. 843 844 @return New controller settings on success, 0 if the feature is not 845 supported and the parameter was False, None otherwise. 846 847 """ 848 msg_data = struct.pack('<B', bool(le)) 849 (status, data) = self.send_command_and_wait( 850 MGMT_OP_SET_LE, 851 index, 852 msg_data, 853 expected_length=4) 854 if status == MGMT_STATUS_NOT_SUPPORTED and not le: 855 return 0 856 elif status != MGMT_STATUS_SUCCESS: 857 return None 858 859 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 860 return current_settings 861 862 863 def set_device_class(self, index, major, minor): 864 """Set the device class of the controller. 865 866 Consult the Bluetooth Baseband Assigned Numbers specification for valid 867 values, in general both values are bit fields defined by that 868 specification. 869 870 If the device class is set while the controller is powered off, 0 will 871 be returned, but the new class will be set by the host subsystem after 872 the controller is powered on. 873 874 @param index: Controller index. 875 @param major: Major device class. 876 @param minor: Minor device class. 877 878 @return New three-octet device class on success, None on failure. 879 880 """ 881 msg_data = struct.pack('<BB', major, minor) 882 (status, data) = self.send_command_and_wait( 883 MGMT_OP_SET_DEV_CLASS, 884 index, 885 msg_data, 886 expected_length=3) 887 if status != MGMT_STATUS_SUCCESS: 888 return None 889 890 (class_of_device_lo, class_of_device_mid, 891 class_of_device_hi) = struct.unpack_from('<3B', memoryview(data)) 892 return (class_of_device_lo |(class_of_device_mid << 8) | 893 (class_of_device_hi << 16)) 894 895 896 def set_local_name(self, index, name, short_name): 897 """Set the local name of the controller. 898 899 @param index: Controller index. 900 @param name: Full length name, up to 248 characters. 901 @param short_name: Short name, up to 10 characters. 902 903 @return Tuple of (name, short_name) on success, None on failure. 904 905 """ 906 # Truncate the provided parameters and then zero-pad using struct 907 # so we pass a fixed-length null-terminated string to the kernel. 908 msg_data = struct.pack('<249s11s', six.ensure_binary(name[:248]), 909 six.ensure_binary(short_name[:10])) 910 (status, data) = self.send_command_and_wait( 911 MGMT_OP_SET_LOCAL_NAME, 912 index, 913 msg_data, 914 expected_length=260) 915 if status != MGMT_STATUS_SUCCESS: 916 return None 917 918 (name, short_name) = struct.unpack_from('<249s11s', memoryview(data)) 919 return (six.ensure_text(name).rstrip('\0'), 920 six.ensure_text(short_name).rstrip('\0')) 921 922 923 def start_discovery(self, index, address_type): 924 """Start discovering remote devices. 925 926 Call get_discovered_devices() to retrieve the list of devices found. 927 928 @param index: Controller index. 929 @param address_type: Address types to discover. 930 931 @return Address types discovery was started for on success, 932 None on failure. 933 934 """ 935 msg_data = struct.pack('<B', address_type) 936 (status, data) = self.send_command_and_wait( 937 MGMT_OP_START_DISCOVERY, 938 index, 939 msg_data, 940 expected_length=1) 941 if status != MGMT_STATUS_SUCCESS: 942 return None 943 944 (address_type, ) = struct.unpack_from('<B', memoryview(data)) 945 return address_type 946 947 948 def stop_discovery(self, index, address_type): 949 """Stop discovering remote devices. 950 951 There is usually no need to call this method explicitly as discovery 952 is automatically stopped once it has iterated through the necessary 953 channels. 954 955 @param index: Controller index. 956 @param address_type: Address types to stop discovering. 957 958 @return Address types discovery was stopped for on success, 959 None on failure. 960 961 """ 962 msg_data = struct.pack('<B', address_type) 963 (status, data) = self.send_command_and_wait( 964 MGMT_OP_STOP_DISCOVERY, 965 index, 966 msg_data, 967 expected_length=1) 968 if status != MGMT_STATUS_SUCCESS: 969 return None 970 971 (address_type, ) = struct.unpack_from('<B', memoryview(data)) 972 return address_type 973 974 975 def get_discovered_devices(self, index): 976 """Return list of discovered remote devices. 977 978 This method may be called any time after start_discovery() and will 979 wait until the full list of devices has been returned, there is usually 980 no need to call stop_discovery() explicitly. 981 982 Use settimeout() to set whether this method will block if there are no 983 events, return immediately or wait for a specific length of time before 984 timing out and raising TimeoutError. 985 986 @param index: Controller index. 987 988 @return List of devices found as tuples with the format 989 (address, address_type, rssi, flags, eirdata) 990 991 """ 992 devices = [] 993 discovering = True 994 while discovering: 995 (event, data) = self.wait_for_events( 996 index, 997 ( MGMT_EV_DISCOVERING, MGMT_EV_DEVICE_FOUND )) 998 999 if event == MGMT_EV_DISCOVERING: 1000 if len(data) != 2: 1001 raise BluetoothInvalidPacketError( 1002 ('Incorrect discovering event data length: ' + 1003 '%d (expected 2)' % len(data))) 1004 1005 (address_type, 1006 discovering) = struct.unpack_from('<BB', memoryview(data)) 1007 1008 elif event == MGMT_EV_DEVICE_FOUND: 1009 if len(data) < 14: 1010 raise BluetoothInvalidPacketError( 1011 ('Incorrect device found event data length: ' + 1012 '%d (expected at least 14)' % len(data))) 1013 1014 (address, address_type, rssi, flags, 1015 eir_len) = struct.unpack_from('<6sBbLH', 1016 memoryview(data)[0:14]) 1017 1018 if len(data) != 14 + eir_len: 1019 raise BluetoothInvalidPacketError( 1020 ('Incorrect device found event data length: ' + 1021 '%d (expected %d)' % (len(data), 14 + eir_len))) 1022 1023 devices.append(( 1024 ':'.join('%02X' % x 1025 for x in reversed( 1026 struct.unpack('6B', address))), 1027 address_type, 1028 rssi, 1029 flags, 1030 bytes(data[14:]) 1031 )) 1032 1033 # The kernel might want us to confirm whether or not we 1034 # know the name of the device. We don't really care whether 1035 # or not this works, we just have to do it to get the EIR 1036 # Request. 1037 if flags & MGMT_DEV_FOUND_CONFIRM_NAME: 1038 msg_data = struct.pack('<6sBB', 1039 address, address_type, False) 1040 if self._kernel_confirms_name: 1041 self.send_command_and_wait( 1042 MGMT_OP_CONFIRM_NAME, 1043 index, 1044 msg_data) 1045 else: 1046 self.send_command( 1047 MGMT_OP_CONFIRM_NAME, 1048 index, 1049 msg_data) 1050 1051 1052 return devices 1053 1054 1055 def set_advertising(self, index, advertising): 1056 """Set the whether a controller is advertising via LE. 1057 1058 @param index: Controller index. 1059 @param advertising: Whether controller should advertise via LE. 1060 1061 @return New controller settings on success, 0 if the feature is not 1062 supported and the parameter was False, None otherwise. 1063 1064 """ 1065 msg_data = struct.pack('<B', bool(advertising)) 1066 (status, data) = self.send_command_and_wait( 1067 MGMT_OP_SET_ADVERTISING, 1068 index, 1069 msg_data, 1070 expected_length=4) 1071 if status == MGMT_STATUS_NOT_SUPPORTED and not advertising: 1072 return 0 1073 elif status != MGMT_STATUS_SUCCESS: 1074 return None 1075 1076 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 1077 return current_settings 1078 1079 1080 def set_bredr(self, index, bredr): 1081 """Set the whether a controller supports Bluetooth BR/EDR (classic). 1082 1083 @param index: Controller index. 1084 @param bredr: Whether controller should support BR/EDR. 1085 1086 @return New controller settings on success, 0 if the feature is not 1087 supported and the parameter was False, None otherwise. 1088 1089 """ 1090 msg_data = struct.pack('<B', bool(bredr)) 1091 (status, data) = self.send_command_and_wait( 1092 MGMT_OP_SET_BREDR, 1093 index, 1094 msg_data, 1095 expected_length=4) 1096 if status == MGMT_STATUS_NOT_SUPPORTED and not bredr: 1097 return 0 1098 elif status != MGMT_STATUS_SUCCESS: 1099 return None 1100 1101 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 1102 return current_settings 1103 1104 1105 def set_secure_connections(self, index, secure_conn): 1106 """Set whether a controller supports secure connections. 1107 1108 @param index: Controller index. 1109 @param secure_conn: Whether controller should support secure connections 1110 1111 @return New controller settings on success, 0 if the feature is not 1112 supported and the parameter was False, None otherwise. 1113 1114 """ 1115 msg_data = struct.pack('<B', bool(secure_conn)) 1116 (status, data) = self.send_command_and_wait( 1117 MGMT_OP_SET_SECURE_CONN, 1118 index, 1119 msg_data, 1120 expected_length=4) 1121 if status == MGMT_STATUS_NOT_SUPPORTED and not secure_conn: 1122 return 0 1123 elif status != MGMT_STATUS_SUCCESS: 1124 return None 1125 1126 (current_settings, ) = struct.unpack_from('<L', memoryview(data)) 1127 return current_settings 1128 1129 1130 def add_device(self, index, address, address_type, action): 1131 """Add a device to the action list. 1132 1133 @param index: Controller index. 1134 @param address: Address of the device to add. 1135 @param address_type: Type of device in @address. 1136 @param action: Action to take. 1137 1138 @return Tuple of ( address, address_type ) on success, 1139 None on failure. 1140 1141 """ 1142 msg_data = struct.pack('<6sBB', address.encode(), address_type, action) 1143 (status, data) = self.send_command_and_wait( 1144 MGMT_OP_ADD_DEVICE, 1145 index, 1146 msg_data, 1147 expected_length=7) 1148 if status != MGMT_STATUS_SUCCESS: 1149 return None 1150 1151 ( 1152 address, 1153 address_type, 1154 ) = struct.unpack_from('<6sB', memoryview(data)) 1155 return (address.decode(), address_type) 1156 1157 1158 def remove_device(self, index, address, address_type): 1159 """Remove a device from the action list. 1160 1161 @param index: Controller index. 1162 @param address: Address of the device to remove. 1163 @param address_type: Type of device in @address. 1164 1165 @return Tuple of ( address, address_type ) on success, 1166 None on failure. 1167 1168 """ 1169 msg_data = struct.pack('<6sB', address.encode(), address_type) 1170 (status, data) = self.send_command_and_wait( 1171 MGMT_OP_REMOVE_DEVICE, 1172 index, 1173 msg_data, 1174 expected_length=7) 1175 if status != MGMT_STATUS_SUCCESS: 1176 return None 1177 1178 ( 1179 address_b, 1180 address_type, 1181 ) = struct.unpack_from('<6sB', memoryview(data)) 1182 return (address_b.decode(), address_type) 1183 1184 1185class BluetoothRawSocket(BluetoothSocket): 1186 """Bluetooth Raw HCI Socket. 1187 1188 BluetoothRawSocket is a subclass of BluetoothSocket representing raw access 1189 to the HCI controller and providing commands corresponding to ioctls that 1190 can be made on that kind of socket. 1191 1192 """ 1193 1194 def get_dev_info(self, index): 1195 """Read HCI device information. 1196 1197 This method uses the same underlying ioctl as the hciconfig tool. 1198 1199 Address is returned as a string in upper-case hex to match the 1200 BlueZ property. 1201 1202 @param index: Device index. 1203 1204 @return tuple (index, name, address, flags, device_type, bus_type, 1205 features, pkt_type, link_policy, link_mode, 1206 acl_mtu, acl_pkts, sco_mtu, sco_pkts, 1207 err_rx, err_tx, cmd_tx, evt_rx, acl_tx, acl_rx, 1208 sco_tx, sco_rx, byte_rx, byte_tx) on success, 1209 None on failure. 1210 1211 """ 1212 buf = array.array('B', [0] * 96) 1213 fcntl.ioctl(self.fileno(), HCIGETDEVINFO, buf, 1) 1214 1215 (dev_id, name, address, flags, dev_type, features, pkt_type, 1216 link_policy, link_mode, acl_mtu, acl_pkts, sco_mtu, sco_pkts, err_rx, 1217 err_tx, cmd_tx, evt_rx, acl_tx, acl_rx, sco_tx, sco_rx, byte_rx, 1218 byte_tx) = struct.unpack_from('@H8s6sIBQIIIHHHHIIIIIIIIII', 1219 memoryview(buf)) 1220 1221 return (dev_id, name.decode('utf-8').rstrip('\0'), ':'.join( 1222 '%02X' % x for x in reversed(struct.unpack('6B', address))), 1223 flags, (dev_type & 0x30) >> 4, dev_type & 0x0f, features, 1224 pkt_type, link_policy, link_mode, acl_mtu, acl_pkts, sco_mtu, 1225 sco_pkts, err_rx, err_tx, cmd_tx, evt_rx, acl_tx, acl_rx, 1226 sco_tx, sco_rx, byte_rx, byte_tx) 1227