hciops.c revision c3ebed5a7d7e6146e7dfb97f6597222f1f9f0e71
11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  BlueZ - Bluetooth protocol stack for Linux
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  This program is free software; you can redistribute it and/or modify
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  it under the terms of the GNU General Public License as published by
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  the Free Software Foundation; either version 2 of the License, or
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  (at your option) any later version.
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  This program is distributed in the hope that it will be useful,
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  but WITHOUT ANY WARRANTY; without even the implied warranty of
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  GNU General Public License for more details.
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  You should have received a copy of the GNU General Public License
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  along with this program; if not, write to the Free Software
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#ifdef HAVE_CONFIG_H
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <config.h>
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#endif
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <stdio.h>
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <errno.h>
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <unistd.h>
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <stdlib.h>
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <sys/types.h>
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <sys/ioctl.h>
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <sys/wait.h>
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <bluetooth/bluetooth.h>
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <bluetooth/hci.h>
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <bluetooth/hci_lib.h>
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <glib.h>
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "hcid.h"
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "sdpd.h"
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "adapter.h"
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "plugin.h"
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "log.h"
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "storage.h"
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "event.h"
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "device.h"
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "manager.h"
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define HCI_REQ_TIMEOUT         5000
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic int child_pipe[2] = { -1, -1 };
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic guint child_io_id = 0;
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic guint ctl_io_id = 0;
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* Commands sent by kernel on starting an adapter */
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertenum {
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	PENDING_BDADDR,
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	PENDING_VERSION,
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	PENDING_FEATURES,
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	PENDING_NAME,
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert};
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define set_bit(nr, addr) (*(addr) |= (1 << (nr)))
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define clear_bit(nr, addr) (*(addr) &= ~(1 << (nr)))
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define SK(index) devs[(index)].sk
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define BDADDR(index) devs[(index)].bdaddr
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define FEATURES(index) devs[(index)].features
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define VER(index) devs[(index)].ver
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define UP(index) devs[(index)].up
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define PENDING(index) devs[(index)].pending
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define CHANNEL(index) devs[(index)].channel
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define WATCH_ID(index) devs[(index)].watch_id
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define PIN_LENGTH(index) devs[(index)].pin_length
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic int max_dev = -1;
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic struct dev_info {
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int sk;
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bdaddr_t bdaddr;
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t features[8];
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_version ver;
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	gboolean up;
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	unsigned long pending;
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	GIOChannel *channel;
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	guint watch_id;
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int pin_length;
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} *devs = NULL;
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic int ignore_device(struct hci_dev_info *di)
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return hci_test_bit(HCI_RAW, &di->flags) || di->type >> 4 != HCI_BREDR;
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void init_dev_info(int index, int sk)
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(&devs[index], 0, sizeof(struct dev_info));
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	SK(index) = sk;
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	PIN_LENGTH(index) = -1;
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* Async HCI command handling with callback support */
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstruct hci_cmd_data {
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bt_hci_result_t		cb;
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint16_t		handle;
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint16_t		ocf;
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	gpointer		caller_data;
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert};
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic gboolean hci_event_watch(GIOChannel *io,
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			GIOCondition cond, gpointer user_data)
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	unsigned char buf[HCI_MAX_EVENT_SIZE], *body;
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_cmd_data *cmd = user_data;
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_cmd_status *evt_status;
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_auth_complete *evt_auth;
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_encrypt_change *evt_enc;
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_event_hdr *hdr;
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	set_conn_encrypt_cp cp;
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int dd;
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint16_t ocf;
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t status = HCI_OE_POWER_OFF;
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (cond & G_IO_NVAL) {
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cmd->cb(status, cmd->caller_data);
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return FALSE;
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (cond & (G_IO_ERR | G_IO_HUP))
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		goto failed;
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	dd = g_io_channel_unix_get_fd(io);
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (read(dd, buf, sizeof(buf)) < 0)
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		goto failed;
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hdr = (hci_event_hdr *) (buf + 1);
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	body = buf + (1 + HCI_EVENT_HDR_SIZE);
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	switch (hdr->evt) {
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_CMD_STATUS:
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		evt_status = (evt_cmd_status *) body;
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ocf = cmd_opcode_ocf(evt_status->opcode);
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (ocf != cmd->ocf)
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return TRUE;
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		switch (ocf) {
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		case OCF_AUTH_REQUESTED:
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		case OCF_SET_CONN_ENCRYPT:
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			if (evt_status->status != 0) {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				/* Baseband rejected command */
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				status = evt_status->status;
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				goto failed;
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			}
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			break;
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		default:
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return TRUE;
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		/* Wait for the next event */
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return TRUE;
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_AUTH_COMPLETE:
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		evt_auth = (evt_auth_complete *) body;
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (evt_auth->handle != cmd->handle) {
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			/* Skipping */
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return TRUE;
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (evt_auth->status != 0x00) {
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			status = evt_auth->status;
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			/* Abort encryption */
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			goto failed;
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		memset(&cp, 0, sizeof(cp));
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cp.handle  = cmd->handle;
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cp.encrypt = 1;
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cmd->ocf = OCF_SET_CONN_ENCRYPT;
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT,
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					SET_CONN_ENCRYPT_CP_SIZE, &cp) < 0) {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			status = HCI_COMMAND_DISALLOWED;
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			goto failed;
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		/* Wait for encrypt change event */
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return TRUE;
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_ENCRYPT_CHANGE:
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		evt_enc = (evt_encrypt_change *) body;
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (evt_enc->handle != cmd->handle)
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return TRUE;
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		/* Procedure finished: reporting status */
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		status = evt_enc->status;
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	default:
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		/* Skipping */
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return TRUE;
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfailed:
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cmd->cb(status, cmd->caller_data);
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_io_channel_shutdown(io, TRUE, NULL);
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return FALSE;
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic int write_inq_mode(int index, uint8_t mode)
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	write_inquiry_mode_cp cp;
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(&cp, 0, sizeof(cp));
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cp.mode = mode;
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE,
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					WRITE_INQUIRY_MODE_CP_SIZE, &cp) < 0)
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return -errno;
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return 0;
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic uint8_t get_inquiry_mode(int index)
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (FEATURES(index)[6] & LMP_EXT_INQ)
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return 2;
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (FEATURES(index)[3] & LMP_RSSI_INQ)
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return 1;
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (VER(index).manufacturer == 11 && VER(index).hci_rev == 0x00 &&
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					VER(index).lmp_subver == 0x0757)
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return 1;
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (VER(index).manufacturer == 15) {
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (VER(index).hci_rev == 0x03 &&
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					VER(index).lmp_subver == 0x6963)
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return 1;
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (VER(index).hci_rev == 0x09 &&
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					VER(index).lmp_subver == 0x6963)
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return 1;
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (VER(index).hci_rev == 0x00 &&
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					VER(index).lmp_subver == 0x6965)
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return 1;
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (VER(index).manufacturer == 31 && VER(index).hci_rev == 0x2005 &&
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					VER(index).lmp_subver == 0x1805)
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return 1;
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return 0;
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic int init_ssp_mode(int index)
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	write_simple_pairing_mode_cp cp;
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (ioctl(SK(index), HCIGETAUTHINFO, NULL) < 0 && errno == EINVAL)
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return 0;
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(&cp, 0, sizeof(cp));
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cp.mode = 0x01;
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (hci_send_cmd(SK(index), OGF_HOST_CTL,
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				OCF_WRITE_SIMPLE_PAIRING_MODE,
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				WRITE_SIMPLE_PAIRING_MODE_CP_SIZE, &cp) < 0)
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return -errno;
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return 0;
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void start_adapter(int index)
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t events[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00 };
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t inqmode;
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (VER(index).lmp_ver > 1) {
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (FEATURES(index)[5] & LMP_SNIFF_SUBR)
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[5] |= 0x20;
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (FEATURES(index)[5] & LMP_PAUSE_ENC)
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[5] |= 0x80;
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (FEATURES(index)[6] & LMP_EXT_INQ)
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[5] |= 0x40;
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (FEATURES(index)[6] & LMP_NFLUSH_PKTS)
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[7] |= 0x01;
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (FEATURES(index)[7] & LMP_LSTO)
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[6] |= 0x80;
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (FEATURES(index)[6] & LMP_SIMPLE_PAIR) {
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[6] |= 0x01;	/* IO Capability Request */
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[6] |= 0x02;	/* IO Capability Response */
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[6] |= 0x04;	/* User Confirmation Request */
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[6] |= 0x08;	/* User Passkey Request */
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[6] |= 0x10;	/* Remote OOB Data Request */
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[6] |= 0x20;	/* Simple Pairing Complete */
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[7] |= 0x04;	/* User Passkey Notification */
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[7] |= 0x08;	/* Keypress Notification */
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[7] |= 0x10;	/* Remote Host Supported
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						 * Features Notification */
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (FEATURES(index)[4] & LMP_LE)
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			events[7] |= 0x20;	/* LE Meta-Event */
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_SET_EVENT_MASK,
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						sizeof(events), events);
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (FEATURES(index)[6] & LMP_SIMPLE_PAIR)
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		init_ssp_mode(index);
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	inqmode = get_inquiry_mode(index);
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (inqmode)
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		write_inq_mode(index, inqmode);
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (FEATURES(index)[7] & LMP_INQ_TX_PWR)
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_HOST_CTL,
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL, 0, NULL);
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	manager_start_adapter(index);
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic int hciops_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb,
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert							gpointer user_data)
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	GIOChannel *io;
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_cmd_data *cmd;
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_conn_info_req *cr;
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	auth_requested_cp cp;
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_filter nf;
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int dd, err;
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint32_t link_mode;
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint16_t handle;
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	dd = hci_open_dev(index);
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (dd < 0)
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return -errno;
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info));
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cr->type = ACL_LINK;
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bacpy(&cr->bdaddr, dst);
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	err = ioctl(dd, HCIGETCONNINFO, cr);
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	link_mode = cr->conn_info->link_mode;
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	handle = cr->conn_info->handle;
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_free(cr);
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (err < 0) {
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		err = -errno;
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		goto fail;
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (link_mode & HCI_LM_ENCRYPT) {
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		err = -EALREADY;
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		goto fail;
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(&cp, 0, sizeof(cp));
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cp.handle = htobs(handle);
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_AUTH_REQUESTED,
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				AUTH_REQUESTED_CP_SIZE, &cp) < 0) {
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		err = -errno;
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		goto fail;
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cmd = g_new0(struct hci_cmd_data, 1);
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cmd->handle = handle;
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cmd->ocf = OCF_AUTH_REQUESTED;
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cmd->cb	= cb;
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cmd->caller_data = user_data;
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_clear(&nf);
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_CMD_STATUS, &nf);
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_AUTH_COMPLETE, &nf);
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_ENCRYPT_CHANGE, &nf);
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) {
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		err = -errno;
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		g_free(cmd);
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		goto fail;
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	io = g_io_channel_unix_new(dd);
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_io_channel_set_close_on_unref(io, FALSE);
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			G_IO_HUP | G_IO_ERR | G_IO_NVAL | G_IO_IN,
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			hci_event_watch, cmd, g_free);
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_io_channel_unref(io);
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return 0;
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfail:
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	close(dd);
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return err;
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* End async HCI command handling */
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* Start of HCI event callbacks */
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic int get_handle(int index, bdaddr_t *dba, uint16_t *handle)
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_conn_list_req *cl;
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_conn_info *ci;
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int i;
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl));
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cl->dev_id = index;
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cl->conn_num = 10;
4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ci = cl->conn_info;
4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (ioctl(SK(index), HCIGETCONNLIST, (void *) cl) < 0) {
4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		g_free(cl);
4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return -EIO;
4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	for (i = 0; i < cl->conn_num; i++, ci++) {
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (bacmp(&ci->bdaddr, dba) == 0) {
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			*handle = ci->handle;
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			g_free(cl);
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return 0;
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_free(cl);
4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return -ENOENT;
4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline int get_bdaddr(int index, uint16_t handle, bdaddr_t *dba)
4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_conn_list_req *cl;
4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_conn_info *ci;
4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int i;
4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl));
4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cl->dev_id = index;
4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cl->conn_num = 10;
4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ci = cl->conn_info;
4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (ioctl(SK(index), HCIGETCONNLIST, (void *) cl) < 0) {
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		g_free(cl);
4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return -EIO;
4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	for (i = 0; i < cl->conn_num; i++, ci++)
4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (ci->handle == handle) {
4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			bacpy(dba, &ci->bdaddr);
4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			g_free(cl);
4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return 0;
4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_free(cl);
4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return -ENOENT;
4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void update_lastseen(bdaddr_t *sba, bdaddr_t *dba)
4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	time_t t;
4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct tm *tm;
4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	t = time(NULL);
4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	tm = gmtime(&t);
4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	write_lastseen_info(sba, dba, tm);
4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void update_lastused(bdaddr_t *sba, bdaddr_t *dba)
4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	time_t t;
4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct tm *tm;
4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	t = time(NULL);
4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	tm = gmtime(&t);
4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	write_lastused_info(sba, dba, tm);
4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* Link Key handling */
4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void link_key_request(int index, bdaddr_t *dba)
4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_device *device;
4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_auth_info_req req;
4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	unsigned char key[16];
4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char sa[18], da[18];
4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t type;
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int err;
5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&BDADDR(index), sa); ba2str(dba, da);
5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info("link_key_request (sba=%s, dba=%s)", sa, da);
5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(&BDADDR(index));
5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (adapter)
5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		device = adapter_find_device(adapter, da);
5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	else
5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		device = NULL;
5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(&req, 0, sizeof(req));
5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bacpy(&req.bdaddr, dba);
5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	err = ioctl(SK(index), HCIGETAUTHINFO, (unsigned long) &req);
5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (err < 0) {
5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (errno != EINVAL)
5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			DBG("HCIGETAUTHINFO failed %s (%d)",
5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						strerror(errno), errno);
5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		req.type = 0x00;
5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	DBG("kernel auth requirements = 0x%02x", req.type);
5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (main_opts.debug_keys && device &&
5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					device_get_debug_key(device, key))
5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		type = 0x03;
5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	else if (read_link_key(&BDADDR(index), dba, key, &type) < 0 ||
5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert								type == 0x03) {
5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		/* Link key not found */
5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY,
5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert								6, dba);
5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* Link key found */
5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	DBG("link key type = 0x%02x", type);
5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* Don't use unauthenticated combination keys if MITM is
5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	 * required */
5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (type == 0x04 && req.type != 0xff && (req.type & 0x01))
5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY,
5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert								6, dba);
5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	else {
5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		link_key_reply_cp lr;
5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		memcpy(lr.link_key, key, 16);
5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		bacpy(&lr.bdaddr, dba);
5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_LINK_KEY_REPLY,
5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						LINK_KEY_REPLY_CP_SIZE, &lr);
5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void link_key_notify(int index, void *ptr)
5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_link_key_notify *evt = ptr;
5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bdaddr_t *dba = &evt->bdaddr;
5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char sa[18], da[18];
5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int err;
5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	unsigned char old_key[16];
5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t old_key_type;
5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&BDADDR(index), sa); ba2str(dba, da);
5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info("link_key_notify (sba=%s, dba=%s, type=%d)", sa, da,
5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert							evt->key_type);
5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	err = read_link_key(&BDADDR(index), dba, old_key, &old_key_type);
5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (err < 0)
5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		old_key_type = 0xff;
5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	err = btd_event_link_key_notify(&BDADDR(index), dba, evt->link_key,
5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					evt->key_type, PIN_LENGTH(index),
5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					old_key_type);
5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	PIN_LENGTH(index) = -1;
5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (err < 0) {
5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		uint16_t handle;
5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (err == -ENODEV)
5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			btd_event_bonding_process_complete(&BDADDR(index), dba,
5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert							HCI_OE_LOW_RESOURCES);
5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		else
5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			btd_event_bonding_process_complete(&BDADDR(index), dba,
5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert							HCI_MEMORY_FULL);
5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (get_handle(index, dba, &handle) == 0) {
5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			disconnect_cp cp;
5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			memset(&cp, 0, sizeof(cp));
5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			cp.handle = htobs(handle);
5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			cp.reason = HCI_OE_LOW_RESOURCES;
5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_DISCONNECT,
5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						DISCONNECT_CP_SIZE, &cp);
5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void return_link_keys(int index, void *ptr)
6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_return_link_keys *evt = ptr;
6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t num = evt->num_keys;
6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	unsigned char key[16];
6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char sa[18], da[18];
6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bdaddr_t dba;
6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int i;
6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&BDADDR(index), sa);
6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ptr++;
6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	for (i = 0; i < num; i++) {
6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		bacpy(&dba, ptr); ba2str(&dba, da);
6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		memcpy(key, ptr + 6, 16);
6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		info("return_link_keys (sba=%s, dba=%s)", sa, da);
6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_returned_link_key(&BDADDR(index), &dba);
6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += 22;
6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* Simple Pairing handling */
6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void user_confirm_request(int index, void *ptr)
6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_user_confirm_request *req = ptr;
6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (btd_event_user_confirm(&BDADDR(index), &req->bdaddr,
6311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					btohl(req->passkey)) < 0)
6321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL,
6331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				OCF_USER_CONFIRM_NEG_REPLY, 6, ptr);
6341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
6351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void user_passkey_request(int index, void *ptr)
6371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
6381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_user_passkey_request *req = ptr;
6391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (btd_event_user_passkey(&BDADDR(index), &req->bdaddr) < 0)
6411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL,
6421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				OCF_USER_PASSKEY_NEG_REPLY, 6, ptr);
6431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
6441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void user_passkey_notify(int index, void *ptr)
6461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
6471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_user_passkey_notify *req = ptr;
6481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_user_notify(&BDADDR(index), &req->bdaddr,
6501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						btohl(req->passkey));
6511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
6521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void remote_oob_data_request(int index, void *ptr)
6541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
6551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_send_cmd(SK(index), OGF_LINK_CTL,
6561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, ptr);
6571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
6581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void io_capa_request(int index, void *ptr)
6601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
6611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bdaddr_t *dba = ptr;
6621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char sa[18], da[18];
6631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t cap, auth;
6641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&BDADDR(index), sa); ba2str(dba, da);
6661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info("io_capa_request (sba=%s, dba=%s)", sa, da);
6671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (btd_event_get_io_cap(&BDADDR(index), dba, &cap, &auth) < 0) {
6691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		io_capability_neg_reply_cp cp;
6701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		memset(&cp, 0, sizeof(cp));
6711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		bacpy(&cp.bdaddr, dba);
6721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cp.reason = HCI_PAIRING_NOT_ALLOWED;
6731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL,
6741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					OCF_IO_CAPABILITY_NEG_REPLY,
6751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					IO_CAPABILITY_NEG_REPLY_CP_SIZE, &cp);
6761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	} else {
6771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		io_capability_reply_cp cp;
6781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		memset(&cp, 0, sizeof(cp));
6791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		bacpy(&cp.bdaddr, dba);
6801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cp.capability = cap;
6811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cp.oob_data = 0x00;
6821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cp.authentication = auth;
6831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY,
6841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					IO_CAPABILITY_REPLY_CP_SIZE, &cp);
6851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
6861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
6871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void io_capa_response(int index, void *ptr)
6891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
6901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_io_capability_response *evt = ptr;
6911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char sa[18], da[18];
6921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&BDADDR(index), sa); ba2str(&evt->bdaddr, da);
6941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info("io_capa_response (sba=%s, dba=%s)", sa, da);
6951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_set_io_cap(&BDADDR(index), &evt->bdaddr,
6971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				evt->capability, evt->authentication);
6981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
6991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* PIN code handling */
7011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void pin_code_request(int index, bdaddr_t *dba)
7031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
7041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	pin_code_reply_cp pr;
7051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_conn_info_req *cr;
7061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_conn_info *ci;
7071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char sa[18], da[18], pin[17];
7081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int pinlen;
7091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(&pr, 0, sizeof(pr));
7111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bacpy(&pr.bdaddr, dba);
7121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&BDADDR(index), sa); ba2str(dba, da);
7141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info("pin_code_request (sba=%s, dba=%s)", sa, da);
7151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cr = g_malloc0(sizeof(*cr) + sizeof(*ci));
7171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bacpy(&cr->bdaddr, dba);
7191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cr->type = ACL_LINK;
7201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (ioctl(SK(index), HCIGETCONNINFO, (unsigned long) cr) < 0) {
7211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Can't get conn info: %s (%d)", strerror(errno), errno);
7221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		goto reject;
7231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
7241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ci = cr->conn_info;
7251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(pin, 0, sizeof(pin));
7271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	pinlen = read_pin_code(&BDADDR(index), dba, pin);
7281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (pinlen > 0) {
7301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		PIN_LENGTH(index) = pinlen;
7311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		memcpy(pr.pin_code, pin, pinlen);
7321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		pr.pin_len = pinlen;
7331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
7341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						PIN_CODE_REPLY_CP_SIZE, &pr);
7351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	} else {
7361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		/* Request PIN from passkey agent */
7371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (btd_event_request_pin(&BDADDR(index), ci) < 0)
7381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			goto reject;
7391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
7401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_free(cr);
7421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return;
7441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertreject:
7461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_free(cr);
7471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba);
7491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
7501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void start_inquiry(bdaddr_t *local, uint8_t status, gboolean periodic)
7521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
7531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
7541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int state;
7551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* Don't send the signal if the cmd failed */
7571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (status) {
7581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Inquiry Failed with status 0x%02x", status);
7591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
7601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
7611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(local);
7631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
7641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Unable to find matching adapter");
7651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
7661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
7671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	state = adapter_get_state(adapter);
7691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (periodic)
7711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		state |= STATE_PINQ;
7721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	else
7731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		state |= STATE_STDINQ;
7741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter_set_state(adapter, state);
7761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
7771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void inquiry_complete(bdaddr_t *local, uint8_t status,
7791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert							gboolean periodic)
7801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
7811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
7821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int state;
7831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* Don't send the signal if the cmd failed */
7851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (status) {
7861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Inquiry Failed with status 0x%02x", status);
7871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
7881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
7891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(local);
7911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
7921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Unable to find matching adapter");
7931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
7941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
7951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	state = adapter_get_state(adapter);
7971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	state &= ~(STATE_STDINQ | STATE_PINQ);
7981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter_set_state(adapter, state);
7991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
8001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void remote_features_notify(int index, void *ptr)
8021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
8031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_remote_host_features_notify *evt = ptr;
8041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (evt->features[0] & 0x01)
8061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_set_legacy_pairing(&BDADDR(index), &evt->bdaddr,
8071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert									FALSE);
8081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	else
8091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_set_legacy_pairing(&BDADDR(index), &evt->bdaddr,
8101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert									TRUE);
8111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	write_features_info(&BDADDR(index), &evt->bdaddr, NULL, evt->features);
8131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
8141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void write_le_host_complete(bdaddr_t *sba, uint8_t status)
8161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
8171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
8181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (status)
8201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(sba);
8231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
8241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("No matching adapter found");
8251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
8271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_adapter_read_local_ext_features(adapter);
8291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
8301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_local_version_complete(int index,
8321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				const read_local_version_rp *rp)
8331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
8341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->status)
8351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	VER(index).manufacturer = btohs(bt_get_unaligned(&rp->manufacturer));
8381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	VER(index).hci_ver = rp->hci_ver;
8391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	VER(index).hci_rev = btohs(bt_get_unaligned(&rp->hci_rev));
8401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	VER(index).lmp_ver = rp->lmp_ver;
8411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	VER(index).lmp_subver = btohs(bt_get_unaligned(&rp->lmp_subver));
8421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index))
8441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	clear_bit(PENDING_VERSION, &PENDING(index));
8471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	DBG("Got version for hci%d", index);
8491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index) && UP(index))
8511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		start_adapter(index);
8521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
8531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_local_features_complete(int index,
8551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				const read_local_features_rp *rp)
8561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
8571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->status)
8581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memcpy(FEATURES(index), rp->features, 8);
8611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index))
8631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	clear_bit(PENDING_FEATURES, &PENDING(index));
8661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	DBG("Got features for hci%d", index);
8681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index) && UP(index))
8701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		start_adapter(index);
8711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
8721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void update_name(int index, const char *name)
8741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
8751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
8761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(&BDADDR(index));
8781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (adapter)
8791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		adapter_update_local_name(adapter, name);
8801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
8811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_local_name_complete(int index, read_local_name_rp *rp)
8831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
8841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->status)
8851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index)) {
8881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		update_name(index, (char *) rp->name);
8891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
8911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	clear_bit(PENDING_NAME, &PENDING(index));
8931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	DBG("Got name for hci%d", index);
8951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!UP(index))
8971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
8981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* Even though it shouldn't happen (assuming the kernel behaves
9001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	 * properly) it seems like we might miss the very first
9011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	 * initialization commands that the kernel sends. So check for
9021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	 * it here (since read_local_name is one of the last init
9031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	 * commands) and resend the first ones if we haven't seen
9041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	 * their results yet */
9051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (hci_test_bit(PENDING_FEATURES, &PENDING(index)))
9071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_INFO_PARAM,
9081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					OCF_READ_LOCAL_FEATURES, 0, NULL);
9091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (hci_test_bit(PENDING_VERSION, &PENDING(index)))
9111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		hci_send_cmd(SK(index), OGF_INFO_PARAM,
9121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					OCF_READ_LOCAL_VERSION, 0, NULL);
9131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index))
9151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		start_adapter(index);
9161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
9171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_tx_power_complete(int index, void *ptr)
9191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
9201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	read_inq_response_tx_power_level_rp *rp = ptr;
9211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
9221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->status)
9241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(&BDADDR(index));
9271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
9281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("No matching adapter found");
9291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
9311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter_update_tx_power(adapter, rp->level);
9331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
9341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_simple_pairing_mode_complete(int index, void *ptr)
9361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
9371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	read_simple_pairing_mode_rp *rp = ptr;
9381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
9391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->status)
9411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(&BDADDR(index));
9441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
9451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("No matching adapter found");
9461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
9481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter_update_ssp_mode(adapter, rp->mode);
9501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
9511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_local_ext_features_complete(bdaddr_t *sba,
9531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				const read_local_ext_features_rp *rp)
9541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
9551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
9561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->status)
9581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(sba);
9611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
9621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("No matching adapter found");
9631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
9651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* Local Extended feature page number is 1 */
9671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->page_num != 1)
9681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_adapter_update_local_ext_features(adapter, rp->features);
9711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
9721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_bd_addr_complete(int index, read_bd_addr_rp *rp)
9741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
9751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (rp->status)
9761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bacpy(&BDADDR(index), &rp->bdaddr);
9791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index))
9811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
9821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	clear_bit(PENDING_BDADDR, &PENDING(index));
9841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	DBG("Got bdaddr for hci%d", index);
9861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!PENDING(index) && UP(index))
9881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		start_adapter(index);
9891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
9901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void cmd_status(int index, void *ptr)
9921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
9931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_cmd_status *evt = ptr;
9941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint16_t opcode = btohs(evt->opcode);
9951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY))
9971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		start_inquiry(&BDADDR(index), evt->status, FALSE);
9981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
9991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void read_scan_complete(int index, uint8_t status, void *ptr)
10011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
10021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
10031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	read_scan_enable_rp *rp = ptr;
10041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(&BDADDR(index));
10061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
10081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Unable to find matching adapter");
10091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
10101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
10111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter_mode_changed(adapter, rp->enable);
10131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
10141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void cmd_complete(int index, void *ptr)
10161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
10171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_cmd_complete *evt = ptr;
10181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint16_t opcode = btohs(evt->opcode);
10191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t status = *((uint8_t *) ptr + EVT_CMD_COMPLETE_SIZE);
10201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	switch (opcode) {
10221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION):
10231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_local_version_complete(index, ptr);
10251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES):
10271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_local_features_complete(index, ptr);
10291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_EXT_FEATURES):
10311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_local_ext_features_complete(&BDADDR(index), ptr);
10331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BD_ADDR):
10351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_bd_addr_complete(index, ptr);
10371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_LINK_CTL, OCF_PERIODIC_INQUIRY):
10391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		start_inquiry(&BDADDR(index), status, TRUE);
10401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_LINK_CTL, OCF_EXIT_PERIODIC_INQUIRY):
10421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		inquiry_complete(&BDADDR(index), status, TRUE);
10431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL):
10451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		inquiry_complete(&BDADDR(index), status, FALSE);
10461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_LE_HOST_SUPPORTED):
10481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		write_le_host_complete(&BDADDR(index), status);
10491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE):
10511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_le_set_scan_enable_complete(&BDADDR(index), status);
10521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME):
10541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (!status)
10551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			hci_send_cmd(SK(index), OGF_HOST_CTL,
10561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						OCF_READ_LOCAL_NAME, 0, 0);
10571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE):
10591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_setscan_enable_complete(&BDADDR(index));
10601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SCAN_ENABLE):
10621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_scan_complete(index, status, ptr);
10641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV):
10661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		adapter_set_class_complete(&BDADDR(index), status);
10671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SIMPLE_PAIRING_MODE):
10691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (!status)
10701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			hci_send_cmd(SK(index), OGF_HOST_CTL,
10711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					OCF_READ_SIMPLE_PAIRING_MODE, 0, NULL);
10721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SIMPLE_PAIRING_MODE):
10741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_simple_pairing_mode_complete(index, ptr);
10761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_NAME):
10781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_local_name_complete(index, ptr);
10801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case cmd_opcode_pack(OGF_HOST_CTL,
10821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL):
10831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += sizeof(evt_cmd_complete);
10841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		read_tx_power_complete(index, ptr);
10851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
10861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	};
10871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
10881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void remote_name_information(int index, void *ptr)
10901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
10911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_remote_name_req_complete *evt = ptr;
10921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char name[MAX_NAME_LENGTH + 1];
10931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(name, 0, sizeof(name));
10951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!evt->status)
10971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		memcpy(name, evt->name, MAX_NAME_LENGTH);
10981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_remote_name(&BDADDR(index), &evt->bdaddr, evt->status, name);
11001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
11011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void remote_version_information(int index, void *ptr)
11031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
11041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_read_remote_version_complete *evt = ptr;
11051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bdaddr_t dba;
11061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (evt->status)
11081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
11091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (get_bdaddr(index, btohs(evt->handle), &dba) < 0)
11111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
11121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	write_version_info(&BDADDR(index), &dba, btohs(evt->manufacturer),
11141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				evt->lmp_ver, btohs(evt->lmp_subver));
11151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
11161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void inquiry_result(int index, int plen, void *ptr)
11181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
11191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t num = *(uint8_t *) ptr++;
11201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int i;
11211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	for (i = 0; i < num; i++) {
11231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		inquiry_info *info = ptr;
11241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		uint32_t class = info->dev_class[0] |
11251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						(info->dev_class[1] << 8) |
11261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						(info->dev_class[2] << 16);
11271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_inquiry_result(&BDADDR(index), &info->bdaddr, class,
11291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert								0, NULL);
11301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		update_lastseen(&BDADDR(index), &info->bdaddr);
11321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += INQUIRY_INFO_SIZE;
11341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
11351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
11361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void inquiry_result_with_rssi(int index, int plen, void *ptr)
11381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
11391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t num = *(uint8_t *) ptr++;
11401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int i;
11411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!num)
11431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
11441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if ((plen - 1) / num == INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE) {
11461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		for (i = 0; i < num; i++) {
11471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			inquiry_info_with_rssi_and_pscan_mode *info = ptr;
11481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			uint32_t class = info->dev_class[0]
11491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						| (info->dev_class[1] << 8)
11501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						| (info->dev_class[2] << 16);
11511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			btd_event_inquiry_result(&BDADDR(index), &info->bdaddr,
11531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						class, info->rssi, NULL);
11541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			update_lastseen(&BDADDR(index), &info->bdaddr);
11561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			ptr += INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE;
11581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
11591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	} else {
11601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		for (i = 0; i < num; i++) {
11611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			inquiry_info_with_rssi *info = ptr;
11621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			uint32_t class = info->dev_class[0]
11631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						| (info->dev_class[1] << 8)
11641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						| (info->dev_class[2] << 16);
11651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			btd_event_inquiry_result(&BDADDR(index), &info->bdaddr,
11671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						class, info->rssi, NULL);
11681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			update_lastseen(&BDADDR(index), &info->bdaddr);
11701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			ptr += INQUIRY_INFO_WITH_RSSI_SIZE;
11721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		}
11731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
11741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
11751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void extended_inquiry_result(int index, int plen, void *ptr)
11771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
11781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t num = *(uint8_t *) ptr++;
11791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int i;
11801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	for (i = 0; i < num; i++) {
11821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		extended_inquiry_info *info = ptr;
11831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		uint32_t class = info->dev_class[0]
11841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					| (info->dev_class[1] << 8)
11851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					| (info->dev_class[2] << 16);
11861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_inquiry_result(&BDADDR(index), &info->bdaddr, class,
11881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						info->rssi, info->data);
11891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		update_lastseen(&BDADDR(index), &info->bdaddr);
11911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		ptr += EXTENDED_INQUIRY_INFO_SIZE;
11931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
11941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
11951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void remote_features_information(int index, void *ptr)
11971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
11981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_read_remote_features_complete *evt = ptr;
11991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bdaddr_t dba;
12001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (evt->status)
12021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
12031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (get_bdaddr(index, btohs(evt->handle), &dba) < 0)
12051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
12061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	write_features_info(&BDADDR(index), &dba, evt->features, NULL);
12081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
12091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void conn_complete(int index, void *ptr)
12111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
12121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_conn_complete *evt = ptr;
12131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char filename[PATH_MAX];
12141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	char local_addr[18], peer_addr[18], *str;
12151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct btd_adapter *adapter;
12161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	adapter = manager_find_adapter(&BDADDR(index));
12181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!adapter) {
12191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Unable to find matching adapter");
12201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
12211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
12221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (evt->link_type != ACL_LINK)
12241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
12251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_conn_complete(&BDADDR(index), evt->status,
12271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					btohs(evt->handle), &evt->bdaddr);
12281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (evt->status)
12301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
12311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	update_lastused(&BDADDR(index), &evt->bdaddr);
12331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* check if the remote version needs be requested */
12351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&BDADDR(index), local_addr);
12361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ba2str(&evt->bdaddr, peer_addr);
12371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	create_name(filename, sizeof(filename), STORAGEDIR, local_addr,
12391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert							"manufacturers");
12401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	str = textfile_get(filename, peer_addr);
12421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!str)
12431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_adapter_get_remote_version(adapter, btohs(evt->handle),
12441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert									TRUE);
12451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	else
12461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		free(str);
12471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
12481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void disconn_complete(int index, void *ptr)
12501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
12511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_disconn_complete *evt = ptr;
12521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_disconn_complete(&BDADDR(index), evt->status,
12541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert					btohs(evt->handle), evt->reason);
12551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
12561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void auth_complete(int index, void *ptr)
12581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
12591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_auth_complete *evt = ptr;
12601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	bdaddr_t dba;
12611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (get_bdaddr(index, btohs(evt->handle), &dba) < 0)
12631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
12641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_bonding_process_complete(&BDADDR(index), &dba, evt->status);
12661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
12671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void simple_pairing_complete(int index, void *ptr)
12691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
12701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_simple_pairing_complete *evt = ptr;
12711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_simple_pairing_complete(&BDADDR(index), &evt->bdaddr,
12731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert								evt->status);
12741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
12751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void conn_request(int index, void *ptr)
12771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
12781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_conn_request *evt = ptr;
12791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint32_t class = evt->dev_class[0] | (evt->dev_class[1] << 8)
12801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert				| (evt->dev_class[2] << 16);
12811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	btd_event_remote_class(&BDADDR(index), &evt->bdaddr, class);
12831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
12841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic inline void le_metaevent(int index, void *ptr)
12861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
12871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_le_meta_event *meta = ptr;
12881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	le_advertising_info *info;
12891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	uint8_t num, i;
12901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	DBG("LE Meta Event");
12921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (meta->subevent != EVT_LE_ADVERTISING_REPORT)
12941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
12951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	num = meta->data[0];
12971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info = (le_advertising_info *) (meta->data + 1);
12981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	for (i = 0; i < num; i++) {
13001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		btd_event_advertising_report(&BDADDR(index), info);
13011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		info = (le_advertising_info *) (info->data + info->length + 1);
13021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
13031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
13041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void stop_hci_dev(int index)
13061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
13071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	GIOChannel *chan = CHANNEL(index);
13081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (!chan)
13101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
13111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info("Stopping hci%d event socket", index);
13131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_source_remove(WATCH_ID(index));
13151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	g_io_channel_unref(CHANNEL(index));
13161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_close_dev(SK(index));
13171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	init_dev_info(index, -1);
13181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
13191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic gboolean io_security_event(GIOChannel *chan, GIOCondition cond,
13211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert								gpointer data)
13221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
13231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf;
13241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	int type, index = GPOINTER_TO_INT(data);
13251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_dev_info di;
13261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	size_t len;
13271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_event_hdr *eh;
13281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	GIOError err;
13291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	evt_cmd_status *evt;
13301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
13321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		stop_hci_dev(index);
13331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return FALSE;
13341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
13351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if ((err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len))) {
13371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (err == G_IO_ERROR_AGAIN)
13381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return TRUE;
13391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		stop_hci_dev(index);
13401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return FALSE;
13411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
13421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	type = *ptr++;
13441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (type != HCI_EVENT_PKT)
13461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return TRUE;
13471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	eh = (hci_event_hdr *) ptr;
13491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	ptr += HCI_EVENT_HDR_SIZE;
13501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	memset(&di, 0, sizeof(di));
13521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (hci_devinfo(index, &di) == 0) {
13531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		bacpy(&BDADDR(index), &di.bdaddr);
13541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		if (ignore_device(&di))
13561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert			return TRUE;
13571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
13581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	switch (eh->evt) {
13601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_CMD_STATUS:
13611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cmd_status(index, ptr);
13621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_CMD_COMPLETE:
13651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		cmd_complete(index, ptr);
13661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_REMOTE_NAME_REQ_COMPLETE:
13691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		remote_name_information(index, ptr);
13701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_READ_REMOTE_VERSION_COMPLETE:
13731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		remote_version_information(index, ptr);
13741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_READ_REMOTE_FEATURES_COMPLETE:
13771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		remote_features_information(index, ptr);
13781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_REMOTE_HOST_FEATURES_NOTIFY:
13811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		remote_features_notify(index, ptr);
13821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_INQUIRY_COMPLETE:
13851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		evt = (evt_cmd_status *) ptr;
13861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		inquiry_complete(&BDADDR(index), evt->status, FALSE);
13871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_INQUIRY_RESULT:
13901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		inquiry_result(index, eh->plen, ptr);
13911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_INQUIRY_RESULT_WITH_RSSI:
13941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		inquiry_result_with_rssi(index, eh->plen, ptr);
13951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
13961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_EXTENDED_INQUIRY_RESULT:
13981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		extended_inquiry_result(index, eh->plen, ptr);
13991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_CONN_COMPLETE:
14021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		conn_complete(index, ptr);
14031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_DISCONN_COMPLETE:
14061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		disconn_complete(index, ptr);
14071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_AUTH_COMPLETE:
14101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		auth_complete(index, ptr);
14111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_SIMPLE_PAIRING_COMPLETE:
14141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		simple_pairing_complete(index, ptr);
14151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_CONN_REQUEST:
14181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		conn_request(index, ptr);
14191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_LE_META_EVENT:
14211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		le_metaevent(index, ptr);
14221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_PIN_CODE_REQ:
14241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		pin_code_request(index, (bdaddr_t *) ptr);
14251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_LINK_KEY_REQ:
14281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		link_key_request(index, (bdaddr_t *) ptr);
14291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_LINK_KEY_NOTIFY:
14321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		link_key_notify(index, ptr);
14331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_RETURN_LINK_KEYS:
14361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return_link_keys(index, ptr);
14371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_IO_CAPABILITY_REQUEST:
14401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		io_capa_request(index, ptr);
14411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_IO_CAPABILITY_RESPONSE:
14441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		io_capa_response(index, ptr);
14451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_USER_CONFIRM_REQUEST:
14481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		user_confirm_request(index, ptr);
14491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_USER_PASSKEY_REQUEST:
14521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		user_passkey_request(index, ptr);
14531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_USER_PASSKEY_NOTIFY:
14561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		user_passkey_notify(index, ptr);
14571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	case EVT_REMOTE_OOB_DATA_REQUEST:
14601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		remote_oob_data_request(index, ptr);
14611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		break;
14621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
14631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	return TRUE;
14651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
14661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void start_hci_dev(int index)
14681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{
14691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	GIOChannel *chan = CHANNEL(index);
14701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	GIOCondition cond;
14711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	struct hci_filter flt;
14721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (chan)
14741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
14751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	info("Listening for HCI events on hci%d", index);
14771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	/* Set filter */
14791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_clear(&flt);
14801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
14811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_CMD_STATUS, &flt);
14821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_CMD_COMPLETE, &flt);
14831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_PIN_CODE_REQ, &flt);
14841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_LINK_KEY_REQ, &flt);
14851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_LINK_KEY_NOTIFY, &flt);
14861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_RETURN_LINK_KEYS, &flt);
14871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_IO_CAPABILITY_REQUEST, &flt);
14881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_IO_CAPABILITY_RESPONSE, &flt);
14891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_USER_CONFIRM_REQUEST, &flt);
14901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_USER_PASSKEY_REQUEST, &flt);
14911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_REMOTE_OOB_DATA_REQUEST, &flt);
14921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_USER_PASSKEY_NOTIFY, &flt);
14931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_KEYPRESS_NOTIFY, &flt);
14941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_SIMPLE_PAIRING_COMPLETE, &flt);
14951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_AUTH_COMPLETE, &flt);
14961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt);
14971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_READ_REMOTE_VERSION_COMPLETE, &flt);
14981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_READ_REMOTE_FEATURES_COMPLETE, &flt);
14991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_REMOTE_HOST_FEATURES_NOTIFY, &flt);
15001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt);
15011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_INQUIRY_RESULT, &flt);
15021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt);
15031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_EXTENDED_INQUIRY_RESULT, &flt);
15041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_CONN_REQUEST, &flt);
15051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_CONN_COMPLETE, &flt);
15061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_DISCONN_COMPLETE, &flt);
15071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	hci_filter_set_event(EVT_LE_META_EVENT, &flt);
15081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	if (setsockopt(SK(index), SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
15091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		error("Can't set filter on hci%d: %s (%d)",
15101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						index, strerror(errno), errno);
15111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert		return;
15121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	}
15131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	chan = g_io_channel_unix_new(SK(index));
15151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	cond = G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR;
15161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	WATCH_ID(index) = g_io_add_watch_full(chan, G_PRIORITY_LOW, cond,
15171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						io_security_event,
15181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert						GINT_TO_POINTER(index), NULL);
15191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert	CHANNEL(index) = chan;
1520	PIN_LENGTH(index) = -1;
1521
1522}
1523
1524/* End of HCI event callbacks */
1525
1526static gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data)
1527{
1528	int status, fd = g_io_channel_unix_get_fd(io);
1529	pid_t child_pid;
1530
1531	if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) {
1532		error("child_exit: unable to read child pid from pipe");
1533		return TRUE;
1534	}
1535
1536	if (waitpid(child_pid, &status, 0) != child_pid)
1537		error("waitpid(%d) failed", child_pid);
1538	else
1539		DBG("child %d exited", child_pid);
1540
1541	return TRUE;
1542}
1543
1544static void at_child_exit(void)
1545{
1546	pid_t pid = getpid();
1547
1548	if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid))
1549		error("unable to write to child pipe");
1550}
1551
1552static void device_devup_setup(int index)
1553{
1554	struct hci_dev_info di;
1555	uint16_t policy;
1556	read_stored_link_key_cp cp;
1557
1558	if (hci_devinfo(index, &di) < 0)
1559		return;
1560
1561	if (ignore_device(&di))
1562		return;
1563
1564	bacpy(&BDADDR(index), &di.bdaddr);
1565	memcpy(FEATURES(index), di.features, 8);
1566
1567	/* Set page timeout */
1568	if ((main_opts.flags & (1 << HCID_SET_PAGETO))) {
1569		write_page_timeout_cp cp;
1570
1571		cp.timeout = htobs(main_opts.pageto);
1572		hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT,
1573					WRITE_PAGE_TIMEOUT_CP_SIZE, &cp);
1574	}
1575
1576	/* Set default link policy */
1577	policy = htobs(main_opts.link_policy);
1578	hci_send_cmd(SK(index), OGF_LINK_POLICY,
1579				OCF_WRITE_DEFAULT_LINK_POLICY, 2, &policy);
1580
1581	bacpy(&cp.bdaddr, BDADDR_ANY);
1582	cp.read_all = 1;
1583	hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY,
1584			READ_STORED_LINK_KEY_CP_SIZE, (void *) &cp);
1585
1586	if (!PENDING(index))
1587		start_adapter(index);
1588}
1589
1590static void init_pending(int index)
1591{
1592	set_bit(PENDING_BDADDR, &PENDING(index));
1593	set_bit(PENDING_VERSION, &PENDING(index));
1594	set_bit(PENDING_FEATURES, &PENDING(index));
1595	set_bit(PENDING_NAME, &PENDING(index));
1596}
1597
1598static void init_device(int index)
1599{
1600	struct hci_dev_req dr;
1601	struct hci_dev_info di;
1602	int dd;
1603	pid_t pid;
1604
1605	dd = hci_open_dev(index);
1606	if (dd < 0) {
1607		error("Unable to open hci%d: %s (%d)", index,
1608						strerror(errno), errno);
1609		return;
1610	}
1611
1612	if (index > max_dev) {
1613		max_dev = index;
1614		devs = g_realloc(devs, sizeof(devs[0]) * (max_dev + 1));
1615	}
1616
1617	init_dev_info(index, dd);
1618	init_pending(index);
1619	start_hci_dev(index);
1620
1621	/* Do initialization in the separate process */
1622	pid = fork();
1623	switch (pid) {
1624		case 0:
1625			atexit(at_child_exit);
1626			break;
1627		case -1:
1628			error("Fork failed. Can't init device hci%d: %s (%d)",
1629					index, strerror(errno), errno);
1630		default:
1631			DBG("child %d forked", pid);
1632			return;
1633	}
1634
1635	memset(&dr, 0, sizeof(dr));
1636	dr.dev_id = index;
1637
1638	/* Set link mode */
1639	dr.dev_opt = main_opts.link_mode;
1640	if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0)
1641		error("Can't set link mode on hci%d: %s (%d)",
1642						index, strerror(errno), errno);
1643
1644	/* Set link policy for BR/EDR HCI devices */
1645	if (hci_devinfo(index, &di) < 0)
1646		goto fail;
1647
1648	if (!ignore_device(&di)) {
1649		dr.dev_opt = main_opts.link_policy;
1650		if (ioctl(dd, HCISETLINKPOL, (unsigned long) &dr) < 0 &&
1651							errno != ENETDOWN) {
1652			error("Can't set link policy on hci%d: %s (%d)",
1653						index, strerror(errno), errno);
1654		}
1655	}
1656
1657	/* Start HCI device */
1658	if (ioctl(dd, HCIDEVUP, index) < 0 && errno != EALREADY) {
1659		error("Can't init device hci%d: %s (%d)",
1660					index, strerror(errno), errno);
1661		goto fail;
1662	}
1663
1664	hci_close_dev(dd);
1665	exit(0);
1666
1667fail:
1668	hci_close_dev(dd);
1669	exit(1);
1670}
1671
1672static void device_devreg_setup(int index)
1673{
1674	struct hci_dev_info di;
1675	gboolean devup;
1676
1677	init_device(index);
1678
1679	memset(&di, 0, sizeof(di));
1680
1681	if (hci_devinfo(index, &di) < 0)
1682		return;
1683
1684	devup = hci_test_bit(HCI_UP, &di.flags);
1685
1686	if (!ignore_device(&di))
1687		manager_register_adapter(index, devup);
1688}
1689
1690static void device_event(int event, int index)
1691{
1692	switch (event) {
1693	case HCI_DEV_REG:
1694		info("HCI dev %d registered", index);
1695		device_devreg_setup(index);
1696		break;
1697
1698	case HCI_DEV_UNREG:
1699		info("HCI dev %d unregistered", index);
1700		stop_hci_dev(index);
1701		manager_unregister_adapter(index);
1702		break;
1703
1704	case HCI_DEV_UP:
1705		info("HCI dev %d up", index);
1706		UP(index) = TRUE;
1707		device_devup_setup(index);
1708		break;
1709
1710	case HCI_DEV_DOWN:
1711		info("HCI dev %d down", index);
1712		UP(index) = FALSE;
1713		if (!PENDING(index)) {
1714			manager_stop_adapter(index);
1715			init_pending(index);
1716		}
1717		break;
1718	}
1719}
1720
1721static gboolean init_known_adapters(gpointer user_data)
1722{
1723	struct hci_dev_list_req *dl;
1724	struct hci_dev_req *dr;
1725	int i, err, ctl = GPOINTER_TO_INT(user_data);
1726	size_t req_size;
1727
1728	req_size = HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t);
1729
1730	dl = g_try_malloc0(req_size);
1731	if (!dl) {
1732		error("Can't allocate devlist buffer");
1733		return FALSE;
1734	}
1735
1736	dl->dev_num = HCI_MAX_DEV;
1737	dr = dl->dev_req;
1738
1739	if (ioctl(ctl, HCIGETDEVLIST, dl) < 0) {
1740		err = -errno;
1741		error("Can't get device list: %s (%d)", strerror(-err), -err);
1742		g_free(dl);
1743		return FALSE;
1744	}
1745
1746	for (i = 0; i < dl->dev_num; i++, dr++) {
1747		device_event(HCI_DEV_REG, dr->dev_id);
1748
1749		if (!hci_test_bit(HCI_UP, &dr->dev_opt))
1750			continue;
1751
1752		PENDING(dr->dev_id) = 0;
1753		set_bit(PENDING_VERSION, &PENDING(dr->dev_id));
1754		hci_send_cmd(SK(dr->dev_id), OGF_INFO_PARAM,
1755					OCF_READ_LOCAL_VERSION, 0, NULL);
1756		device_event(HCI_DEV_UP, dr->dev_id);
1757	}
1758
1759	g_free(dl);
1760
1761	return FALSE;
1762}
1763
1764static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond,
1765								gpointer data)
1766{
1767	unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr;
1768	evt_stack_internal *si;
1769	evt_si_device *sd;
1770	hci_event_hdr *eh;
1771	int type;
1772	size_t len;
1773	GIOError err;
1774
1775	ptr = buf;
1776
1777	err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
1778	if (err) {
1779		if (err == G_IO_ERROR_AGAIN)
1780			return TRUE;
1781
1782		error("Read from control socket failed: %s (%d)",
1783						strerror(errno), errno);
1784		return FALSE;
1785	}
1786
1787	type = *ptr++;
1788
1789	if (type != HCI_EVENT_PKT)
1790		return TRUE;
1791
1792	eh = (hci_event_hdr *) ptr;
1793	if (eh->evt != EVT_STACK_INTERNAL)
1794		return TRUE;
1795
1796	ptr += HCI_EVENT_HDR_SIZE;
1797
1798	si = (evt_stack_internal *) ptr;
1799	switch (si->type) {
1800	case EVT_SI_DEVICE:
1801		sd = (void *) &si->data;
1802		device_event(sd->event, sd->dev_id);
1803		break;
1804	}
1805
1806	return TRUE;
1807}
1808
1809static int hciops_setup(void)
1810{
1811	struct sockaddr_hci addr;
1812	struct hci_filter flt;
1813	GIOChannel *ctl_io, *child_io;
1814	int sock, err;
1815
1816	if (child_pipe[0] != -1)
1817		return -EALREADY;
1818
1819	if (pipe(child_pipe) < 0) {
1820		err = -errno;
1821		error("pipe(): %s (%d)", strerror(-err), -err);
1822		return err;
1823	}
1824
1825	child_io = g_io_channel_unix_new(child_pipe[0]);
1826	g_io_channel_set_close_on_unref(child_io, TRUE);
1827	child_io_id = g_io_add_watch(child_io,
1828				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1829				child_exit, NULL);
1830	g_io_channel_unref(child_io);
1831
1832	/* Create and bind HCI socket */
1833	sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
1834	if (sock < 0) {
1835		err = -errno;
1836		error("Can't open HCI socket: %s (%d)", strerror(-err),
1837								-err);
1838		return err;
1839	}
1840
1841	/* Set filter */
1842	hci_filter_clear(&flt);
1843	hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
1844	hci_filter_set_event(EVT_STACK_INTERNAL, &flt);
1845	if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
1846		err = -errno;
1847		error("Can't set filter: %s (%d)", strerror(-err), -err);
1848		return err;
1849	}
1850
1851	memset(&addr, 0, sizeof(addr));
1852	addr.hci_family = AF_BLUETOOTH;
1853	addr.hci_dev = HCI_DEV_NONE;
1854	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1855		err = -errno;
1856		error("Can't bind HCI socket: %s (%d)", strerror(-err), -err);
1857		return err;
1858	}
1859
1860	ctl_io = g_io_channel_unix_new(sock);
1861	g_io_channel_set_close_on_unref(ctl_io, TRUE);
1862
1863	ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL);
1864
1865	g_io_channel_unref(ctl_io);
1866
1867	g_idle_add(init_known_adapters, GINT_TO_POINTER(sock));
1868
1869	return 0;
1870}
1871
1872static void hciops_cleanup(void)
1873{
1874	int i;
1875
1876	for (i = 0; i <= max_dev; i++) {
1877		if (SK(i) >= 0)
1878			hci_close_dev(SK(i));
1879	}
1880
1881	g_free(devs);
1882	devs = NULL;
1883	max_dev = -1;
1884
1885	if (child_io_id) {
1886		g_source_remove(child_io_id);
1887		child_io_id = 0;
1888	}
1889
1890	if (ctl_io_id) {
1891		g_source_remove(ctl_io_id);
1892		ctl_io_id = 0;
1893	}
1894
1895	if (child_pipe[0] >= 0) {
1896		close(child_pipe[0]);
1897		child_pipe[0] = -1;
1898	}
1899
1900	if (child_pipe[1] >= 0) {
1901		close(child_pipe[1]);
1902		child_pipe[1] = -1;
1903	}
1904}
1905
1906static int hciops_start(int index)
1907{
1908	int err;
1909
1910	if (ioctl(SK(index), HCIDEVUP, index) == 0)
1911		return 0;
1912
1913	if (errno == EALREADY)
1914		return 0;
1915
1916	err = -errno;
1917	error("Can't init device hci%d: %s (%d)",
1918					index, strerror(-err), -err);
1919
1920	return err;
1921}
1922
1923static int hciops_stop(int index)
1924{
1925	int err = 0;
1926
1927	if (ioctl(SK(index), HCIDEVDOWN, index) == 0)
1928		goto done; /* on success */
1929
1930	if (errno != EALREADY) {
1931		err = -errno;
1932		error("Can't stop device hci%d: %s (%d)",
1933				index, strerror(-err), -err);
1934	}
1935
1936done:
1937	return err;
1938}
1939
1940static int hciops_powered(int index, gboolean powered)
1941{
1942	uint8_t mode = SCAN_DISABLED;
1943
1944	if (powered)
1945		return hciops_start(index);
1946
1947	if (hci_send_cmd(SK(index), OGF_HOST_CTL,
1948					OCF_WRITE_SCAN_ENABLE, 1, &mode) < 0)
1949		return -errno;
1950
1951	return hciops_stop(index);
1952}
1953
1954static int hciops_connectable(int index)
1955{
1956	uint8_t mode = SCAN_PAGE;
1957
1958	if (hci_send_cmd(SK(index), OGF_HOST_CTL,
1959					OCF_WRITE_SCAN_ENABLE, 1, &mode) < 0)
1960		return -errno;
1961
1962	return 0;
1963}
1964
1965static int hciops_discoverable(int index)
1966{
1967	uint8_t mode = (SCAN_PAGE | SCAN_INQUIRY);
1968
1969	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,
1970								1, &mode) < 0)
1971		return -errno;
1972
1973	return 0;
1974}
1975
1976static int hciops_set_class(int index, uint32_t class)
1977{
1978	write_class_of_dev_cp cp;
1979
1980	memcpy(cp.dev_class, &class, 3);
1981
1982	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV,
1983					WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0)
1984		return -errno;
1985
1986	return 0;
1987}
1988
1989static int hciops_set_limited_discoverable(int index, uint32_t class,
1990							gboolean limited)
1991{
1992	int num = (limited ? 2 : 1);
1993	uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e };
1994	write_current_iac_lap_cp cp;
1995
1996	/*
1997	 * 1: giac
1998	 * 2: giac + liac
1999	 */
2000	memset(&cp, 0, sizeof(cp));
2001	cp.num_current_iac = num;
2002	memcpy(&cp.lap, lap, num * 3);
2003
2004	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP,
2005						(num * 3 + 1), &cp) < 0)
2006		return -errno;
2007
2008	return hciops_set_class(index, class);
2009}
2010
2011static int hciops_start_inquiry(int index, uint8_t length, gboolean periodic)
2012{
2013	uint8_t lap[3] = { 0x33, 0x8b, 0x9e };
2014	int err;
2015
2016	if (periodic) {
2017		periodic_inquiry_cp cp;
2018
2019		memset(&cp, 0, sizeof(cp));
2020		memcpy(&cp.lap, lap, 3);
2021		cp.max_period = htobs(24);
2022		cp.min_period = htobs(16);
2023		cp.length  = length;
2024		cp.num_rsp = 0x00;
2025
2026		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2027						OCF_PERIODIC_INQUIRY,
2028						PERIODIC_INQUIRY_CP_SIZE, &cp);
2029	} else {
2030		inquiry_cp inq_cp;
2031
2032		memset(&inq_cp, 0, sizeof(inq_cp));
2033		memcpy(&inq_cp.lap, lap, 3);
2034		inq_cp.length = length;
2035		inq_cp.num_rsp = 0x00;
2036
2037		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2038					OCF_INQUIRY, INQUIRY_CP_SIZE, &inq_cp);
2039	}
2040
2041	if (err < 0)
2042		err = -errno;
2043
2044	return err;
2045}
2046
2047static int hciops_stop_inquiry(int index)
2048{
2049	struct hci_dev_info di;
2050	int err;
2051
2052	if (hci_devinfo(index, &di) < 0)
2053		return -errno;
2054
2055	if (hci_test_bit(HCI_INQUIRY, &di.flags))
2056		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2057						OCF_INQUIRY_CANCEL, 0, 0);
2058	else
2059		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2060					OCF_EXIT_PERIODIC_INQUIRY, 0, 0);
2061	if (err < 0)
2062		err = -errno;
2063
2064	return err;
2065}
2066
2067static int le_set_scan_enable(int index, uint8_t enable)
2068{
2069	le_set_scan_enable_cp cp;
2070
2071	memset(&cp, 0, sizeof(cp));
2072	cp.enable = enable;
2073	cp.filter_dup = 0;
2074
2075	if (hci_send_cmd(SK(index), OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE,
2076				LE_SET_SCAN_ENABLE_CP_SIZE, &cp) < 0)
2077		return -errno;
2078
2079	return 0;
2080}
2081
2082static int hciops_start_scanning(int index)
2083{
2084	le_set_scan_parameters_cp cp;
2085
2086	memset(&cp, 0, sizeof(cp));
2087	cp.type = 0x01;			/* Active scanning */
2088	cp.interval = htobs(0x0010);
2089	cp.window = htobs(0x0010);
2090	cp.own_bdaddr_type = 0;		/* Public address */
2091	cp.filter = 0;			/* Accept all adv packets */
2092
2093	if (hci_send_cmd(SK(index), OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS,
2094				LE_SET_SCAN_PARAMETERS_CP_SIZE, &cp) < 0)
2095		return -errno;
2096
2097	return le_set_scan_enable(index, 1);
2098}
2099
2100static int hciops_stop_scanning(int index)
2101{
2102	return le_set_scan_enable(index, 0);
2103}
2104
2105static int hciops_resolve_name(int index, bdaddr_t *bdaddr)
2106{
2107	remote_name_req_cp cp;
2108
2109	memset(&cp, 0, sizeof(cp));
2110	bacpy(&cp.bdaddr, bdaddr);
2111	cp.pscan_rep_mode = 0x02;
2112
2113	if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_NAME_REQ,
2114					REMOTE_NAME_REQ_CP_SIZE, &cp) < 0)
2115		return -errno;
2116
2117	return 0;
2118}
2119
2120static int hciops_set_name(int index, const char *name)
2121{
2122	change_local_name_cp cp;
2123
2124	memset(&cp, 0, sizeof(cp));
2125	strncpy((char *) cp.name, name, sizeof(cp.name));
2126
2127	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME,
2128				CHANGE_LOCAL_NAME_CP_SIZE, &cp) < 0)
2129		return -errno;
2130
2131	return 0;
2132}
2133
2134static int hciops_cancel_resolve_name(int index, bdaddr_t *bdaddr)
2135{
2136	remote_name_req_cancel_cp cp;
2137
2138	memset(&cp, 0, sizeof(cp));
2139	bacpy(&cp.bdaddr, bdaddr);
2140
2141	if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL,
2142				REMOTE_NAME_REQ_CANCEL_CP_SIZE, &cp) < 0)
2143		return -errno;
2144
2145	return 0;
2146}
2147
2148static int hciops_fast_connectable(int index, gboolean enable)
2149{
2150	write_page_activity_cp cp;
2151	uint8_t type;
2152
2153	if (enable) {
2154		type = PAGE_SCAN_TYPE_INTERLACED;
2155		cp.interval = 0x0024;	/* 22.5 msec page scan interval */
2156	} else {
2157		type = PAGE_SCAN_TYPE_STANDARD;	/* default */
2158		cp.interval = 0x0800;	/* default 1.28 sec page scan */
2159	}
2160
2161	cp.window = 0x0012;	/* default 11.25 msec page scan window */
2162
2163	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY,
2164					WRITE_PAGE_ACTIVITY_CP_SIZE, &cp) < 0)
2165		return -errno;
2166	else if (hci_send_cmd(SK(index), OGF_HOST_CTL,
2167				OCF_WRITE_PAGE_SCAN_TYPE, 1, &type) < 0)
2168		return -errno;
2169
2170	return 0;
2171}
2172
2173static int hciops_read_clock(int index, int handle, int which, int timeout,
2174					uint32_t *clock, uint16_t *accuracy)
2175{
2176	if (hci_read_clock(SK(index), handle, which, clock, accuracy,
2177								timeout) < 0)
2178		return -errno;
2179
2180	return 0;
2181}
2182
2183static int hciops_conn_handle(int index, const bdaddr_t *bdaddr, int *handle)
2184{
2185	int err;
2186	struct hci_conn_info_req *cr;
2187
2188	cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info));
2189	bacpy(&cr->bdaddr, bdaddr);
2190	cr->type = ACL_LINK;
2191
2192	if (ioctl(SK(index), HCIGETCONNINFO, (unsigned long) cr) < 0) {
2193		err = -errno;
2194		goto fail;
2195	}
2196
2197	err = 0;
2198	*handle = htobs(cr->conn_info->handle);
2199
2200fail:
2201	g_free(cr);
2202	return err;
2203}
2204
2205static int hciops_write_eir_data(int index, uint8_t *data)
2206{
2207	write_ext_inquiry_response_cp cp;
2208
2209	memset(&cp, 0, sizeof(cp));
2210	memcpy(cp.data, data, 240);
2211
2212	if (hci_send_cmd(SK(index), OGF_HOST_CTL,
2213				OCF_WRITE_EXT_INQUIRY_RESPONSE,
2214				WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0)
2215		return -errno;
2216
2217	return 0;
2218}
2219
2220static int hciops_read_bdaddr(int index, bdaddr_t *bdaddr)
2221{
2222	bacpy(bdaddr, &BDADDR(index));
2223	return 0;
2224}
2225
2226static int hciops_block_device(int index, bdaddr_t *bdaddr)
2227{
2228	if (ioctl(SK(index), HCIBLOCKADDR, bdaddr) < 0)
2229		return -errno;
2230
2231	return 0;
2232}
2233
2234static int hciops_unblock_device(int index, bdaddr_t *bdaddr)
2235{
2236	if (ioctl(SK(index), HCIUNBLOCKADDR, bdaddr) < 0)
2237		return -errno;
2238
2239	return 0;
2240}
2241
2242static int hciops_get_conn_list(int index, GSList **conns)
2243{
2244	struct hci_conn_list_req *cl;
2245	struct hci_conn_info *ci;
2246	int err, i;
2247
2248	cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl));
2249
2250	cl->dev_id = index;
2251	cl->conn_num = 10;
2252	ci = cl->conn_info;
2253
2254	if (ioctl(SK(index), HCIGETCONNLIST, cl) < 0) {
2255		err = -errno;
2256		goto fail;
2257	}
2258
2259	err = 0;
2260	*conns = NULL;
2261
2262	for (i = 0; i < cl->conn_num; i++, ci++)
2263		*conns = g_slist_append(*conns, g_memdup(ci, sizeof(*ci)));
2264
2265fail:
2266	g_free(cl);
2267	return err;
2268}
2269
2270static int hciops_read_local_version(int index, struct hci_version *ver)
2271{
2272	memcpy(ver, &VER(index), sizeof(*ver));
2273	return 0;
2274}
2275
2276static int hciops_read_local_features(int index, uint8_t *features)
2277{
2278	memcpy(features, FEATURES(index), 8);
2279	return  0;
2280}
2281
2282static int hciops_read_local_ext_features(int index)
2283{
2284	uint8_t page_num = 1;
2285
2286	if (hci_send_cmd(SK(index), OGF_INFO_PARAM,
2287				OCF_READ_LOCAL_EXT_FEATURES, 1, &page_num) < 0)
2288		return -errno;
2289
2290	return 0;
2291}
2292
2293static int hciops_read_link_policy(int index)
2294{
2295	if (hci_send_cmd(SK(index), OGF_LINK_POLICY,
2296				OCF_READ_DEFAULT_LINK_POLICY, 0, NULL) < 0)
2297		return -errno;
2298
2299	return 0;
2300}
2301
2302static int hciops_disconnect(int index, uint16_t handle)
2303{
2304	disconnect_cp cp;
2305
2306	memset(&cp, 0, sizeof(cp));
2307	cp.handle = htobs(handle);
2308	cp.reason = HCI_OE_USER_ENDED_CONNECTION;
2309
2310	if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_DISCONNECT,
2311						DISCONNECT_CP_SIZE, &cp) < 0)
2312		return -errno;
2313
2314	return 0;
2315}
2316
2317static int hciops_remove_bonding(int index, bdaddr_t *bdaddr)
2318{
2319	delete_stored_link_key_cp cp;
2320
2321	memset(&cp, 0, sizeof(cp));
2322	bacpy(&cp.bdaddr, bdaddr);
2323
2324	/* Delete the link key from the Bluetooth chip */
2325	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_DELETE_STORED_LINK_KEY,
2326				DELETE_STORED_LINK_KEY_CP_SIZE, &cp) < 0)
2327		return -errno;
2328
2329	return 0;
2330}
2331
2332static int hciops_request_authentication(int index, uint16_t handle)
2333{
2334	auth_requested_cp cp;
2335
2336	DBG("");
2337
2338	memset(&cp, 0, sizeof(cp));
2339	cp.handle = htobs(handle);
2340
2341	if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_AUTH_REQUESTED,
2342					AUTH_REQUESTED_CP_SIZE, &cp) < 0)
2343		return -errno;
2344
2345	return 0;
2346}
2347
2348static int hciops_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin)
2349{
2350	int err;
2351
2352	if (pin) {
2353		pin_code_reply_cp pr;
2354		size_t len = strlen(pin);
2355
2356		PIN_LENGTH(index) = len;
2357
2358		memset(&pr, 0, sizeof(pr));
2359		bacpy(&pr.bdaddr, bdaddr);
2360		memcpy(pr.pin_code, pin, len);
2361		pr.pin_len = len;
2362		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2363						OCF_PIN_CODE_REPLY,
2364						PIN_CODE_REPLY_CP_SIZE, &pr);
2365	} else
2366		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2367					OCF_PIN_CODE_NEG_REPLY, 6, bdaddr);
2368
2369	if (err < 0)
2370		err = -errno;
2371
2372	return err;
2373}
2374
2375static int hciops_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success)
2376{
2377	int err;
2378	user_confirm_reply_cp cp;
2379
2380	memset(&cp, 0, sizeof(cp));
2381	bacpy(&cp.bdaddr, bdaddr);
2382
2383	if (success)
2384		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2385					OCF_USER_CONFIRM_REPLY,
2386					USER_CONFIRM_REPLY_CP_SIZE, &cp);
2387	else
2388		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2389					OCF_USER_CONFIRM_NEG_REPLY,
2390					USER_CONFIRM_REPLY_CP_SIZE, &cp);
2391
2392	if (err < 0)
2393		err = -errno;
2394
2395	return err;
2396}
2397
2398static int hciops_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey)
2399{
2400	int err;
2401
2402	if (passkey != INVALID_PASSKEY) {
2403		user_passkey_reply_cp cp;
2404
2405		memset(&cp, 0, sizeof(cp));
2406		bacpy(&cp.bdaddr, bdaddr);
2407		cp.passkey = passkey;
2408
2409		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2410					OCF_USER_PASSKEY_REPLY,
2411					USER_PASSKEY_REPLY_CP_SIZE, &cp);
2412	} else
2413		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
2414					OCF_USER_PASSKEY_NEG_REPLY, 6, bdaddr);
2415
2416	if (err < 0)
2417		err = -errno;
2418
2419	return err;
2420}
2421
2422static int hciops_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth)
2423{
2424	struct hci_auth_info_req req;
2425
2426	memset(&req, 0, sizeof(req));
2427	bacpy(&req.bdaddr, bdaddr);
2428
2429	if (ioctl(SK(index), HCIGETAUTHINFO, (unsigned long) &req) < 0)
2430		return -errno;
2431
2432	if (auth)
2433		*auth = req.type;
2434
2435	return 0;
2436}
2437
2438static int hciops_read_scan_enable(int index)
2439{
2440	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_READ_SCAN_ENABLE,
2441								0, NULL) < 0)
2442		return -errno;
2443
2444	return 0;
2445}
2446
2447static int hciops_write_le_host(int index, uint8_t le, uint8_t simul)
2448{
2449	write_le_host_supported_cp cp;
2450
2451	memset(&cp, 0, sizeof(cp));
2452	cp.le = le;
2453	cp.simul = simul;
2454
2455	if (hci_send_cmd(SK(index), OGF_HOST_CTL,
2456				OCF_WRITE_LE_HOST_SUPPORTED,
2457				WRITE_LE_HOST_SUPPORTED_CP_SIZE, &cp) < 0)
2458		return -errno;
2459
2460	return 0;
2461}
2462
2463struct remote_version_req {
2464	int index;
2465	uint16_t handle;
2466};
2467
2468static gboolean get_remote_version(gpointer user_data)
2469{
2470	struct remote_version_req *req = user_data;
2471	read_remote_version_cp cp;
2472
2473	memset(&cp, 0, sizeof(cp));
2474	cp.handle = htobs(req->handle);
2475
2476	hci_send_cmd(SK(req->index), OGF_LINK_CTL, OCF_READ_REMOTE_VERSION,
2477					READ_REMOTE_VERSION_CP_SIZE, &cp);
2478
2479	return FALSE;
2480}
2481
2482static int hciops_get_remote_version(int index, uint16_t handle,
2483							gboolean delayed)
2484{
2485	struct remote_version_req *req;
2486
2487	req = g_new0(struct remote_version_req, 1);
2488	req->handle = handle;
2489	req->index = index;
2490
2491	if (!delayed) {
2492		get_remote_version(req);
2493		g_free(req);
2494		return 0;
2495	}
2496
2497	g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 1, get_remote_version,
2498								req, g_free);
2499
2500	return 0;
2501}
2502
2503static struct btd_adapter_ops hci_ops = {
2504	.setup = hciops_setup,
2505	.cleanup = hciops_cleanup,
2506	.start = hciops_start,
2507	.stop = hciops_stop,
2508	.set_powered = hciops_powered,
2509	.set_connectable = hciops_connectable,
2510	.set_discoverable = hciops_discoverable,
2511	.set_limited_discoverable = hciops_set_limited_discoverable,
2512	.start_inquiry = hciops_start_inquiry,
2513	.stop_inquiry = hciops_stop_inquiry,
2514	.start_scanning = hciops_start_scanning,
2515	.stop_scanning = hciops_stop_scanning,
2516	.resolve_name = hciops_resolve_name,
2517	.cancel_resolve_name = hciops_cancel_resolve_name,
2518	.set_name = hciops_set_name,
2519	.set_class = hciops_set_class,
2520	.set_fast_connectable = hciops_fast_connectable,
2521	.read_clock = hciops_read_clock,
2522	.get_conn_handle = hciops_conn_handle,
2523	.write_eir_data = hciops_write_eir_data,
2524	.read_bdaddr = hciops_read_bdaddr,
2525	.block_device = hciops_block_device,
2526	.unblock_device = hciops_unblock_device,
2527	.get_conn_list = hciops_get_conn_list,
2528	.read_local_version = hciops_read_local_version,
2529	.read_local_features = hciops_read_local_features,
2530	.read_local_ext_features = hciops_read_local_ext_features,
2531	.read_link_policy = hciops_read_link_policy,
2532	.disconnect = hciops_disconnect,
2533	.remove_bonding = hciops_remove_bonding,
2534	.request_authentication = hciops_request_authentication,
2535	.pincode_reply = hciops_pincode_reply,
2536	.confirm_reply = hciops_confirm_reply,
2537	.passkey_reply = hciops_passkey_reply,
2538	.get_auth_info = hciops_get_auth_info,
2539	.read_scan_enable = hciops_read_scan_enable,
2540	.write_le_host = hciops_write_le_host,
2541	.get_remote_version = hciops_get_remote_version,
2542	.encrypt_link = hciops_encrypt_link,
2543};
2544
2545static int hciops_init(void)
2546{
2547	return btd_register_adapter_ops(&hci_ops, FALSE);
2548}
2549
2550static void hciops_exit(void)
2551{
2552	btd_adapter_cleanup_ops(&hci_ops);
2553}
2554
2555BLUETOOTH_PLUGIN_DEFINE(hciops, VERSION,
2556		BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit)
2557