• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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