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