def write_inquiry_mode(sock, mode):
    """returns 0 on success, -1 on failure"""
    # save current filter
    old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14)

    # Setup socket filter to receive only events related to the
    # write_inquiry_mode command
    flt = bluez.hci_filter_new()
    opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, 
            bluez.OCF_WRITE_INQUIRY_MODE)
    bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
    bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE);
    bluez.hci_filter_set_opcode(flt, opcode)
    sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt )

    # send the command!
    bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, 
            bluez.OCF_WRITE_INQUIRY_MODE, struct.pack("B", mode) )

    pkt = sock.recv(255)

    status = struct.unpack("xxxxxxB", pkt)[0]

    # restore old filter
    sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter )
    if status != 0: return -1
    return 0
def read_inquiry_scan_activity(sock):
    """returns the current inquiry scan interval and window, 
    or -1 on failure"""
    # save current filter
    old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14)

    # Setup socket filter to receive only events related to the
    # read_inquiry_mode command
    flt = bluez.hci_filter_new()
    opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, 
            bluez.OCF_READ_INQ_ACTIVITY)
    bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
    bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE);
    bluez.hci_filter_set_opcode(flt, opcode)
    sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt )

    # first read the current inquiry mode.
    bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, 
            bluez.OCF_READ_INQ_ACTIVITY )

    pkt = sock.recv(255)

    status,interval,window = struct.unpack("!xxxxxxBHH", pkt)
    interval = bluez.btohs(interval)
    interval = (interval >> 8) | ( (interval & 0xFF) << 8 )
    window = (window >> 8) | ( (window & 0xFF) << 8 )
    if status != 0: mode = -1

    # restore old filter
    sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter )
    return interval, window
def read_inquiry_mode(sock):
    """returns the current mode, or -1 on failure"""
    # save current filter
    old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14)

    # Setup socket filter to receive only events related to the
    # read_inquiry_mode command
    flt = bluez.hci_filter_new()
    opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, 
            bluez.OCF_READ_INQUIRY_MODE)
    bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
    bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE);
    bluez.hci_filter_set_opcode(flt, opcode)
    sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt )

    # first read the current inquiry mode.
    bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, 
            bluez.OCF_READ_INQUIRY_MODE )

    pkt = sock.recv(255)

    status,mode = struct.unpack("xxxxxxBB", pkt)
    if status != 0: mode = -1

    # restore old filter
    sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter )
    return mode
Пример #4
0
    def _check_command_support(self, octet, mask):
        """
        Checks if a certain command is supported by the Bluetooth sensor.

        @param  octet   The octet of the command.
        @param  mask    The bitmask of the command.
                           Both as defined in the Bluetooth specification v4.0 pp. 447 (pdf 693).
        """
        # save current filter
        old_filter = self.sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14)

        # Setup socket filter to receive only events related to the
        # read_inquiry_mode command
        flt = bluez.hci_filter_new()
        opcode = bluez.cmd_opcode_pack(0x04, 0x0002)
        bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
        bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE);
        bluez.hci_filter_set_opcode(flt, opcode)
        self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt)

        # Send the Read Local Supported Commands command
        bluez.hci_send_cmd(self.sock, 0x04, 0x0002)

        pkt = self.sock.recv(65)

        status = struct.unpack("65B", pkt)
        status = status[6:]

        # restore old filter
        self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter)

        # Check if the requested bit is set.
        if len(status) >= octet+1:
            return status[octet+1] & mask == mask
        return False
    def find_local_bdaddr(self):
        dev_id = 0
        hci_sock = _bt.hci_open_dev(dev_id)

        old_filter = hci_sock.getsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, 14)
        flt = _bt.hci_filter_new()
        opcode = _bt.cmd_opcode_pack(_bt.OGF_INFO_PARAM, _bt.OCF_READ_BD_ADDR)
        _bt.hci_filter_set_ptype(flt, _bt.HCI_EVENT_PKT)
        _bt.hci_filter_set_event(flt, _bt.EVT_CMD_COMPLETE);
        _bt.hci_filter_set_opcode(flt, opcode)
        hci_sock.setsockopt(_bt.SOL_HCI, _bt.HCI_FILTER, flt)

        _bt.hci_send_cmd(hci_sock, _bt.OGF_INFO_PARAM, _bt.OCF_READ_BD_ADDR)

        pkt = hci_sock.recv(255)

        status,raw_bdaddr = struct.unpack("xxxxxxB6s", pkt)
        assert status == 0

        t = [ "%X" % ord(b) for b in raw_bdaddr ]
        t.reverse()
        bdaddr = ":".join(t)

        # restore old filter
        hci_sock.setsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, old_filter )
        return bdaddr
Пример #6
0
    def _write_inquiry_tx_power(self, power):
        """
        Returns 0 on success, error status code or -1 on failure.
        """
        if not self._check_command_support(18, 0b10):
            return -1

        # save current filter
        old_filter = self.sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14)

        # Setup socket filter to receive only events related to the
        # read_inquiry_mode command
        flt = bluez.hci_filter_new()
        opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, 0x0059)
        bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
        bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE);
        bluez.hci_filter_set_opcode(flt, opcode)
        self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt)

        # first read the current inquiry mode.
        bluez.hci_send_cmd(self.sock, bluez.OGF_HOST_CTL,
                0x0059, struct.pack("b", power))

        pkt = self.sock.recv(255)

        status = struct.unpack("xxxxxxB", pkt)[0]

        # restore old filter
        self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter)
        return status
Пример #7
0
def hci_le_set_scan_parameters(sock):
    SCAN_TYPE = 0x01
    INTERVAL = 0x10
    WINDOW = 0x10
    OWN_TYPE = 0x00
    FILTER = 0x00  # all advertisements, not just whitelisted devices

    cmd_pkt = struct.pack("<BBBBBBB", SCAN_TYPE, 0x0, INTERVAL, 0x0, WINDOW, OWN_TYPE, FILTER)

    bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd_pkt)

    old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14)

    filtr = bluez.hci_filter_new()

    bluez.hci_filter_all_events(filtr)
    bluez.hci_filter_set_ptype(filtr, bluez.HCI_EVENT_PKT)
    bluez.hci_filter_set_event(filtr, LE_META_EVENT)
    sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, filtr)
Пример #8
0
  def get_localAdapter(self, deviceNr):
    "Return name and address of a local adapter"
    name = None
    address = None
    sock = bt.hci_open_dev(deviceNr)
    if sock.getsockid() >= 0:
      sock.settimeout(3)
      # Save original filter
      orig_filter = sock.getsockopt(bt.SOL_HCI, bt.HCI_FILTER, 14)
      # Create new filter
      new_filter = orig_filter
      new_filter = bt.hci_filter_new()
      bt.hci_filter_set_ptype(new_filter, bt.HCI_EVENT_PKT)
      bt.hci_filter_set_event(new_filter, bt.EVT_CMD_COMPLETE)
      # CMD Read local name
      opcode = bt.cmd_opcode_pack(bt.OGF_HOST_CTL, bt.OCF_READ_LOCAL_NAME)
      bt.hci_filter_set_opcode(new_filter, opcode)
      sock.setsockopt(bt.SOL_HCI, bt.HCI_FILTER, new_filter)
      bt.hci_send_cmd(sock, bt.OGF_HOST_CTL, bt.OCF_READ_LOCAL_NAME)
      try:
        data = sock.recv(255)
        name = data[7:]
        name = name[:name.find('\0')]
      except bluetooth._bluetooth.timeout:
        print 'bluetooth timeout during local device scan for name'
      # CMD Read local address
      opcode = bt.cmd_opcode_pack(bt.OGF_INFO_PARAM, bt.OCF_READ_BD_ADDR)
      bt.hci_filter_set_opcode(new_filter, opcode)
      sock.setsockopt(bt.SOL_HCI, bt.HCI_FILTER, new_filter)
      bt.hci_send_cmd(sock, bt.OGF_INFO_PARAM, bt.OCF_READ_BD_ADDR)
      try:
        data = sock.recv(255)
        status, raw_bdaddr = struct.unpack('xxxxxxB6s', data)
        address = ['%02X' % ord(b) for b in raw_bdaddr]
        address.reverse()
        address = ':'.join(address)
      except bluetooth._bluetooth.timeout:
        print 'bluetooth timeout during local device scan for address'

      # Restore original filter
      sock.setsockopt(bt.SOL_HCI, bt.HCI_FILTER, orig_filter)
    sock.close()
    return name, address
Пример #9
0
    def read_remote_version_information(self, cmd_params: dict) -> dict:
        '''
        cmd_params -- {
            'Connection_Handle': 0x0000
        }
        '''
        dd = hci_open_dev(self.devid)

        bin_cmd_params = cmd_params['Connection_Handle'].to_bytes(2, 'little')

        flt = hci_filter_new()
        hci_filter_set_ptype(flt, HCI_EVENT_PKT)
        hci_filter_set_event(flt, EVT_READ_REMOTE_VERSION_COMPLETE)
        dd.setsockopt(SOL_HCI, HCI_FILTER, flt)

        hci_send_cmd(dd, OGF_LINK_CTL, OCF_READ_REMOTE_VERSION, bin_cmd_params)

        while True:
            event_params = dd.recv(3 + \
                EVT_READ_REMOTE_VERSION_COMPLETE_SIZE)[3:]
            status, conn_handle, ver, manufacturer_name, subver = \
                struct.unpack('<BHBHH', event_params)
            event_params = {
                'Status': status,
                'Connection_Handle': conn_handle,
                'Version': ver,
                'Manufacturer_Name': manufacturer_name,
                'Subversion': subver
            }

            if event_params['Connection_Handle'] == cmd_params[
                    'Connection_Handle']:
                break

        hci_close_dev(dd.fileno())
        return event_params
Пример #10
0
def read_local_bdaddr():
    hci_sock = _bt.hci_open_dev(0)
    old_filter = hci_sock.getsockopt(_bt.SOL_HCI, _bt.HCI_FILTER, 14)
    flt = _bt.hci_filter_new()
    opcode = _bt.cmd_opcode_pack(_bt.OGF_INFO_PARAM, _bt.OCF_READ_BD_ADDR)
    _bt.hci_filter_set_ptype(flt, _bt.HCI_EVENT_PKT)
    _bt.hci_filter_set_event(flt, _bt.EVT_CMD_COMPLETE)
    _bt.hci_filter_set_opcode(flt, opcode)
    hci_sock.setsockopt(_bt.SOL_HCI, _bt.HCI_FILTER, flt)

    _bt.hci_send_cmd(hci_sock, _bt.OGF_INFO_PARAM, _bt.OCF_READ_BD_ADDR)

    pkt = hci_sock.recv(255)

    status, raw_bdaddr = struct.unpack("xxxxxxB6s", pkt)
    assert status == 0

    t = ["%02X" % ord(b) for b in raw_bdaddr]
    t.reverse()
    bdaddr = ":".join(t)

    # restore old filter
    hci_sock.setsockopt(_bt.SOL_HCI, _bt.HCI_FILTER, old_filter)
    return bdaddr
Пример #11
0
    def read_extended_page_timeout(self):
        dd = hci_open_dev(self.devid)

        flt = hci_filter_new()
        hci_filter_set_ptype(flt, HCI_EVENT_PKT)
        hci_filter_set_event(flt, EVT_CMD_COMPLETE)
        hci_filter_set_opcode(
            flt, cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_EXT_PAGE_TIMEOUT))
        dd.setsockopt(SOL_HCI, HCI_FILTER, flt)

        hci_send_cmd(dd, OGF_HOST_CTL, OCF_READ_EXT_PAGE_TIMEOUT)

        event_params = dd.recv(3 + EVT_CMD_COMPLETE_SIZE + 3)[3:]
        num_hci_cmd_pkts, cmd_opcode, status, \
           ext_page_timeout = struct.unpack('<BHBH', event_params)
        event_params = {
            'Num_HCI_Command_Packets': num_hci_cmd_pkts,
            'Command_Opcode': cmd_opcode,
            'Status': status,
            'Extended_Page_Timeout': ext_page_timeout
        }

        hci_close_dev(dd.fileno())
        return event_params
Пример #12
0
    def read_class_of_device(self) -> dict:
        dd = hci_open_dev(self.devid)

        flt = hci_filter_new()
        hci_filter_set_ptype(flt, HCI_EVENT_PKT)
        hci_filter_set_event(flt, EVT_CMD_COMPLETE)
        hci_filter_set_opcode(
            flt, cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_CLASS_OF_DEV))
        dd.setsockopt(SOL_HCI, HCI_FILTER, flt)

        hci_send_cmd(dd, OGF_HOST_CTL, OCF_READ_CLASS_OF_DEV)

        event_params = dd.recv(3 + HCI_MAX_EVENT_SIZE)[3:]
        num_hci_cmd_pkts, cmd_opcode, status, cod = struct.unpack(
            '<BHB3s', event_params)
        event_params = {
            'Num_HCI_Command_Packets': num_hci_cmd_pkts,
            'Command_Opcode': cmd_opcode,
            'Status': status,
            'Class_Of_Device': cod[::-1]
        }

        hci_close_dev(dd.fileno())
        return event_params
Пример #13
0
    def write_page_timeout(self, cmd_params={'Page_Timeout': 0x2000}) -> dict:
        dd = hci_open_dev(self.devid)

        bin_cmd_params = cmd_params['Page_Timeout'].to_bytes(2, 'little')

        flt = hci_filter_new()
        hci_filter_set_ptype(flt, HCI_EVENT_PKT)
        hci_filter_set_event(flt, EVT_CMD_COMPLETE)
        hci_filter_set_opcode(
            flt, cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT))
        dd.setsockopt(SOL_HCI, HCI_FILTER, flt)

        hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, bin_cmd_params)
        event_params = dd.recv(3 + EVT_CMD_COMPLETE_SIZE + 3)[3:]
        num_hci_cmd_pkts, cmd_opcode, status = struct.unpack(
            '<BHB', event_params)
        event_params = {
            'Num_HCI_Command_Packets': num_hci_cmd_pkts,
            'Command_Opcode': cmd_opcode,
            'Status': status
        }

        hci_close_dev(dd.fileno())
        return event_params
Пример #14
0
    def write_inquiry_mode(self, cmd_params={'Inquiry_Mode': 0x00}) -> dict:
        dd = hci_open_dev(self.devid)

        bin_cmd_params = cmd_params['Inquiry_Mode'].to_bytes(1, 'little')

        flt = hci_filter_new()
        hci_filter_set_ptype(flt, HCI_EVENT_PKT)
        hci_filter_set_event(flt, EVT_CMD_COMPLETE)
        hci_filter_set_opcode(
            flt, cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE))
        dd.setsockopt(SOL_HCI, HCI_FILTER, flt)

        hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE, bin_cmd_params)
        event_params = dd.recv(3 + EVT_CMD_COMPLETE_SIZE + 1)[3:]
        num_hci_cmd_pkts, cmd_opcode, status = struct.unpack(
            '<BHB', event_params)
        event_params = {
            'Num_HCI_Command_Packets': num_hci_cmd_pkts,
            'Command_Opcode': cmd_opcode,
            'Status': status
        }

        hci_close_dev(dd.fileno())
        return event_params
Пример #15
0
    def read_local_name(self) -> dict:
        dd = hci_open_dev(self.devid)

        flt = hci_filter_new()
        hci_filter_set_ptype(flt, HCI_EVENT_PKT)
        hci_filter_set_event(flt, EVT_CMD_COMPLETE)
        hci_filter_set_opcode(
            flt, cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_NAME))
        dd.setsockopt(SOL_HCI, HCI_FILTER, flt)

        hci_send_cmd(dd, OGF_HOST_CTL, OCF_READ_LOCAL_NAME)

        event_params = dd.recv(3 + EVT_CMD_COMPLETE_SIZE + 249)[3:]
        num_hci_cmd_pkts, cmd_opcode, status, local_name = struct.unpack(
            '<BHB248s', event_params)
        event_params = {
            'Num_HCI_Command_Packets': num_hci_cmd_pkts,
            'Command_Opcode': cmd_opcode,
            'Status': status,
            'Local_Name': local_name.decode()
        }

        hci_close_dev(dd.fileno())
        return event_params
Пример #16
0
def parse_le_advertising_events(sock,
                                mac_addr=None,
                                packet_length=None,
                                handler=None,
                                debug=False):
    """
    Parse and report LE advertisements.
    This is a blocking call, an infinite loop is started and the
    given handler will be called each time a new LE advertisement packet
    is detected and corresponds to the given filters.
    .. note:: The :func:`.start_le_advertising` function must be
        called before calling this function.
    :param sock: A bluetooth HCI socket (retrieved using the
        ``hci_open_dev`` PyBluez function).
    :param mac_addr: list of filtered mac address representations
        (uppercase, with ':' separators).
        If not specified, the LE advertisement of any device will be reported.
        Example: mac_addr=('00:2A:5F:FF:25:11', 'DA:FF:12:33:66:12')
    :type mac_addr: ``list`` of ``string``
    :param packet_length: Filter a specific length of LE advertisement packet.
    :type packet_length: ``int``
    :param handler: Handler that will be called each time a LE advertisement
        packet is available (in accordance with the ``mac_addr``
        and ``packet_length`` filters).
    :type handler: ``callable`` taking 4 parameters:
        mac (``str``), adv_type (``int``), data (``bytes``) and rssi (``int``)
    :param debug: Enable debug prints.
    :type debug: ``bool``
    """
    if not debug and handler is None:
        raise ValueError("You must either enable debug or give a handler !")

    old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14)

    flt = bluez.hci_filter_new()
    bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
    # bluez.hci_filter_all_events(flt)
    bluez.hci_filter_set_event(flt, LE_META_EVENT)
    sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt)

    print("socket filter set to ptype=HCI_EVENT_PKT event=LE_META_EVENT")
    print("Listening ...")

    try:
        while True:
            pkt = full_pkt = sock.recv(255)
            ptype, event, plen = struct.unpack("BBB", pkt[:3])

            if event != LE_META_EVENT:
                # Should never occur because we filtered with this type of event
                print("Not a LE_META_EVENT !")
                continue

            sub_event, = struct.unpack("B", pkt[3:4])
            if sub_event != EVT_LE_ADVERTISING_REPORT:
                if debug:
                    print("Not a EVT_LE_ADVERTISING_REPORT !")
                continue

            pkt = pkt[4:]
            adv_type = struct.unpack("b", pkt[1:2])[0]
            mac_addr_str = bluez.ba2str(pkt[3:9])

            if packet_length and plen != packet_length:
                # ignore this packet
                if debug:
                    print(
                        "packet with non-matching length: mac=%s adv_type=%02x plen=%s"
                        % (mac_addr_str, adv_type, plen))
                    print(raw_packet_to_str(pkt))
                continue

            data = pkt[9:-1]

            rssi = struct.unpack("b",
                                 full_pkt[len(full_pkt) - 1:len(full_pkt)])[0]

            if mac_addr and mac_addr_str not in mac_addr:
                if debug:
                    print(
                        "packet with non-matching mac %s adv_type=%02x data=%s RSSI=%s"
                        % (mac_addr_str, adv_type, raw_packet_to_str(data),
                           rssi))
                continue

            if debug:
                print(
                    "LE advertisement: mac=%s adv_type=%02x data=%s RSSI=%d" %
                    (mac_addr_str, adv_type, raw_packet_to_str(data), rssi))

            if handler is not None:
                try:
                    handler(mac_addr_str, adv_type, data, rssi)
                except Exception as e:
                    print(
                        'Exception when calling handler with a BLE advertising event: %r'
                        % (e, ))
                    import traceback
                    traceback.print_exc()

    except KeyboardInterrupt:
        print("\nRestore previous socket filter")
        sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter)
        raise