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