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