hciops.c revision 55694454017b04a416931a81964bb695f48b3d93
194e91856179a268805256055ffd5155d1468b99cAlok Barsode/* 294e91856179a268805256055ffd5155d1468b99cAlok Barsode * 394e91856179a268805256055ffd5155d1468b99cAlok Barsode * BlueZ - Bluetooth protocol stack for Linux 494e91856179a268805256055ffd5155d1468b99cAlok Barsode * 59184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> 694e91856179a268805256055ffd5155d1468b99cAlok Barsode * 794e91856179a268805256055ffd5155d1468b99cAlok Barsode * This program is free software; you can redistribute it and/or modify 894e91856179a268805256055ffd5155d1468b99cAlok Barsode * it under the terms of the GNU General Public License as published by 994e91856179a268805256055ffd5155d1468b99cAlok Barsode * the Free Software Foundation; either version 2 of the License, or 1094e91856179a268805256055ffd5155d1468b99cAlok Barsode * (at your option) any later version. 1194e91856179a268805256055ffd5155d1468b99cAlok Barsode * 1294e91856179a268805256055ffd5155d1468b99cAlok Barsode * This program is distributed in the hope that it will be useful, 1394e91856179a268805256055ffd5155d1468b99cAlok Barsode * but WITHOUT ANY WARRANTY; without even the implied warranty of 1494e91856179a268805256055ffd5155d1468b99cAlok Barsode * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1594e91856179a268805256055ffd5155d1468b99cAlok Barsode * GNU General Public License for more details. 1694e91856179a268805256055ffd5155d1468b99cAlok Barsode * 1794e91856179a268805256055ffd5155d1468b99cAlok Barsode * You should have received a copy of the GNU General Public License 1894e91856179a268805256055ffd5155d1468b99cAlok Barsode * along with this program; if not, write to the Free Software 1994e91856179a268805256055ffd5155d1468b99cAlok Barsode * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2094e91856179a268805256055ffd5155d1468b99cAlok Barsode * 2194e91856179a268805256055ffd5155d1468b99cAlok Barsode */ 2294e91856179a268805256055ffd5155d1468b99cAlok Barsode 2394e91856179a268805256055ffd5155d1468b99cAlok Barsode#ifdef HAVE_CONFIG_H 2494e91856179a268805256055ffd5155d1468b99cAlok Barsode#include <config.h> 2594e91856179a268805256055ffd5155d1468b99cAlok Barsode#endif 26a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 27a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include <stdio.h> 28cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include <errno.h> 29a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include <unistd.h> 30a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include <stdlib.h> 31cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include <sys/types.h> 32cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include <sys/ioctl.h> 33a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include <sys/wait.h> 3494e91856179a268805256055ffd5155d1468b99cAlok Barsode 3594e91856179a268805256055ffd5155d1468b99cAlok Barsode#include <bluetooth/bluetooth.h> 36cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include <bluetooth/hci.h> 37cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include <bluetooth/hci_lib.h> 3894e91856179a268805256055ffd5155d1468b99cAlok Barsode 39cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include <glib.h> 40cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 41cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include "hcid.h" 42a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include "sdpd.h" 43a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include "adapter.h" 4494e91856179a268805256055ffd5155d1468b99cAlok Barsode#include "plugin.h" 45e891f7df6225c758da0d95f7554c6cc67f72f31eGustavo F. Padovan#include "log.h" 465288199788ecb17183d6517da3062cd94692a900Johan Hedberg#include "storage.h" 475288199788ecb17183d6517da3062cd94692a900Johan Hedberg#include "event.h" 485288199788ecb17183d6517da3062cd94692a900Johan Hedberg#include "device.h" 49a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include "manager.h" 50a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 515ade59881c2ee8b57116414dc21615c4c94afd92Claudio Takahasi#define HCI_REQ_TIMEOUT 5000 525ade59881c2ee8b57116414dc21615c4c94afd92Claudio Takahasi 5318e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedbergstatic int child_pipe[2] = { -1, -1 }; 5494e91856179a268805256055ffd5155d1468b99cAlok Barsode 558b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedbergstatic guint child_io_id = 0; 568b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedbergstatic guint ctl_io_id = 0; 578b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 58ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg#define SK(index) devs[(index)].sk 59a352058752e541539b09e55124d411a534cc14afJohan Hedberg#define BDADDR(index) devs[(index)].bdaddr 605a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg#define UP(index) devs[(index)].up 615a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg#define READY(index) devs[(index)].ready 6255694454017b04a416931a81964bb695f48b3d93Johan Hedberg#define CHANNEL(index) devs[(index)].channel 6355694454017b04a416931a81964bb695f48b3d93Johan Hedberg#define WATCH_ID(index) devs[(index)].watch_id 6455694454017b04a416931a81964bb695f48b3d93Johan Hedberg#define PIN_LENGTH(index) devs[(index)].pin_length 65ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg 666844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedbergstatic int max_dev = -1; 67ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedbergstatic struct dev_info { 68ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg int sk; 69a352058752e541539b09e55124d411a534cc14afJohan Hedberg bdaddr_t bdaddr; 705a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg gboolean up; 715a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg gboolean ready; 7255694454017b04a416931a81964bb695f48b3d93Johan Hedberg 7355694454017b04a416931a81964bb695f48b3d93Johan Hedberg GIOChannel *channel; 7455694454017b04a416931a81964bb695f48b3d93Johan Hedberg guint watch_id; 7555694454017b04a416931a81964bb695f48b3d93Johan Hedberg int pin_length; 76ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg} *devs = NULL; 77ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg 78db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedbergstatic int ignore_device(struct hci_dev_info *di) 79db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg{ 80db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg return hci_test_bit(HCI_RAW, &di->flags) || di->type >> 4 != HCI_BREDR; 81db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg} 82db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg 83ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedbergstatic void init_dev_info(int index, int sk) 84ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg{ 85ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg memset(&devs[index], 0, sizeof(struct dev_info)); 86ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg SK(index) = sk; 8755694454017b04a416931a81964bb695f48b3d93Johan Hedberg PIN_LENGTH(index) = -1; 88ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg} 896844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 90abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg/* Async HCI command handling with callback support */ 91abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 92abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergstruct hci_cmd_data { 93abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg bt_hci_result_t cb; 94abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t handle; 95abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t ocf; 96abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg gpointer caller_data; 97abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg}; 98abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 99abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergstatic gboolean hci_event_watch(GIOChannel *io, 100abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg GIOCondition cond, gpointer user_data) 101abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg{ 102abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg unsigned char buf[HCI_MAX_EVENT_SIZE], *body; 103abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_cmd_data *cmd = user_data; 104abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_cmd_status *evt_status; 105abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_auth_complete *evt_auth; 106abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_encrypt_change *evt_enc; 107abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_event_hdr *hdr; 108abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg set_conn_encrypt_cp cp; 109abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg int dd; 110abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t ocf; 111abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint8_t status = HCI_OE_POWER_OFF; 112abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 113abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (cond & G_IO_NVAL) { 114abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->cb(status, cmd->caller_data); 115abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return FALSE; 116abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 117abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 118abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (cond & (G_IO_ERR | G_IO_HUP)) 119abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 120abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 121abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg dd = g_io_channel_unix_get_fd(io); 122abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 123abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (read(dd, buf, sizeof(buf)) < 0) 124abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 125abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 126abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hdr = (hci_event_hdr *) (buf + 1); 127abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg body = buf + (1 + HCI_EVENT_HDR_SIZE); 128abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 129abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg switch (hdr->evt) { 130abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case EVT_CMD_STATUS: 131abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_status = (evt_cmd_status *) body; 132abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg ocf = cmd_opcode_ocf(evt_status->opcode); 133abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (ocf != cmd->ocf) 134abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 135abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg switch (ocf) { 136abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case OCF_AUTH_REQUESTED: 137abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case OCF_SET_CONN_ENCRYPT: 138abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_status->status != 0) { 139abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Baseband rejected command */ 140abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = evt_status->status; 141abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 142abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 143abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg break; 144abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg default: 145abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 146abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 147abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Wait for the next event */ 148abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 149abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case EVT_AUTH_COMPLETE: 150abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_auth = (evt_auth_complete *) body; 151abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_auth->handle != cmd->handle) { 152abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Skipping */ 153abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 154abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 155abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 156abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_auth->status != 0x00) { 157abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = evt_auth->status; 158abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Abort encryption */ 159abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 160abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 161abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 162abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg memset(&cp, 0, sizeof(cp)); 163abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cp.handle = cmd->handle; 164abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cp.encrypt = 1; 165abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 166abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->ocf = OCF_SET_CONN_ENCRYPT; 167abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 168abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, 169abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg SET_CONN_ENCRYPT_CP_SIZE, &cp) < 0) { 170abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = HCI_COMMAND_DISALLOWED; 171abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 172abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 173abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Wait for encrypt change event */ 174abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 175abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case EVT_ENCRYPT_CHANGE: 176abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_enc = (evt_encrypt_change *) body; 177abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_enc->handle != cmd->handle) 178abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 179abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 180abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Procedure finished: reporting status */ 181abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = evt_enc->status; 182abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg break; 183abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg default: 184abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Skipping */ 185abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 186abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 187abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 188abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergfailed: 189abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->cb(status, cmd->caller_data); 190abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_shutdown(io, TRUE, NULL); 191abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 192abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return FALSE; 193abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg} 194abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 195abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergstatic int hciops_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb, 196abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg gpointer user_data) 197abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg{ 198abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg GIOChannel *io; 199abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_cmd_data *cmd; 200abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_conn_info_req *cr; 201abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg auth_requested_cp cp; 202abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_filter nf; 203abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg int dd, err; 204abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint32_t link_mode; 205abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t handle; 206abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 207abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info)); 208abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cr->type = ACL_LINK; 209abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg bacpy(&cr->bdaddr, dst); 210abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 211abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg err = ioctl(SK(index), HCIGETCONNINFO, cr); 212abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg link_mode = cr->conn_info->link_mode; 213abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg handle = cr->conn_info->handle; 214abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_free(cr); 215abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 216abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (err < 0) 217abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return -errno; 218abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 219abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (link_mode & HCI_LM_ENCRYPT) 220abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return -EALREADY; 221abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 222abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg memset(&cp, 0, sizeof(cp)); 223abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cp.handle = htobs(handle); 224abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 225abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_AUTH_REQUESTED, 226abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg AUTH_REQUESTED_CP_SIZE, &cp) < 0) 227abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return -errno; 228abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 229abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg dd = dup(SK(index)); 230abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (dd < 0) 231abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return -errno; 232abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 233abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd = g_new0(struct hci_cmd_data, 1); 234abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->handle = handle; 235abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->ocf = OCF_AUTH_REQUESTED; 236abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->cb = cb; 237abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->caller_data = user_data; 238abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 239abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_clear(&nf); 240abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_ptype(HCI_EVENT_PKT, &nf); 241abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_CMD_STATUS, &nf); 242abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_AUTH_COMPLETE, &nf); 243abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_ENCRYPT_CHANGE, &nf); 244abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 245abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { 246abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg err = -errno; 247abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_free(cmd); 248abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg close(dd); 249abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return -err; 250abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 251abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 252abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg io = g_io_channel_unix_new(dup(SK(index))); 253abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_set_close_on_unref(io, FALSE); 254abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_add_watch_full(io, G_PRIORITY_DEFAULT, 255abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg G_IO_HUP | G_IO_ERR | G_IO_NVAL | G_IO_IN, 256abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_event_watch, cmd, g_free); 257abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_unref(io); 258abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 259abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return 0; 260abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg} 261abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 262abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg/* End async HCI command handling */ 263abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 2645288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Start of HCI event callbacks */ 2655288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2665288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic int get_handle(int dev, bdaddr_t *sba, bdaddr_t *dba, uint16_t *handle) 2675288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2685288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_conn_list_req *cl; 2695288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_conn_info *ci; 2705288199788ecb17183d6517da3062cd94692a900Johan Hedberg char addr[18]; 2715288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 2725288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2735288199788ecb17183d6517da3062cd94692a900Johan Hedberg cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); 2745288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2755288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, addr); 2765288199788ecb17183d6517da3062cd94692a900Johan Hedberg cl->dev_id = hci_devid(addr); 2775288199788ecb17183d6517da3062cd94692a900Johan Hedberg cl->conn_num = 10; 2785288199788ecb17183d6517da3062cd94692a900Johan Hedberg ci = cl->conn_info; 2795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2805288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (ioctl(dev, HCIGETCONNLIST, (void *) cl) < 0) { 2815288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cl); 2825288199788ecb17183d6517da3062cd94692a900Johan Hedberg return -EIO; 2835288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 2845288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2855288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < cl->conn_num; i++, ci++) { 2865288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (bacmp(&ci->bdaddr, dba) == 0) { 2875288199788ecb17183d6517da3062cd94692a900Johan Hedberg *handle = ci->handle; 2885288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cl); 2895288199788ecb17183d6517da3062cd94692a900Johan Hedberg return 0; 2905288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 2915288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 2925288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2935288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cl); 2945288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2955288199788ecb17183d6517da3062cd94692a900Johan Hedberg return -ENOENT; 2965288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 2975288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2985288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline int get_bdaddr(int dev, bdaddr_t *sba, uint16_t handle, bdaddr_t *dba) 2995288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 3005288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_conn_list_req *cl; 3015288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_conn_info *ci; 3025288199788ecb17183d6517da3062cd94692a900Johan Hedberg char addr[18]; 3035288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 3045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3055288199788ecb17183d6517da3062cd94692a900Johan Hedberg cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); 3065288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3075288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, addr); 3085288199788ecb17183d6517da3062cd94692a900Johan Hedberg cl->dev_id = hci_devid(addr); 3095288199788ecb17183d6517da3062cd94692a900Johan Hedberg cl->conn_num = 10; 3105288199788ecb17183d6517da3062cd94692a900Johan Hedberg ci = cl->conn_info; 3115288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3125288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (ioctl(dev, HCIGETCONNLIST, (void *) cl) < 0) { 3135288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cl); 3145288199788ecb17183d6517da3062cd94692a900Johan Hedberg return -EIO; 3155288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 3165288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3175288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < cl->conn_num; i++, ci++) 3185288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (ci->handle == handle) { 3195288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(dba, &ci->bdaddr); 3205288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cl); 3215288199788ecb17183d6517da3062cd94692a900Johan Hedberg return 0; 3225288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 3235288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3245288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cl); 3255288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3265288199788ecb17183d6517da3062cd94692a900Johan Hedberg return -ENOENT; 3275288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 3285288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3295288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void update_lastseen(bdaddr_t *sba, bdaddr_t *dba) 3305288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 3315288199788ecb17183d6517da3062cd94692a900Johan Hedberg time_t t; 3325288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct tm *tm; 3335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3345288199788ecb17183d6517da3062cd94692a900Johan Hedberg t = time(NULL); 3355288199788ecb17183d6517da3062cd94692a900Johan Hedberg tm = gmtime(&t); 3365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3375288199788ecb17183d6517da3062cd94692a900Johan Hedberg write_lastseen_info(sba, dba, tm); 3385288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 3395288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3405288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void update_lastused(bdaddr_t *sba, bdaddr_t *dba) 3415288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 3425288199788ecb17183d6517da3062cd94692a900Johan Hedberg time_t t; 3435288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct tm *tm; 3445288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3455288199788ecb17183d6517da3062cd94692a900Johan Hedberg t = time(NULL); 3465288199788ecb17183d6517da3062cd94692a900Johan Hedberg tm = gmtime(&t); 3475288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3485288199788ecb17183d6517da3062cd94692a900Johan Hedberg write_lastused_info(sba, dba, tm); 3495288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 3505288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3515288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Link Key handling */ 3525288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3535288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba) 3545288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 3555288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 3565288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_device *device; 3575288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_auth_info_req req; 3585288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char key[16]; 3595288199788ecb17183d6517da3062cd94692a900Johan Hedberg char sa[18], da[18]; 3605288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t type; 3615288199788ecb17183d6517da3062cd94692a900Johan Hedberg int err; 3625288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3635288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, sa); ba2str(dba, da); 3645288199788ecb17183d6517da3062cd94692a900Johan Hedberg info("link_key_request (sba=%s, dba=%s)", sa, da); 3655288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3665288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter = manager_find_adapter(sba); 3675288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (adapter) 3685288199788ecb17183d6517da3062cd94692a900Johan Hedberg device = adapter_find_device(adapter, da); 3695288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 3705288199788ecb17183d6517da3062cd94692a900Johan Hedberg device = NULL; 3715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3725288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&req, 0, sizeof(req)); 3735288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&req.bdaddr, dba); 3745288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3755288199788ecb17183d6517da3062cd94692a900Johan Hedberg err = ioctl(dev, HCIGETAUTHINFO, (unsigned long) &req); 3765288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (err < 0) { 3775288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (errno != EINVAL) 3785288199788ecb17183d6517da3062cd94692a900Johan Hedberg DBG("HCIGETAUTHINFO failed %s (%d)", 3795288199788ecb17183d6517da3062cd94692a900Johan Hedberg strerror(errno), errno); 3805288199788ecb17183d6517da3062cd94692a900Johan Hedberg req.type = 0x00; 3815288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 3825288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3835288199788ecb17183d6517da3062cd94692a900Johan Hedberg DBG("kernel auth requirements = 0x%02x", req.type); 3845288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3855288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (main_opts.debug_keys && device && device_get_debug_key(device, key)) 3865288199788ecb17183d6517da3062cd94692a900Johan Hedberg type = 0x03; 3875288199788ecb17183d6517da3062cd94692a900Johan Hedberg else if (read_link_key(sba, dba, key, &type) < 0 || type == 0x03) { 3885288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Link key not found */ 3895288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 6, dba); 3905288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 3915288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 3925288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3935288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Link key found */ 3945288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3955288199788ecb17183d6517da3062cd94692a900Johan Hedberg DBG("link key type = 0x%02x", type); 3965288199788ecb17183d6517da3062cd94692a900Johan Hedberg 3975288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Don't use unauthenticated combination keys if MITM is 3985288199788ecb17183d6517da3062cd94692a900Johan Hedberg * required */ 3995288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (type == 0x04 && req.type != 0xff && (req.type & 0x01)) 4005288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 4015288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6, dba); 4025288199788ecb17183d6517da3062cd94692a900Johan Hedberg else { 4035288199788ecb17183d6517da3062cd94692a900Johan Hedberg link_key_reply_cp lr; 4045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4055288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(lr.link_key, key, 16); 4065288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&lr.bdaddr, dba); 4075288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4085288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_REPLY, 4095288199788ecb17183d6517da3062cd94692a900Johan Hedberg LINK_KEY_REPLY_CP_SIZE, &lr); 4105288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 4115288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 4125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4135288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void link_key_notify(int dev, bdaddr_t *sba, void *ptr) 4145288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 4155288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_link_key_notify *evt = ptr; 4165288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t *dba = &evt->bdaddr; 4175288199788ecb17183d6517da3062cd94692a900Johan Hedberg char sa[18], da[18]; 4185288199788ecb17183d6517da3062cd94692a900Johan Hedberg int dev_id, err; 4195288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char old_key[16]; 4205288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t old_key_type; 4215288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4225288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, sa); ba2str(dba, da); 4235288199788ecb17183d6517da3062cd94692a900Johan Hedberg info("link_key_notify (sba=%s, dba=%s, type=%d)", sa, da, 4245288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt->key_type); 4255288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4265288199788ecb17183d6517da3062cd94692a900Johan Hedberg err = read_link_key(sba, dba, old_key, &old_key_type); 4275288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (err < 0) 4285288199788ecb17183d6517da3062cd94692a900Johan Hedberg old_key_type = 0xff; 4295288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4305288199788ecb17183d6517da3062cd94692a900Johan Hedberg dev_id = hci_devid(sa); 4315288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (dev_id < 0) 4325288199788ecb17183d6517da3062cd94692a900Johan Hedberg err = -errno; 4335288199788ecb17183d6517da3062cd94692a900Johan Hedberg else { 4345288199788ecb17183d6517da3062cd94692a900Johan Hedberg err = btd_event_link_key_notify(sba, dba, evt->link_key, 4355288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt->key_type, 43655694454017b04a416931a81964bb695f48b3d93Johan Hedberg PIN_LENGTH(dev_id), 4375288199788ecb17183d6517da3062cd94692a900Johan Hedberg old_key_type); 43855694454017b04a416931a81964bb695f48b3d93Johan Hedberg PIN_LENGTH(dev_id) = -1; 4395288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 4405288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4415288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (err < 0) { 4425288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint16_t handle; 4435288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4445288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (err == -ENODEV) 4455288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_bonding_process_complete(sba, dba, 4465288199788ecb17183d6517da3062cd94692a900Johan Hedberg HCI_OE_LOW_RESOURCES); 4475288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 4485288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_bonding_process_complete(sba, dba, 4495288199788ecb17183d6517da3062cd94692a900Johan Hedberg HCI_MEMORY_FULL); 4505288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4515288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (get_handle(dev, sba, dba, &handle) == 0) { 4525288199788ecb17183d6517da3062cd94692a900Johan Hedberg disconnect_cp cp; 4535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4545288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&cp, 0, sizeof(cp)); 4555288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.handle = htobs(handle); 4565288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.reason = HCI_OE_LOW_RESOURCES; 4575288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4585288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_DISCONNECT, 4595288199788ecb17183d6517da3062cd94692a900Johan Hedberg DISCONNECT_CP_SIZE, &cp); 4605288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 4615288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 4625288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 4635288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4645288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void return_link_keys(int dev, bdaddr_t *sba, void *ptr) 4655288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 4665288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_return_link_keys *evt = ptr; 4675288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = evt->num_keys; 4685288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char key[16]; 4695288199788ecb17183d6517da3062cd94692a900Johan Hedberg char sa[18], da[18]; 4705288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t dba; 4715288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 4725288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4735288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, sa); 4745288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr++; 4755288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4765288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 4775288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&dba, ptr); ba2str(&dba, da); 4785288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(key, ptr + 6, 16); 4795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4805288199788ecb17183d6517da3062cd94692a900Johan Hedberg info("return_link_keys (sba=%s, dba=%s)", sa, da); 4815288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4825288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_returned_link_key(sba, &dba); 4835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4845288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += 22; 4855288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 4865288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 4875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4885288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Simple Pairing handling */ 4895288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4905288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void user_confirm_request(int dev, bdaddr_t *sba, void *ptr) 4915288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 4925288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_confirm_request *req = ptr; 4935288199788ecb17183d6517da3062cd94692a900Johan Hedberg 4945288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (btd_event_user_confirm(sba, &req->bdaddr, 4955288199788ecb17183d6517da3062cd94692a900Johan Hedberg btohl(req->passkey)) < 0) 4965288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, 4975288199788ecb17183d6517da3062cd94692a900Johan Hedberg OCF_USER_CONFIRM_NEG_REPLY, 6, ptr); 4985288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 4995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5005288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void user_passkey_request(int dev, bdaddr_t *sba, void *ptr) 5015288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 5025288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_passkey_request *req = ptr; 5035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5045288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (btd_event_user_passkey(sba, &req->bdaddr) < 0) 5055288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, 5065288199788ecb17183d6517da3062cd94692a900Johan Hedberg OCF_USER_PASSKEY_NEG_REPLY, 6, ptr); 5075288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 5085288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5095288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void user_passkey_notify(int dev, bdaddr_t *sba, void *ptr) 5105288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 5115288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_passkey_notify *req = ptr; 5125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5135288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_user_notify(sba, &req->bdaddr, btohl(req->passkey)); 5145288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 5155288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5165288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void remote_oob_data_request(int dev, bdaddr_t *sba, void *ptr) 5175288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 5185288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, ptr); 5195288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 5205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5215288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void io_capa_request(int dev, bdaddr_t *sba, bdaddr_t *dba) 5225288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 5235288199788ecb17183d6517da3062cd94692a900Johan Hedberg char sa[18], da[18]; 5245288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t cap, auth; 5255288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5265288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, sa); ba2str(dba, da); 5275288199788ecb17183d6517da3062cd94692a900Johan Hedberg info("io_capa_request (sba=%s, dba=%s)", sa, da); 5285288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5295288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (btd_event_get_io_cap(sba, dba, &cap, &auth) < 0) { 5305288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capability_neg_reply_cp cp; 5315288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&cp, 0, sizeof(cp)); 5325288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&cp.bdaddr, dba); 5335288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.reason = HCI_PAIRING_NOT_ALLOWED; 5345288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_IO_CAPABILITY_NEG_REPLY, 5355288199788ecb17183d6517da3062cd94692a900Johan Hedberg IO_CAPABILITY_NEG_REPLY_CP_SIZE, &cp); 5365288199788ecb17183d6517da3062cd94692a900Johan Hedberg } else { 5375288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capability_reply_cp cp; 5385288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&cp, 0, sizeof(cp)); 5395288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&cp.bdaddr, dba); 5405288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.capability = cap; 5415288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.oob_data = 0x00; 5425288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.authentication = auth; 5435288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY, 5445288199788ecb17183d6517da3062cd94692a900Johan Hedberg IO_CAPABILITY_REPLY_CP_SIZE, &cp); 5455288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 5465288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 5475288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5485288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void io_capa_response(int dev, bdaddr_t *sba, void *ptr) 5495288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 5505288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_io_capability_response *evt = ptr; 5515288199788ecb17183d6517da3062cd94692a900Johan Hedberg char sa[18], da[18]; 5525288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5535288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, sa); ba2str(&evt->bdaddr, da); 5545288199788ecb17183d6517da3062cd94692a900Johan Hedberg info("io_capa_response (sba=%s, dba=%s)", sa, da); 5555288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5565288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_set_io_cap(sba, &evt->bdaddr, 5575288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt->capability, evt->authentication); 5585288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 5595288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5605288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* PIN code handling */ 5615288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5625288199788ecb17183d6517da3062cd94692a900Johan Hedbergvoid set_pin_length(bdaddr_t *sba, int length) 5635288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 5645288199788ecb17183d6517da3062cd94692a900Johan Hedberg char addr[18]; 5655288199788ecb17183d6517da3062cd94692a900Johan Hedberg int dev_id; 5665288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5675288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, addr); 5685288199788ecb17183d6517da3062cd94692a900Johan Hedberg dev_id = hci_devid(addr); 5695288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5705288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (dev_id >= 0) 57155694454017b04a416931a81964bb695f48b3d93Johan Hedberg PIN_LENGTH(dev_id) = length; 5725288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 5735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5745288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void pin_code_request(int dev, bdaddr_t *sba, bdaddr_t *dba) 5755288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 5765288199788ecb17183d6517da3062cd94692a900Johan Hedberg pin_code_reply_cp pr; 5775288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_conn_info_req *cr; 5785288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_conn_info *ci; 5795288199788ecb17183d6517da3062cd94692a900Johan Hedberg char sa[18], da[18], pin[17]; 5805288199788ecb17183d6517da3062cd94692a900Johan Hedberg int pinlen; 5815288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5825288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&pr, 0, sizeof(pr)); 5835288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&pr.bdaddr, dba); 5845288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5855288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, sa); ba2str(dba, da); 5865288199788ecb17183d6517da3062cd94692a900Johan Hedberg info("pin_code_request (sba=%s, dba=%s)", sa, da); 5875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5885288199788ecb17183d6517da3062cd94692a900Johan Hedberg cr = g_malloc0(sizeof(*cr) + sizeof(*ci)); 5895288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5905288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&cr->bdaddr, dba); 5915288199788ecb17183d6517da3062cd94692a900Johan Hedberg cr->type = ACL_LINK; 5925288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (ioctl(dev, HCIGETCONNINFO, (unsigned long) cr) < 0) { 5935288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Can't get conn info: %s (%d)", strerror(errno), errno); 5945288199788ecb17183d6517da3062cd94692a900Johan Hedberg goto reject; 5955288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 5965288199788ecb17183d6517da3062cd94692a900Johan Hedberg ci = cr->conn_info; 5975288199788ecb17183d6517da3062cd94692a900Johan Hedberg 5985288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(pin, 0, sizeof(pin)); 5995288199788ecb17183d6517da3062cd94692a900Johan Hedberg pinlen = read_pin_code(sba, dba, pin); 6005288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6015288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (pinlen > 0) { 6025288199788ecb17183d6517da3062cd94692a900Johan Hedberg set_pin_length(sba, pinlen); 6035288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(pr.pin_code, pin, pinlen); 6045288199788ecb17183d6517da3062cd94692a900Johan Hedberg pr.pin_len = pinlen; 6055288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, 6065288199788ecb17183d6517da3062cd94692a900Johan Hedberg PIN_CODE_REPLY_CP_SIZE, &pr); 6075288199788ecb17183d6517da3062cd94692a900Johan Hedberg } else { 6085288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Request PIN from passkey agent */ 6095288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (btd_event_request_pin(dev, sba, ci) < 0) 6105288199788ecb17183d6517da3062cd94692a900Johan Hedberg goto reject; 6115288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 6125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6135288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cr); 6145288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6155288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 6165288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6175288199788ecb17183d6517da3062cd94692a900Johan Hedbergreject: 6185288199788ecb17183d6517da3062cd94692a900Johan Hedberg g_free(cr); 6195288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6205288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba); 6215288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 6225288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6235288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void start_inquiry(bdaddr_t *local, uint8_t status, gboolean periodic) 6245288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 6255288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 6265288199788ecb17183d6517da3062cd94692a900Johan Hedberg int state; 6275288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6285288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Don't send the signal if the cmd failed */ 6295288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (status) { 6305288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Inquiry Failed with status 0x%02x", status); 6315288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 6325288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 6335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6345288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter = manager_find_adapter(local); 6355288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 6365288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Unable to find matching adapter"); 6375288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 6385288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 6395288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6405288199788ecb17183d6517da3062cd94692a900Johan Hedberg state = adapter_get_state(adapter); 6415288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6425288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (periodic) 6435288199788ecb17183d6517da3062cd94692a900Johan Hedberg state |= STATE_PINQ; 6445288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 6455288199788ecb17183d6517da3062cd94692a900Johan Hedberg state |= STATE_STDINQ; 6465288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6475288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_set_state(adapter, state); 6485288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 6495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6505288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void inquiry_complete(bdaddr_t *local, uint8_t status, gboolean periodic) 6515288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 6525288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 6535288199788ecb17183d6517da3062cd94692a900Johan Hedberg int state; 6545288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6555288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Don't send the signal if the cmd failed */ 6565288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (status) { 6575288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Inquiry Failed with status 0x%02x", status); 6585288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 6595288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 6605288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6615288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter = manager_find_adapter(local); 6625288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 6635288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Unable to find matching adapter"); 6645288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 6655288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 6665288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6675288199788ecb17183d6517da3062cd94692a900Johan Hedberg state = adapter_get_state(adapter); 6685288199788ecb17183d6517da3062cd94692a900Johan Hedberg state &= ~(STATE_STDINQ | STATE_PINQ); 6695288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_set_state(adapter, state); 6705288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 6715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6725288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void remote_features_notify(int dev, bdaddr_t *sba, void *ptr) 6735288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 6745288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_remote_host_features_notify *evt = ptr; 6755288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6765288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->features[0] & 0x01) 6775288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_set_legacy_pairing(sba, &evt->bdaddr, FALSE); 6785288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 6795288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_set_legacy_pairing(sba, &evt->bdaddr, TRUE); 6805288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6815288199788ecb17183d6517da3062cd94692a900Johan Hedberg write_features_info(sba, &evt->bdaddr, NULL, evt->features); 6825288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 6835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6845288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void write_le_host_complete(bdaddr_t *sba, uint8_t status) 6855288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 6865288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 6875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6885288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (status) 6895288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 6905288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6915288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter = manager_find_adapter(sba); 6925288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 6935288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("No matching adapter found"); 6945288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 6955288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 6965288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6975288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_adapter_read_local_ext_features(adapter); 6985288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 6995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7005288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void read_local_ext_features_complete(bdaddr_t *sba, 7015288199788ecb17183d6517da3062cd94692a900Johan Hedberg const read_local_ext_features_rp *rp) 7025288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 7035288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 7045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7055288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (rp->status) 7065288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 7075288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7085288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter = manager_find_adapter(sba); 7095288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 7105288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("No matching adapter found"); 7115288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 7125288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 7135288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7145288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Local Extended feature page number is 1 */ 7155288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (rp->page_num != 1) 7165288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 7175288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7185288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_adapter_update_local_ext_features(adapter, rp->features); 7195288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 7205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7215a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedbergstatic void read_bd_addr_complete(int index, read_bd_addr_rp *rp) 7225a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg{ 7235a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg if (rp->status) 7245a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg return; 7255a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 7265a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg bacpy(&BDADDR(index), &rp->bdaddr); 7275a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 7285a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg if (READY(index)) 7295a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg return; 7305a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 7315a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg READY(index) = TRUE; 7325a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 7335a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg info("Got bdaddr for hci%d", index); 7345a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 73555694454017b04a416931a81964bb695f48b3d93Johan Hedberg if (UP(index)) 73655694454017b04a416931a81964bb695f48b3d93Johan Hedberg manager_start_adapter(index); 7375a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg} 7385a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 7395288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void cmd_status(int dev, bdaddr_t *sba, void *ptr) 7405288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 7415288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_status *evt = ptr; 7425288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint16_t opcode = btohs(evt->opcode); 7435288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7445288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY)) 7455288199788ecb17183d6517da3062cd94692a900Johan Hedberg start_inquiry(sba, evt->status, FALSE); 7465288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 7475288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7485288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic void read_scan_complete(bdaddr_t *sba, uint8_t status, void *ptr) 7495288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 7505288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 7515288199788ecb17183d6517da3062cd94692a900Johan Hedberg read_scan_enable_rp *rp = ptr; 7525288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7535288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter = manager_find_adapter(sba); 7545288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7555288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 7565288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Unable to find matching adapter"); 7575288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 7585288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 7595288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7605288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_mode_changed(adapter, rp->enable); 7615288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 7625288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7635a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedbergstatic inline void cmd_complete(int index, bdaddr_t *sba, void *ptr) 7645288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 7655288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_complete *evt = ptr; 7665288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint16_t opcode = btohs(evt->opcode); 7675288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t status = *((uint8_t *) ptr + EVT_CMD_COMPLETE_SIZE); 7685288199788ecb17183d6517da3062cd94692a900Johan Hedberg 7695288199788ecb17183d6517da3062cd94692a900Johan Hedberg switch (opcode) { 7705288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_EXT_FEATURES): 7715288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 7725288199788ecb17183d6517da3062cd94692a900Johan Hedberg read_local_ext_features_complete(sba, ptr); 7735288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7745a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BD_ADDR): 7755a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg ptr += sizeof(evt_cmd_complete); 7765a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg read_bd_addr_complete(index, ptr); 7775a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg break; 7785288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LINK_CTL, OCF_PERIODIC_INQUIRY): 7795288199788ecb17183d6517da3062cd94692a900Johan Hedberg start_inquiry(sba, status, TRUE); 7805288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7815288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LINK_CTL, OCF_EXIT_PERIODIC_INQUIRY): 7825288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_complete(sba, status, TRUE); 7835288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7845288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL): 7855288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_complete(sba, status, FALSE); 7865288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7875288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_LE_HOST_SUPPORTED): 7885288199788ecb17183d6517da3062cd94692a900Johan Hedberg write_le_host_complete(sba, status); 7895288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7905288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE): 7915288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_le_set_scan_enable_complete(sba, status); 7925288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7935288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME): 7945288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_setname_complete(sba, status); 7955288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7965288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE): 7975288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_setscan_enable_complete(sba); 7985288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 7995288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SCAN_ENABLE): 8005288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 8015288199788ecb17183d6517da3062cd94692a900Johan Hedberg read_scan_complete(sba, status, ptr); 8025288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 8035288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV): 8045288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_set_class_complete(sba, status); 8055288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 8065288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SIMPLE_PAIRING_MODE): 8075288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_write_simple_pairing_mode_complete(sba); 8085288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 8095288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SIMPLE_PAIRING_MODE): 8105288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 8115288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_read_simple_pairing_mode_complete(sba, ptr); 8125288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 8135288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_NAME): 8145288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 8155288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_update_local_name(sba, status, ptr); 8165288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 8175288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL): 8185288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 8195288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_update_tx_power(sba, status, ptr); 8205288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 8215288199788ecb17183d6517da3062cd94692a900Johan Hedberg }; 8225288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8235288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8245288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void remote_name_information(int dev, bdaddr_t *sba, void *ptr) 8255288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 8265288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_remote_name_req_complete *evt = ptr; 8275288199788ecb17183d6517da3062cd94692a900Johan Hedberg char name[MAX_NAME_LENGTH + 1]; 8285288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8295288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(name, 0, sizeof(name)); 8305288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8315288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!evt->status) 8325288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(name, evt->name, MAX_NAME_LENGTH); 8335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8345288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_remote_name(sba, &evt->bdaddr, evt->status, name); 8355288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8375288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void remote_version_information(int dev, bdaddr_t *sba, void *ptr) 8385288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 8395288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_read_remote_version_complete *evt = ptr; 8405288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t dba; 8415288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8425288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->status) 8435288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 8445288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8455288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (get_bdaddr(dev, sba, btohs(evt->handle), &dba) < 0) 8465288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 8475288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8485288199788ecb17183d6517da3062cd94692a900Johan Hedberg write_version_info(sba, &dba, btohs(evt->manufacturer), 8495288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt->lmp_ver, btohs(evt->lmp_subver)); 8505288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8515288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8525288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void inquiry_result(int dev, bdaddr_t *sba, int plen, void *ptr) 8535288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 8545288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 8555288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 8565288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8575288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 8585288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info *info = ptr; 8595288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 8605288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[1] << 8) 8615288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[2] << 16); 8625288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8635288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_inquiry_result(sba, &info->bdaddr, class, 0, NULL); 8645288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8655288199788ecb17183d6517da3062cd94692a900Johan Hedberg update_lastseen(sba, &info->bdaddr); 8665288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8675288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_SIZE; 8685288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 8695288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8705288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8715288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void inquiry_result_with_rssi(int dev, bdaddr_t *sba, 8725288199788ecb17183d6517da3062cd94692a900Johan Hedberg int plen, void *ptr) 8735288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 8745288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 8755288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 8765288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8775288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!num) 8785288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 8795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8805288199788ecb17183d6517da3062cd94692a900Johan Hedberg if ((plen - 1) / num == INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE) { 8815288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 8825288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info_with_rssi_and_pscan_mode *info = ptr; 8835288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 8845288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[1] << 8) 8855288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[2] << 16); 8865288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8875288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_inquiry_result(sba, &info->bdaddr, 8885288199788ecb17183d6517da3062cd94692a900Johan Hedberg class, info->rssi, NULL); 8895288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8905288199788ecb17183d6517da3062cd94692a900Johan Hedberg update_lastseen(sba, &info->bdaddr); 8915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8925288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE; 8935288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 8945288199788ecb17183d6517da3062cd94692a900Johan Hedberg } else { 8955288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 8965288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info_with_rssi *info = ptr; 8975288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 8985288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[1] << 8) 8995288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[2] << 16); 9005288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9015288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_inquiry_result(sba, &info->bdaddr, 9025288199788ecb17183d6517da3062cd94692a900Johan Hedberg class, info->rssi, NULL); 9035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9045288199788ecb17183d6517da3062cd94692a900Johan Hedberg update_lastseen(sba, &info->bdaddr); 9055288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9065288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_WITH_RSSI_SIZE; 9075288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 9085288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 9095288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 9105288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9115288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void extended_inquiry_result(int dev, bdaddr_t *sba, 9125288199788ecb17183d6517da3062cd94692a900Johan Hedberg int plen, void *ptr) 9135288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 9145288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 9155288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 9165288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9175288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 9185288199788ecb17183d6517da3062cd94692a900Johan Hedberg extended_inquiry_info *info = ptr; 9195288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 9205288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[1] << 8) 9215288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (info->dev_class[2] << 16); 9225288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9235288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_inquiry_result(sba, &info->bdaddr, class, 9245288199788ecb17183d6517da3062cd94692a900Johan Hedberg info->rssi, info->data); 9255288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9265288199788ecb17183d6517da3062cd94692a900Johan Hedberg update_lastseen(sba, &info->bdaddr); 9275288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9285288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += EXTENDED_INQUIRY_INFO_SIZE; 9295288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 9305288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 9315288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9325288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void remote_features_information(int dev, bdaddr_t *sba, 9335288199788ecb17183d6517da3062cd94692a900Johan Hedberg void *ptr) 9345288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 9355288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_read_remote_features_complete *evt = ptr; 9365288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t dba; 9375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9385288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->status) 9395288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 9405288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9415288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (get_bdaddr(dev, sba, btohs(evt->handle), &dba) < 0) 9425288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 9435288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9445288199788ecb17183d6517da3062cd94692a900Johan Hedberg write_features_info(sba, &dba, evt->features, NULL); 9455288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 9465288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9475288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void conn_complete(int dev, int dev_id, bdaddr_t *sba, void *ptr) 9485288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 9495288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_conn_complete *evt = ptr; 9505288199788ecb17183d6517da3062cd94692a900Johan Hedberg char filename[PATH_MAX]; 9515288199788ecb17183d6517da3062cd94692a900Johan Hedberg char local_addr[18], peer_addr[18], *str; 9525288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 9535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9545288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter = manager_find_adapter(sba); 9555288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 9565288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Unable to find matching adapter"); 9575288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 9585288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 9595288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9605288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->link_type != ACL_LINK) 9615288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 9625288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9635288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_conn_complete(sba, evt->status, btohs(evt->handle), 9645288199788ecb17183d6517da3062cd94692a900Johan Hedberg &evt->bdaddr); 9655288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9665288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->status) 9675288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 9685288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9695288199788ecb17183d6517da3062cd94692a900Johan Hedberg update_lastused(sba, &evt->bdaddr); 9705288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9715288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* check if the remote version needs be requested */ 9725288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(sba, local_addr); 9735288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(&evt->bdaddr, peer_addr); 9745288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9755288199788ecb17183d6517da3062cd94692a900Johan Hedberg create_name(filename, sizeof(filename), STORAGEDIR, local_addr, 9765288199788ecb17183d6517da3062cd94692a900Johan Hedberg "manufacturers"); 9775288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9785288199788ecb17183d6517da3062cd94692a900Johan Hedberg str = textfile_get(filename, peer_addr); 9795288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!str) 9805288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_adapter_get_remote_version(adapter, btohs(evt->handle), 9815288199788ecb17183d6517da3062cd94692a900Johan Hedberg TRUE); 9825288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 9835288199788ecb17183d6517da3062cd94692a900Johan Hedberg free(str); 9845288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 9855288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9865288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void disconn_complete(int dev, bdaddr_t *sba, void *ptr) 9875288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 9885288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_disconn_complete *evt = ptr; 9895288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9905288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_disconn_complete(sba, evt->status, btohs(evt->handle), 9915288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt->reason); 9925288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 9935288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9945288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void auth_complete(int dev, bdaddr_t *sba, void *ptr) 9955288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 9965288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_auth_complete *evt = ptr; 9975288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t dba; 9985288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9995288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (get_bdaddr(dev, sba, btohs(evt->handle), &dba) < 0) 10005288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 10015288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10025288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_bonding_process_complete(sba, &dba, evt->status); 10035288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10055288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void simple_pairing_complete(int dev, bdaddr_t *sba, void *ptr) 10065288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 10075288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_simple_pairing_complete *evt = ptr; 10085288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10095288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_simple_pairing_complete(sba, &evt->bdaddr, evt->status); 10105288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10115288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10125288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void conn_request(int dev, bdaddr_t *sba, void *ptr) 10135288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 10145288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_conn_request *evt = ptr; 10155288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = evt->dev_class[0] | (evt->dev_class[1] << 8) 10165288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (evt->dev_class[2] << 16); 10175288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10185288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_remote_class(sba, &evt->bdaddr, class); 10195288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10215288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic inline void le_metaevent(int dev, bdaddr_t *sba, void *ptr) 10225288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 10235288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_le_meta_event *meta = ptr; 10245288199788ecb17183d6517da3062cd94692a900Johan Hedberg le_advertising_info *info; 10255288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t *rssi, num, i; 10265288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10275288199788ecb17183d6517da3062cd94692a900Johan Hedberg DBG("LE Meta Event"); 10285288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10295288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (meta->subevent != EVT_LE_ADVERTISING_REPORT) 10305288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 10315288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10325288199788ecb17183d6517da3062cd94692a900Johan Hedberg num = meta->data[0]; 10335288199788ecb17183d6517da3062cd94692a900Johan Hedberg info = (le_advertising_info *) (meta->data + 1); 10345288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10355288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 10365288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* RSSI is last byte of the advertising report event */ 10375288199788ecb17183d6517da3062cd94692a900Johan Hedberg rssi = info->data + info->length; 10385288199788ecb17183d6517da3062cd94692a900Johan Hedberg btd_event_inquiry_result(sba, &info->bdaddr, 0, *rssi, NULL); 10395288199788ecb17183d6517da3062cd94692a900Johan Hedberg info = (le_advertising_info *) (rssi + 1); 10405288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 10415288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10425288199788ecb17183d6517da3062cd94692a900Johan Hedberg 104355694454017b04a416931a81964bb695f48b3d93Johan Hedbergstatic void stop_hci_dev(int index) 10445288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 104555694454017b04a416931a81964bb695f48b3d93Johan Hedberg GIOChannel *chan = CHANNEL(index); 10465288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10475288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!chan) 10485288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 10495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 105055694454017b04a416931a81964bb695f48b3d93Johan Hedberg info("Stopping hci%d event socket", index); 10515288199788ecb17183d6517da3062cd94692a900Johan Hedberg 105255694454017b04a416931a81964bb695f48b3d93Johan Hedberg g_source_remove(WATCH_ID(index)); 105355694454017b04a416931a81964bb695f48b3d93Johan Hedberg g_io_channel_unref(CHANNEL(index)); 105455694454017b04a416931a81964bb695f48b3d93Johan Hedberg hci_close_dev(SK(index)); 105555694454017b04a416931a81964bb695f48b3d93Johan Hedberg init_dev_info(index, -1); 10565288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10575288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10585288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic gboolean io_security_event(GIOChannel *chan, GIOCondition cond, 10595288199788ecb17183d6517da3062cd94692a900Johan Hedberg gpointer data) 10605288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 10615288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf; 106255694454017b04a416931a81964bb695f48b3d93Johan Hedberg int type, dev, index = GPOINTER_TO_INT(data); 106355694454017b04a416931a81964bb695f48b3d93Johan Hedberg struct hci_dev_info dev_info, *di = &dev_info; 10645288199788ecb17183d6517da3062cd94692a900Johan Hedberg size_t len; 10655288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_event_hdr *eh; 10665288199788ecb17183d6517da3062cd94692a900Johan Hedberg GIOError err; 10675288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_status *evt; 10685288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10695288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { 107055694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 10715288199788ecb17183d6517da3062cd94692a900Johan Hedberg return FALSE; 10725288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 10735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10745288199788ecb17183d6517da3062cd94692a900Johan Hedberg if ((err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len))) { 10755288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (err == G_IO_ERROR_AGAIN) 10765288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 107755694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 10785288199788ecb17183d6517da3062cd94692a900Johan Hedberg return FALSE; 10795288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 10805288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10815288199788ecb17183d6517da3062cd94692a900Johan Hedberg type = *ptr++; 10825288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10835288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (type != HCI_EVENT_PKT) 10845288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 10855288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10865288199788ecb17183d6517da3062cd94692a900Johan Hedberg eh = (hci_event_hdr *) ptr; 10875288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += HCI_EVENT_HDR_SIZE; 10885288199788ecb17183d6517da3062cd94692a900Johan Hedberg 108955694454017b04a416931a81964bb695f48b3d93Johan Hedberg memset(di, 0, sizeof(*di)); 109055694454017b04a416931a81964bb695f48b3d93Johan Hedberg if (hci_devinfo(index, di) == 0) 109155694454017b04a416931a81964bb695f48b3d93Johan Hedberg bacpy(&BDADDR(index), &di->bdaddr); 109255694454017b04a416931a81964bb695f48b3d93Johan Hedberg else 109355694454017b04a416931a81964bb695f48b3d93Johan Hedberg bacpy(&di->bdaddr, &BDADDR(index)); 10945288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10955288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (ignore_device(di)) 10965288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 10975288199788ecb17183d6517da3062cd94692a900Johan Hedberg 109855694454017b04a416931a81964bb695f48b3d93Johan Hedberg dev = g_io_channel_unix_get_fd(chan); 109955694454017b04a416931a81964bb695f48b3d93Johan Hedberg 11005288199788ecb17183d6517da3062cd94692a900Johan Hedberg switch (eh->evt) { 11015288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CMD_STATUS: 11025288199788ecb17183d6517da3062cd94692a900Johan Hedberg cmd_status(dev, &di->bdaddr, ptr); 11035288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11055288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CMD_COMPLETE: 11065a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg cmd_complete(di->dev_id, &di->bdaddr, ptr); 11075288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11085288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11095288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_NAME_REQ_COMPLETE: 11105288199788ecb17183d6517da3062cd94692a900Johan Hedberg remote_name_information(dev, &di->bdaddr, ptr); 11115288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11135288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_READ_REMOTE_VERSION_COMPLETE: 11145288199788ecb17183d6517da3062cd94692a900Johan Hedberg remote_version_information(dev, &di->bdaddr, ptr); 11155288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11165288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11175288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_READ_REMOTE_FEATURES_COMPLETE: 11185288199788ecb17183d6517da3062cd94692a900Johan Hedberg remote_features_information(dev, &di->bdaddr, ptr); 11195288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11215288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_HOST_FEATURES_NOTIFY: 11225288199788ecb17183d6517da3062cd94692a900Johan Hedberg remote_features_notify(dev, &di->bdaddr, ptr); 11235288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11245288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11255288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_COMPLETE: 11265288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt = (evt_cmd_status *) ptr; 11275288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_complete(&di->bdaddr, evt->status, FALSE); 11285288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11295288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11305288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_RESULT: 11315288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_result(dev, &di->bdaddr, eh->plen, ptr); 11325288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11345288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_RESULT_WITH_RSSI: 11355288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_result_with_rssi(dev, &di->bdaddr, eh->plen, ptr); 11365288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11385288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_EXTENDED_INQUIRY_RESULT: 11395288199788ecb17183d6517da3062cd94692a900Johan Hedberg extended_inquiry_result(dev, &di->bdaddr, eh->plen, ptr); 11405288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11415288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11425288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CONN_COMPLETE: 11435288199788ecb17183d6517da3062cd94692a900Johan Hedberg conn_complete(dev, di->dev_id, &di->bdaddr, ptr); 11445288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11455288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11465288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_DISCONN_COMPLETE: 11475288199788ecb17183d6517da3062cd94692a900Johan Hedberg disconn_complete(dev, &di->bdaddr, ptr); 11485288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11505288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_AUTH_COMPLETE: 11515288199788ecb17183d6517da3062cd94692a900Johan Hedberg auth_complete(dev, &di->bdaddr, ptr); 11525288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11545288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_SIMPLE_PAIRING_COMPLETE: 11555288199788ecb17183d6517da3062cd94692a900Johan Hedberg simple_pairing_complete(dev, &di->bdaddr, ptr); 11565288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11575288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11585288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CONN_REQUEST: 11595288199788ecb17183d6517da3062cd94692a900Johan Hedberg conn_request(dev, &di->bdaddr, ptr); 11605288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11615288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LE_META_EVENT: 11625288199788ecb17183d6517da3062cd94692a900Johan Hedberg le_metaevent(dev, &di->bdaddr, ptr); 11635288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11645288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_PIN_CODE_REQ: 11655288199788ecb17183d6517da3062cd94692a900Johan Hedberg pin_code_request(dev, &di->bdaddr, (bdaddr_t *) ptr); 11665288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11675288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11685288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LINK_KEY_REQ: 11695288199788ecb17183d6517da3062cd94692a900Johan Hedberg link_key_request(dev, &di->bdaddr, (bdaddr_t *) ptr); 11705288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11725288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LINK_KEY_NOTIFY: 11735288199788ecb17183d6517da3062cd94692a900Johan Hedberg link_key_notify(dev, &di->bdaddr, ptr); 11745288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11755288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11765288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_RETURN_LINK_KEYS: 11775288199788ecb17183d6517da3062cd94692a900Johan Hedberg return_link_keys(dev, &di->bdaddr, ptr); 11785288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11805288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_IO_CAPABILITY_REQUEST: 11815288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capa_request(dev, &di->bdaddr, (bdaddr_t *) ptr); 11825288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11845288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_IO_CAPABILITY_RESPONSE: 11855288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capa_response(dev, &di->bdaddr, ptr); 11865288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11885288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_CONFIRM_REQUEST: 11895288199788ecb17183d6517da3062cd94692a900Johan Hedberg user_confirm_request(dev, &di->bdaddr, ptr); 11905288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11925288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_PASSKEY_REQUEST: 11935288199788ecb17183d6517da3062cd94692a900Johan Hedberg user_passkey_request(dev, &di->bdaddr, ptr); 11945288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11955288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11965288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_PASSKEY_NOTIFY: 11975288199788ecb17183d6517da3062cd94692a900Johan Hedberg user_passkey_notify(dev, &di->bdaddr, ptr); 11985288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 11995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12005288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_OOB_DATA_REQUEST: 12015288199788ecb17183d6517da3062cd94692a900Johan Hedberg remote_oob_data_request(dev, &di->bdaddr, ptr); 12025288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 12035288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 12045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12055288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 12065288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 12075288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12085a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedbergstatic void start_hci_dev(int index) 12095288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 121055694454017b04a416931a81964bb695f48b3d93Johan Hedberg GIOChannel *chan = CHANNEL(index); 12115288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_filter flt; 12125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12135288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (chan) 12145288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 12155288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12165a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg info("Listening for HCI events on hci%d", index); 12175288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12185288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Set filter */ 12195288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_clear(&flt); 12205288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 12215288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CMD_STATUS, &flt); 12225288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CMD_COMPLETE, &flt); 12235288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_PIN_CODE_REQ, &flt); 12245288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LINK_KEY_REQ, &flt); 12255288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LINK_KEY_NOTIFY, &flt); 12265288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_RETURN_LINK_KEYS, &flt); 12275288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_IO_CAPABILITY_REQUEST, &flt); 12285288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_IO_CAPABILITY_RESPONSE, &flt); 12295288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_CONFIRM_REQUEST, &flt); 12305288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_PASSKEY_REQUEST, &flt); 12315288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_OOB_DATA_REQUEST, &flt); 12325288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_PASSKEY_NOTIFY, &flt); 12335288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_KEYPRESS_NOTIFY, &flt); 12345288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_SIMPLE_PAIRING_COMPLETE, &flt); 12355288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_AUTH_COMPLETE, &flt); 12365288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt); 12375288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_READ_REMOTE_VERSION_COMPLETE, &flt); 12385288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_READ_REMOTE_FEATURES_COMPLETE, &flt); 12395288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_HOST_FEATURES_NOTIFY, &flt); 12405288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt); 12415288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); 12425288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt); 12435288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_EXTENDED_INQUIRY_RESULT, &flt); 12445288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CONN_REQUEST, &flt); 12455288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CONN_COMPLETE, &flt); 12465288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_DISCONN_COMPLETE, &flt); 12475288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LE_META_EVENT, &flt); 12485a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg if (setsockopt(SK(index), SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 12495288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Can't set filter on hci%d: %s (%d)", 12505a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg index, strerror(errno), errno); 12515288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 12525288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 12535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12545a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg chan = g_io_channel_unix_new(SK(index)); 125555694454017b04a416931a81964bb695f48b3d93Johan Hedberg WATCH_ID(index) = g_io_add_watch_full(chan, G_PRIORITY_LOW, 12565288199788ecb17183d6517da3062cd94692a900Johan Hedberg G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR, 125755694454017b04a416931a81964bb695f48b3d93Johan Hedberg io_security_event, GINT_TO_POINTER(index), 125855694454017b04a416931a81964bb695f48b3d93Johan Hedberg NULL); 125955694454017b04a416931a81964bb695f48b3d93Johan Hedberg CHANNEL(index) = chan; 126055694454017b04a416931a81964bb695f48b3d93Johan Hedberg PIN_LENGTH(index) = -1; 12615288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12625288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 12635288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12645288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* End of HCI event callbacks */ 12655288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1266a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) 1267a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 1268a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode int status, fd = g_io_channel_unix_get_fd(io); 1269a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t child_pid; 1270a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1271a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) { 1272a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("child_exit: unable to read child pid from pipe"); 1273a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 1274a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 1275a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1276a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (waitpid(child_pid, &status, 0) != child_pid) 1277a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("waitpid(%d) failed", child_pid); 1278a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode else 12798e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d exited", child_pid); 1280a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1281a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 1282a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 1283a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1284a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic void at_child_exit(void) 1285a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 1286a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t pid = getpid(); 1287a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1288a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid)) 1289a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("unable to write to child pipe"); 1290a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 1291a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1292fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedbergstatic void device_devup_setup(int index) 1293a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 1294a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_info di; 1295a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode uint16_t policy; 12965a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg read_stored_link_key_cp cp; 1297a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1298ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (hci_devinfo(index, &di) < 0) 1299a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 1300a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 130165bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (ignore_device(&di)) 1302a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 1303a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1304a352058752e541539b09e55124d411a534cc14afJohan Hedberg bacpy(&BDADDR(index), &di.bdaddr); 1305a352058752e541539b09e55124d411a534cc14afJohan Hedberg 1306a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set page timeout */ 1307a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if ((main_opts.flags & (1 << HCID_SET_PAGETO))) { 1308a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode write_page_timeout_cp cp; 1309a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1310a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode cp.timeout = htobs(main_opts.pageto); 1311ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, 1312a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode WRITE_PAGE_TIMEOUT_CP_SIZE, &cp); 1313a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 1314a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1315a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set default link policy */ 1316a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode policy = htobs(main_opts.link_policy); 1317ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg hci_send_cmd(SK(index), OGF_LINK_POLICY, 13186844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_DEFAULT_LINK_POLICY, 2, &policy); 1319fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg 13205a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg bacpy(&cp.bdaddr, BDADDR_ANY); 13215a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg cp.read_all = 1; 13225a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY, 13235a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg READ_STORED_LINK_KEY_CP_SIZE, (void *) &cp); 1324fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg 13255a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg if (READY(index)) 13265a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg manager_start_adapter(index); 1327a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 1328a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1329ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void init_device(int index) 1330a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 1331a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_req dr; 133265bf1321203b55b11167ac8b869da28a86ce49d2David Scherba struct hci_dev_info di; 1333c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg int dd; 13346844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg pid_t pid; 13356844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 13366844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg dd = hci_open_dev(index); 13376844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (dd < 0) { 13386844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Unable to open hci%d: %s (%d)", index, 13396844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg strerror(errno), errno); 13406844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return; 13416844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg } 13426844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 13436844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (index > max_dev) { 13446844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg max_dev = index; 1345ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg devs = g_realloc(devs, sizeof(devs[0]) * (max_dev + 1)); 13466844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg } 13476844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 1348ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg init_dev_info(index, dd); 13495a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg start_hci_dev(index); 1350a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1351a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Do initialization in the separate process */ 1352a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid = fork(); 1353a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (pid) { 1354a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case 0: 1355a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode atexit(at_child_exit); 1356a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 1357a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case -1: 1358a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Fork failed. Can't init device hci%d: %s (%d)", 1359c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg index, strerror(errno), errno); 1360a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode default: 13618e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d forked", pid); 1362a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 1363a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 1364a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1365a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode memset(&dr, 0, sizeof(dr)); 1366ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode dr.dev_id = index; 1367a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1368a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set link mode */ 1369a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode dr.dev_opt = main_opts.link_mode; 1370c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0) 1371a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't set link mode on hci%d: %s (%d)", 1372ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg index, strerror(errno), errno); 1373a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 137465bf1321203b55b11167ac8b869da28a86ce49d2David Scherba /* Set link policy for BR/EDR HCI devices */ 137565bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (hci_devinfo(index, &di) < 0) 137665bf1321203b55b11167ac8b869da28a86ce49d2David Scherba goto fail; 137765bf1321203b55b11167ac8b869da28a86ce49d2David Scherba 137865bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (!ignore_device(&di)) { 137965bf1321203b55b11167ac8b869da28a86ce49d2David Scherba dr.dev_opt = main_opts.link_policy; 138065bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (ioctl(dd, HCISETLINKPOL, (unsigned long) &dr) < 0 && 1381a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode errno != ENETDOWN) { 138265bf1321203b55b11167ac8b869da28a86ce49d2David Scherba error("Can't set link policy on hci%d: %s (%d)", 138365bf1321203b55b11167ac8b869da28a86ce49d2David Scherba index, strerror(errno), errno); 138465bf1321203b55b11167ac8b869da28a86ce49d2David Scherba } 1385a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 1386a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1387a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Start HCI device */ 1388ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (ioctl(dd, HCIDEVUP, index) < 0 && errno != EALREADY) { 1389a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't init device hci%d: %s (%d)", 1390ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode index, strerror(errno), errno); 1391a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode goto fail; 1392a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 1393a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1394a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 1395a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(0); 1396a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1397a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodefail: 1398a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 1399a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(1); 1400a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 1401a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1402ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void device_devreg_setup(int index) 1403a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 1404a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_info di; 1405a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode gboolean devup; 1406a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1407ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode init_device(index); 1408a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1409a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode memset(&di, 0, sizeof(di)); 1410a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1411ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (hci_devinfo(index, &di) < 0) 1412a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 1413a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1414a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode devup = hci_test_bit(HCI_UP, &di.flags); 1415a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 141665bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (!ignore_device(&di)) 1417ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode manager_register_adapter(index, devup); 1418a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 1419a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1420ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void device_event(int event, int index) 1421a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 1422a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (event) { 1423a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_REG: 1424ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d registered", index); 1425ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode device_devreg_setup(index); 1426a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 1427a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1428a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UNREG: 1429ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d unregistered", index); 143055694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 1431ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode manager_unregister_adapter(index); 1432a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 1433a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1434a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UP: 1435ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d up", index); 14365a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg UP(index) = TRUE; 1437ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode device_devup_setup(index); 1438a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 1439a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1440a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_DOWN: 1441ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d down", index); 14425a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg UP(index) = FALSE; 14435a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg if (READY(index)) { 14445a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg manager_stop_adapter(index); 14455a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg READY(index) = FALSE; 14465a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg } 1447a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 1448a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 1449a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 1450cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1451f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedbergstatic gboolean init_known_adapters(gpointer user_data) 145294e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 1453cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_list_req *dl; 1454cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_req *dr; 1455f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg int i, err, ctl = GPOINTER_TO_INT(user_data); 1456ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg size_t req_size; 1457cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1458ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg req_size = HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t); 1459ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg 1460ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg dl = g_try_malloc0(req_size); 1461cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (!dl) { 1462ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg error("Can't allocate devlist buffer"); 1463f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 1464cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1465cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1466cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dl->dev_num = HCI_MAX_DEV; 1467cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dr = dl->dev_req; 1468cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1469ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg if (ioctl(ctl, HCIGETDEVLIST, dl) < 0) { 1470c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 1471ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg error("Can't get device list: %s (%d)", strerror(-err), -err); 147283003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi g_free(dl); 1473f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 1474cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1475cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1476cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode for (i = 0; i < dl->dev_num; i++, dr++) { 1477cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(HCI_DEV_REG, dr->dev_id); 1478cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 147983003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi if (hci_test_bit(HCI_UP, &dr->dev_opt)) 1480cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(HCI_DEV_UP, dr->dev_id); 1481cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1482cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1483cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_free(dl); 1484f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg 1485f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 148694e91856179a268805256055ffd5155d1468b99cAlok Barsode} 148794e91856179a268805256055ffd5155d1468b99cAlok Barsode 1488cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsodestatic gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, 1489cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode gpointer data) 1490cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 1491cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; 1492cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_stack_internal *si; 1493cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_si_device *sd; 1494cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_event_hdr *eh; 1495cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode int type; 1496cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode size_t len; 1497cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode GIOError err; 1498cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1499cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr = buf; 1500cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1501cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); 1502cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (err) { 1503cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (err == G_IO_ERROR_AGAIN) 1504cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 1505cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1506cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode error("Read from control socket failed: %s (%d)", 1507ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg strerror(errno), errno); 1508cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return FALSE; 1509cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1510cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1511cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode type = *ptr++; 1512cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1513cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (type != HCI_EVENT_PKT) 1514cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 1515cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1516cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode eh = (hci_event_hdr *) ptr; 1517cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (eh->evt != EVT_STACK_INTERNAL) 1518cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 1519cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1520cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr += HCI_EVENT_HDR_SIZE; 1521cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1522cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode si = (evt_stack_internal *) ptr; 1523cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode switch (si->type) { 1524cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode case EVT_SI_DEVICE: 1525cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sd = (void *) &si->data; 1526cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(sd->event, sd->dev_id); 1527cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode break; 1528cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1529cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1530cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 1531cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 1532cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 153334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_setup(void) 1534cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 1535cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct sockaddr_hci addr; 1536cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_filter flt; 1537a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode GIOChannel *ctl_io, *child_io; 153818e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg int sock, err; 153918e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg 154018e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg if (child_pipe[0] != -1) 154118e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg return -EALREADY; 1542cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1543a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (pipe(child_pipe) < 0) { 1544c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 1545c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("pipe(): %s (%d)", strerror(-err), -err); 1546c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 1547a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 1548a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1549a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode child_io = g_io_channel_unix_new(child_pipe[0]); 1550a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_set_close_on_unref(child_io, TRUE); 15518b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = g_io_add_watch(child_io, 15528b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 15538b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_exit, NULL); 1554a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_unref(child_io); 1555a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 1556cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Create and bind HCI socket */ 1557cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 1558cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (sock < 0) { 1559c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 1560c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("Can't open HCI socket: %s (%d)", strerror(-err), 1561c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg -err); 1562c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 1563cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1564cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1565cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Set filter */ 1566cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_clear(&flt); 1567cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 1568cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_event(EVT_STACK_INTERNAL, &flt); 15696844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 1570c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 1571c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("Can't set filter: %s (%d)", strerror(-err), -err); 1572c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 1573cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1574cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1575cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode memset(&addr, 0, sizeof(addr)); 1576cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_family = AF_BLUETOOTH; 1577cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_dev = HCI_DEV_NONE; 15786844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1579c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 15806844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Can't bind HCI socket: %s (%d)", strerror(-err), -err); 1581c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 1582cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 1583cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1584cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ctl_io = g_io_channel_unix_new(sock); 1585cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_set_close_on_unref(ctl_io, TRUE); 1586cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 15878b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); 1588cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1589cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_unref(ctl_io); 1590cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 1591f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg g_idle_add(init_known_adapters, GINT_TO_POINTER(sock)); 1592f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg 1593f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return 0; 1594cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 1595cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 159634c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic void hciops_cleanup(void) 159734c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 15986844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int i; 15996844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 16006844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg for (i = 0; i <= max_dev; i++) { 1601ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (SK(i) >= 0) 1602ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg hci_close_dev(SK(i)); 16036844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg } 16046844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 16056844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg g_free(devs); 16066844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg devs = NULL; 16076844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg max_dev = -1; 16086844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 16098b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_io_id) { 16108b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(child_io_id); 16118b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = 0; 16128b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 16138b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 16148b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (ctl_io_id) { 16158b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(ctl_io_id); 16168b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = 0; 16178b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 16188b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 16198b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[0] >= 0) { 16208b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[0]); 16218b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[0] = -1; 16228b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 16238b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 16248b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[1] >= 0) { 16258b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[1]); 16268b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[1] = -1; 16278b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 162834c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 162934c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 1630076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsodestatic int hciops_start(int index) 1631076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode{ 16326844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 1633076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 1634ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIDEVUP, index) == 0) 16356844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1636076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 16376844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (errno == EALREADY) 16386844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1639076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 16406844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 16416844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Can't init device hci%d: %s (%d)", 16426844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg index, strerror(-err), -err); 1643076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 1644c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 1645076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode} 1646076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 16474e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsodestatic int hciops_stop(int index) 16484e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode{ 16494e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode int err = 0; 16504e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 1651ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIDEVDOWN, index) == 0) 16524e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode goto done; /* on success */ 16534e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 16544e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode if (errno != EALREADY) { 1655c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 16564e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode error("Can't stop device hci%d: %s (%d)", 1657c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg index, strerror(-err), -err); 16584e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode } 16594e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 16604e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsodedone: 1661c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 16624e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode} 16634e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 1664030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsodestatic int hciops_powered(int index, gboolean powered) 1665030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode{ 1666030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode uint8_t mode = SCAN_DISABLED; 1667030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 1668030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode if (powered) 1669030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode return hciops_start(index); 1670030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 1671ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, 16726844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_SCAN_ENABLE, 1, &mode) < 0) 16736844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1674030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 1675030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode return hciops_stop(index); 1676030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode} 1677030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 16788b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsodestatic int hciops_connectable(int index) 16798b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode{ 16808b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode uint8_t mode = SCAN_PAGE; 16818b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 1682ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, 16836844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_SCAN_ENABLE, 1, &mode) < 0) 16846844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 16858b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 16866844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 16878b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode} 16888b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 168955927114c520807297b2fc63148aa467bed60218Alok Barsodestatic int hciops_discoverable(int index) 169055927114c520807297b2fc63148aa467bed60218Alok Barsode{ 169155927114c520807297b2fc63148aa467bed60218Alok Barsode uint8_t mode = (SCAN_PAGE | SCAN_INQUIRY); 169255927114c520807297b2fc63148aa467bed60218Alok Barsode 1693ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 16946844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 1, &mode) < 0) 16956844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 169655927114c520807297b2fc63148aa467bed60218Alok Barsode 16976844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 169855927114c520807297b2fc63148aa467bed60218Alok Barsode} 169955927114c520807297b2fc63148aa467bed60218Alok Barsode 1700d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsodestatic int hciops_set_class(int index, uint32_t class) 1701d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode{ 1702d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode write_class_of_dev_cp cp; 1703d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 1704d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode memcpy(cp.dev_class, &class, 3); 1705d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 1706ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, 17076844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0) 17086844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1709d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 17106844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1711d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode} 1712d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 1713d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsodestatic int hciops_set_limited_discoverable(int index, uint32_t class, 1714eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode gboolean limited) 1715eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode{ 1716eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode int num = (limited ? 2 : 1); 1717eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e }; 1718d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode write_current_iac_lap_cp cp; 1719d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 1720eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode /* 1721eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode * 1: giac 1722eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode * 2: giac + liac 1723eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode */ 1724d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode memset(&cp, 0, sizeof(cp)); 1725d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode cp.num_current_iac = num; 1726d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode memcpy(&cp.lap, lap, num * 3); 1727eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 1728ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP, 17296844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg (num * 3 + 1), &cp) < 0) 17306844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1731d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 17326844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return hciops_set_class(index, class); 1733eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode} 1734eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 17353af792e57b7ccb82d3139748a2b3c6b44d2e7ce2Claudio Takahasistatic int hciops_start_inquiry(int index, uint8_t length, gboolean periodic) 1736a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode{ 1737a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; 17386844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 1739a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 1740a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode if (periodic) { 1741a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode periodic_inquiry_cp cp; 1742a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 1743a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memset(&cp, 0, sizeof(cp)); 1744a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memcpy(&cp.lap, lap, 3); 1745a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode cp.max_period = htobs(24); 1746a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode cp.min_period = htobs(16); 1747388cdea43870fe5c5163cfbe96d3218111ba39b5Claudio Takahasi cp.length = length; 1748a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode cp.num_rsp = 0x00; 1749a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 1750ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 17516844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_PERIODIC_INQUIRY, 17526844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg PERIODIC_INQUIRY_CP_SIZE, &cp); 1753a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode } else { 1754a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode inquiry_cp inq_cp; 1755a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 1756a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memset(&inq_cp, 0, sizeof(inq_cp)); 1757a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memcpy(&inq_cp.lap, lap, 3); 1758388cdea43870fe5c5163cfbe96d3218111ba39b5Claudio Takahasi inq_cp.length = length; 1759a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode inq_cp.num_rsp = 0x00; 1760a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 1761ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 17626844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_INQUIRY, INQUIRY_CP_SIZE, &inq_cp); 1763a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode } 1764a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 1765a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode if (err < 0) 1766a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode err = -errno; 1767a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 1768a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode return err; 1769a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode} 1770a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 17713af792e57b7ccb82d3139748a2b3c6b44d2e7ce2Claudio Takahasistatic int hciops_stop_inquiry(int index) 1772f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode{ 1773f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode struct hci_dev_info di; 17746844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 1775f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 1776f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode if (hci_devinfo(index, &di) < 0) 1777f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode return -errno; 1778f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 1779f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode if (hci_test_bit(HCI_INQUIRY, &di.flags)) 1780ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 17816844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_INQUIRY_CANCEL, 0, 0); 1782f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode else 1783ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 17846844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_EXIT_PERIODIC_INQUIRY, 0, 0); 1785f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode if (err < 0) 1786f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode err = -errno; 1787f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 1788f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode return err; 1789f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode} 1790f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 179170cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasistatic int hciops_start_scanning(int index) 179270cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi{ 1793ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_le_set_scan_parameters(SK(index), 0x01, htobs(0x0010), 17946844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg htobs(0x0010), 0x00, 0x00) < 0) 179570cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi return -errno; 179670cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 1797ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_le_set_scan_enable(SK(index), 0x01, 0x00) < 0) 17986844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 179970cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 18006844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 180170cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi} 180270cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 180370cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasistatic int hciops_stop_scanning(int index) 180470cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi{ 1805ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_le_set_scan_enable(SK(index), 0x00, 0x00) < 0) 180670cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi return -errno; 180770cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 18086844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 180970cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi} 181070cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 1811ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsodestatic int hciops_resolve_name(int index, bdaddr_t *bdaddr) 1812ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode{ 1813ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode remote_name_req_cp cp; 1814ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 1815ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode memset(&cp, 0, sizeof(cp)); 1816ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode bacpy(&cp.bdaddr, bdaddr); 1817ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode cp.pscan_rep_mode = 0x02; 1818ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 1819ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, 18206844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg REMOTE_NAME_REQ_CP_SIZE, &cp) < 0) 18216844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1822ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 18236844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1824ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode} 1825ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 1826164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsodestatic int hciops_set_name(int index, const char *name) 1827164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode{ 1828164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode change_local_name_cp cp; 1829164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 1830164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode memset(&cp, 0, sizeof(cp)); 1831164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode strncpy((char *) cp.name, name, sizeof(cp.name)); 1832164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 1833ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, 18346844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg CHANGE_LOCAL_NAME_CP_SIZE, &cp) < 0) 18356844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1836164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 18376844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1838164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode} 1839164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 1840d209c50141349ee9413d0717002af3d036db4762Alok Barsodestatic int hciops_read_name(int index) 1841d209c50141349ee9413d0717002af3d036db4762Alok Barsode{ 1842ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_READ_LOCAL_NAME, 18436844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 0, 0) < 0) 18446844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1845d209c50141349ee9413d0717002af3d036db4762Alok Barsode 18466844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1847d209c50141349ee9413d0717002af3d036db4762Alok Barsode} 1848d209c50141349ee9413d0717002af3d036db4762Alok Barsode 1849b96f44db8e91325968a0149595b2522d4a22481aAlok Barsodestatic int hciops_cancel_resolve_name(int index, bdaddr_t *bdaddr) 1850b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode{ 1851b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode remote_name_req_cancel_cp cp; 1852b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 1853b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode memset(&cp, 0, sizeof(cp)); 1854b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode bacpy(&cp.bdaddr, bdaddr); 1855b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 1856ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL, 18576844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg REMOTE_NAME_REQ_CANCEL_CP_SIZE, &cp) < 0) 18586844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1859b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 18606844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1861b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode} 1862b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 186361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliystatic int hciops_fast_connectable(int index, gboolean enable) 186461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy{ 186561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy write_page_activity_cp cp; 186661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy uint8_t type; 186761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 186861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy if (enable) { 186961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_INTERLACED; 187061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0024; /* 22.5 msec page scan interval */ 187161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } else { 187261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_STANDARD; /* default */ 187361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0800; /* default 1.28 sec page scan */ 187461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } 187561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 187661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.window = 0x0012; /* default 11.25 msec page scan window */ 187761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 1878ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY, 187961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy WRITE_PAGE_ACTIVITY_CP_SIZE, &cp) < 0) 18806844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1881ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg else if (hci_send_cmd(SK(index), OGF_HOST_CTL, 18826844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_PAGE_SCAN_TYPE, 1, &type) < 0) 18836844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 188461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 18856844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 188661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy} 188761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 18885bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuterstatic int hciops_read_clock(int index, int handle, int which, int timeout, 1889ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg uint32_t *clock, uint16_t *accuracy) 18905bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter{ 1891ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_read_clock(SK(index), handle, which, clock, accuracy, 18926844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg timeout) < 0) 18936844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 18945bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 18956844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 18965bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter} 18975bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 18985bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuterstatic int hciops_conn_handle(int index, const bdaddr_t *bdaddr, int *handle) 18995bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter{ 19006844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 19015bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter struct hci_conn_info_req *cr; 19025bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 19035bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info)); 19045bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter bacpy(&cr->bdaddr, bdaddr); 19055bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter cr->type = ACL_LINK; 19065bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 1907ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIGETCONNINFO, (unsigned long) cr) < 0) { 1908c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 1909c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg goto fail; 1910c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg } 19115bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 19126844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = 0; 1913c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg *handle = htobs(cr->conn_info->handle); 19145bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 1915c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedbergfail: 19165bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter g_free(cr); 19175bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter return err; 19185bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter} 19195bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 1920e070bc11469123aefc412ce4e408fe5ad5b525e5Johan Hedbergstatic int hciops_write_eir_data(int index, uint8_t *data) 1921e070bc11469123aefc412ce4e408fe5ad5b525e5Johan Hedberg{ 1922197eb53c0b5a3a0997ad0cb85d828236c6228700Johan Hedberg write_ext_inquiry_response_cp cp; 1923e070bc11469123aefc412ce4e408fe5ad5b525e5Johan Hedberg 1924197eb53c0b5a3a0997ad0cb85d828236c6228700Johan Hedberg memset(&cp, 0, sizeof(cp)); 1925197eb53c0b5a3a0997ad0cb85d828236c6228700Johan Hedberg memcpy(cp.data, data, 240); 1926197eb53c0b5a3a0997ad0cb85d828236c6228700Johan Hedberg 1927ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, 19286844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_EXT_INQUIRY_RESPONSE, 1929197eb53c0b5a3a0997ad0cb85d828236c6228700Johan Hedberg WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0) 19306844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1931e070bc11469123aefc412ce4e408fe5ad5b525e5Johan Hedberg 19326844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1933e070bc11469123aefc412ce4e408fe5ad5b525e5Johan Hedberg} 1934e070bc11469123aefc412ce4e408fe5ad5b525e5Johan Hedberg 1935b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedbergstatic int hciops_read_bdaddr(int index, bdaddr_t *bdaddr) 1936b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg{ 1937a352058752e541539b09e55124d411a534cc14afJohan Hedberg bacpy(bdaddr, &BDADDR(index)); 19386844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1939b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg} 1940b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg 19413e2860479cdb722a849a569495e22366949f8d18Johan Hedbergstatic int hciops_set_event_mask(int index, uint8_t *events, size_t count) 19423e2860479cdb722a849a569495e22366949f8d18Johan Hedberg{ 1943ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_SET_EVENT_MASK, 19446844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg count, events) < 0) 19453e2860479cdb722a849a569495e22366949f8d18Johan Hedberg return -errno; 19463e2860479cdb722a849a569495e22366949f8d18Johan Hedberg 19476844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 19483e2860479cdb722a849a569495e22366949f8d18Johan Hedberg} 19493e2860479cdb722a849a569495e22366949f8d18Johan Hedberg 1950c0af129926e28403c10a272cd90770ed9facfe2bJohan Hedbergstatic int hciops_write_inq_mode(int index, uint8_t mode) 1951c0af129926e28403c10a272cd90770ed9facfe2bJohan Hedberg{ 1952195cb7501bcbee2f3be5006c5e5f5a15e50c9599Johan Hedberg write_inquiry_mode_cp cp; 1953c0af129926e28403c10a272cd90770ed9facfe2bJohan Hedberg 1954195cb7501bcbee2f3be5006c5e5f5a15e50c9599Johan Hedberg memset(&cp, 0, sizeof(cp)); 1955195cb7501bcbee2f3be5006c5e5f5a15e50c9599Johan Hedberg cp.mode = mode; 1956195cb7501bcbee2f3be5006c5e5f5a15e50c9599Johan Hedberg 1957ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE, 1958195cb7501bcbee2f3be5006c5e5f5a15e50c9599Johan Hedberg WRITE_INQUIRY_MODE_CP_SIZE, &cp) < 0) 19596844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 1960c0af129926e28403c10a272cd90770ed9facfe2bJohan Hedberg 19616844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1962c0af129926e28403c10a272cd90770ed9facfe2bJohan Hedberg} 1963c0af129926e28403c10a272cd90770ed9facfe2bJohan Hedberg 19647dedff71686cac5556b0c3a3137ffd0b8c6fb28fJohan Hedbergstatic int hciops_read_inq_tx_pwr(int index) 19657dedff71686cac5556b0c3a3137ffd0b8c6fb28fJohan Hedberg{ 1966ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, 19677dedff71686cac5556b0c3a3137ffd0b8c6fb28fJohan Hedberg OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL, 0, NULL) < 0) 19686844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 19697dedff71686cac5556b0c3a3137ffd0b8c6fb28fJohan Hedberg 19706844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 19717dedff71686cac5556b0c3a3137ffd0b8c6fb28fJohan Hedberg} 19727dedff71686cac5556b0c3a3137ffd0b8c6fb28fJohan Hedberg 1973885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedbergstatic int hciops_block_device(int index, bdaddr_t *bdaddr) 1974885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg{ 1975ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIBLOCKADDR, bdaddr) < 0) 1976885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg return -errno; 1977885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 19786844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1979885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg} 1980885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 1981885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedbergstatic int hciops_unblock_device(int index, bdaddr_t *bdaddr) 1982885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg{ 1983ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIUNBLOCKADDR, bdaddr) < 0) 1984885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg return -errno; 1985885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 19866844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 1987885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg} 1988885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 1989f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedbergstatic int hciops_get_conn_list(int index, GSList **conns) 1990f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg{ 1991f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg struct hci_conn_list_req *cl; 1992f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg struct hci_conn_info *ci; 19936844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err, i; 1994f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 1995f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); 1996f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 1997f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg cl->dev_id = index; 1998f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg cl->conn_num = 10; 1999f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg ci = cl->conn_info; 2000f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 2001ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIGETCONNLIST, cl) < 0) { 2002f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg err = -errno; 2003f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg goto fail; 2004f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg } 2005f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 2006f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg err = 0; 2007f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg *conns = NULL; 2008f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 2009f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg for (i = 0; i < cl->conn_num; i++, ci++) 2010f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg *conns = g_slist_append(*conns, g_memdup(ci, sizeof(*ci))); 2011f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 2012f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedbergfail: 2013f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg g_free(cl); 2014f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg return err; 2015f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg} 2016f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 2017e38fdde63c8f385b99bf17c9e5794e7f08575f7eJohan Hedbergstatic int hciops_read_local_version(int index, struct hci_version *ver) 2018e38fdde63c8f385b99bf17c9e5794e7f08575f7eJohan Hedberg{ 2019ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_read_local_version(SK(index), ver, HCI_REQ_TIMEOUT) < 0) 2020e38fdde63c8f385b99bf17c9e5794e7f08575f7eJohan Hedberg return -errno; 2021e38fdde63c8f385b99bf17c9e5794e7f08575f7eJohan Hedberg 20226844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2023e38fdde63c8f385b99bf17c9e5794e7f08575f7eJohan Hedberg} 2024e38fdde63c8f385b99bf17c9e5794e7f08575f7eJohan Hedberg 202548e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedbergstatic int hciops_read_local_features(int index, uint8_t *features) 202648e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg{ 2027ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_read_local_features(SK(index), features, 20286844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg HCI_REQ_TIMEOUT) < 0) 202948e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg return -errno; 203048e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg 20316844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 203248e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg} 203348e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg 20349ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasistatic int hciops_read_local_ext_features(int index) 20359ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi{ 20369ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi uint8_t page_num = 1; 20379ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi 2038ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_INFO_PARAM, 20396844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_READ_LOCAL_EXT_FEATURES, 1, &page_num) < 0) 20409ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi return -errno; 20419ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi 20426844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 20439ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi} 20449ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi 20450133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedbergstatic int hciops_init_ssp_mode(int index, uint8_t *mode) 20460133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedberg{ 2047132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg write_simple_pairing_mode_cp cp; 20480133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedberg 2049ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIGETAUTHINFO, NULL) < 0 && errno == EINVAL) 20506844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2051132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg 2052132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg memset(&cp, 0, sizeof(cp)); 2053132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg cp.mode = 0x01; 20540133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedberg 2055ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, 20566844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_SIMPLE_PAIRING_MODE, 2057132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg WRITE_SIMPLE_PAIRING_MODE_CP_SIZE, &cp) < 0) 20586844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 20590133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedberg 20606844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 20610133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedberg} 20620133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedberg 206398dbebb8edf59666e226386caf38824e40c8ff33Johan Hedbergstatic int hciops_read_link_policy(int index) 206498dbebb8edf59666e226386caf38824e40c8ff33Johan Hedberg{ 2065ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_LINK_POLICY, 20666844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_READ_DEFAULT_LINK_POLICY, 0, NULL) < 0) 206798dbebb8edf59666e226386caf38824e40c8ff33Johan Hedberg return -errno; 206898dbebb8edf59666e226386caf38824e40c8ff33Johan Hedberg 20696844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 207098dbebb8edf59666e226386caf38824e40c8ff33Johan Hedberg} 207198dbebb8edf59666e226386caf38824e40c8ff33Johan Hedberg 207206dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedbergstatic int hciops_disconnect(int index, uint16_t handle) 207306dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg{ 207406dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg disconnect_cp cp; 207506dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 207606dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg memset(&cp, 0, sizeof(cp)); 207706dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg cp.handle = htobs(handle); 207806dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg cp.reason = HCI_OE_USER_ENDED_CONNECTION; 207906dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 2080ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_DISCONNECT, 208106dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg DISCONNECT_CP_SIZE, &cp) < 0) 20826844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 208306dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 20846844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 208506dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg} 208606dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 20871bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedbergstatic int hciops_remove_bonding(int index, bdaddr_t *bdaddr) 20881bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg{ 208973c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg delete_stored_link_key_cp cp; 20901bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 209173c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg memset(&cp, 0, sizeof(cp)); 209273c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg bacpy(&cp.bdaddr, bdaddr); 209373c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg 20941bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg /* Delete the link key from the Bluetooth chip */ 2095ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_DELETE_STORED_LINK_KEY, 209673c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg DELETE_STORED_LINK_KEY_CP_SIZE, &cp) < 0) 20976844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 20981bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 20996844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 21001bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg} 21011bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 2102424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedbergstatic int hciops_request_authentication(int index, uint16_t handle, 2103424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg uint8_t *status) 2104424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg{ 2105424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg struct hci_request rq; 2106424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg auth_requested_cp cp; 2107424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg evt_cmd_status rp; 2108424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg 2109424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg memset(&rp, 0, sizeof(rp)); 2110424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg 2111424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg memset(&cp, 0, sizeof(cp)); 2112424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg cp.handle = htobs(handle); 2113424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg 2114424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg memset(&rq, 0, sizeof(rq)); 2115424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg rq.ogf = OGF_LINK_CTL; 2116424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg rq.ocf = OCF_AUTH_REQUESTED; 2117424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg rq.cparam = &cp; 2118424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg rq.clen = AUTH_REQUESTED_CP_SIZE; 2119424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg rq.rparam = &rp; 2120424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg rq.rlen = EVT_CMD_STATUS_SIZE; 2121424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg rq.event = EVT_CMD_STATUS; 2122424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg 2123ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_req(SK(index), &rq, HCI_REQ_TIMEOUT) < 0) 21246844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 2125424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg 2126424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg if (status) 2127424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg *status = rp.status; 2128424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg 21296844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2130424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg} 2131424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg 2132e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedbergstatic int hciops_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin) 2133e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg{ 21346844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 2135e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 2136e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg if (pin) { 2137e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg pin_code_reply_cp pr; 2138e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg size_t len = strlen(pin); 2139e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 2140e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg memset(&pr, 0, sizeof(pr)); 2141e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg bacpy(&pr.bdaddr, bdaddr); 2142e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg memcpy(pr.pin_code, pin, len); 2143e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg pr.pin_len = len; 2144ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 21456844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_PIN_CODE_REPLY, 2146e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg PIN_CODE_REPLY_CP_SIZE, &pr); 2147e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg } else 2148ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 2149e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg OCF_PIN_CODE_NEG_REPLY, 6, bdaddr); 2150e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 21516844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (err < 0) 21526844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 2153e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 2154e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg return err; 2155e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg} 2156e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 2157df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedbergstatic int hciops_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success) 2158df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg{ 21596844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 2160df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg user_confirm_reply_cp cp; 2161df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg 2162df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg memset(&cp, 0, sizeof(cp)); 2163df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg bacpy(&cp.bdaddr, bdaddr); 2164df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg 2165df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg if (success) 2166ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 21676844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_USER_CONFIRM_REPLY, 2168df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg USER_CONFIRM_REPLY_CP_SIZE, &cp); 2169df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg else 2170ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 2171df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg OCF_USER_CONFIRM_NEG_REPLY, 2172df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg USER_CONFIRM_REPLY_CP_SIZE, &cp); 2173df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg 21746844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (err < 0) 21756844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 2176df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg 2177df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg return err; 2178df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg} 2179df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg 2180889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedbergstatic int hciops_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey) 2181889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg{ 21826844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 2183889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 2184889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg if (passkey != INVALID_PASSKEY) { 2185889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg user_passkey_reply_cp cp; 2186889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 2187889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg memset(&cp, 0, sizeof(cp)); 2188889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg bacpy(&cp.bdaddr, bdaddr); 2189889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg cp.passkey = passkey; 2190889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 2191ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 21926844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_USER_PASSKEY_REPLY, 2193889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg USER_PASSKEY_REPLY_CP_SIZE, &cp); 2194889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg } else 2195ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg err = hci_send_cmd(SK(index), OGF_LINK_CTL, 2196889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg OCF_USER_PASSKEY_NEG_REPLY, 6, bdaddr); 2197889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 21986844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (err < 0) 21996844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 2200889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 2201889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg return err; 2202889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg} 2203889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 22044b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedbergstatic int hciops_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth) 22054b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg{ 22064b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg struct hci_auth_info_req req; 22074b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg 22084b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg memset(&req, 0, sizeof(req)); 22094b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg bacpy(&req.bdaddr, bdaddr); 22104b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg 2211ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (ioctl(SK(index), HCIGETAUTHINFO, (unsigned long) &req) < 0) 22126844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 22134b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg 22144b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg if (auth) 22154b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg *auth = req.type; 22164b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg 22176844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 22184b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg} 22194b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg 2220f8b7d84e2cceed2f113d1688c87326ea2505cd16Johan Hedbergstatic int hciops_read_scan_enable(int index) 2221f8b7d84e2cceed2f113d1688c87326ea2505cd16Johan Hedberg{ 2222ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_READ_SCAN_ENABLE, 22236844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 0, NULL) < 0) 2224f8b7d84e2cceed2f113d1688c87326ea2505cd16Johan Hedberg return -errno; 2225f8b7d84e2cceed2f113d1688c87326ea2505cd16Johan Hedberg 22266844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2227f8b7d84e2cceed2f113d1688c87326ea2505cd16Johan Hedberg} 2228f8b7d84e2cceed2f113d1688c87326ea2505cd16Johan Hedberg 2229132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedbergstatic int hciops_read_ssp_mode(int index) 2230132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg{ 2231ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, 22326844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_READ_SIMPLE_PAIRING_MODE, 0, NULL) < 0) 2233132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg return -errno; 2234132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg 22356844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2236132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg} 2237132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg 22387ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasistatic int hciops_write_le_host(int index, uint8_t le, uint8_t simul) 22397ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi{ 22407ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi write_le_host_supported_cp cp; 22417ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 22427ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi memset(&cp, 0, sizeof(cp)); 22437ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi cp.le = le; 22447ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi cp.simul = simul; 22457ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 2246ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg if (hci_send_cmd(SK(index), OGF_HOST_CTL, 22476844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_LE_HOST_SUPPORTED, 22486844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg WRITE_LE_HOST_SUPPORTED_CP_SIZE, &cp) < 0) 22496844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 22507ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 22516844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 22527ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi} 22537ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 2254646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedbergstruct remote_version_req { 2255646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg int index; 2256646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg uint16_t handle; 2257646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg}; 2258646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2259646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedbergstatic gboolean get_remote_version(gpointer user_data) 2260646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg{ 2261646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg struct remote_version_req *req = user_data; 2262646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg read_remote_version_cp cp; 2263646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2264646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg memset(&cp, 0, sizeof(cp)); 2265646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg cp.handle = htobs(req->handle); 2266646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2267646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg hci_send_cmd(SK(req->index), OGF_LINK_CTL, OCF_READ_REMOTE_VERSION, 2268646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg READ_REMOTE_VERSION_CP_SIZE, &cp); 2269646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2270646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg return FALSE; 2271646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg} 2272646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2273646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedbergstatic int hciops_get_remote_version(int index, uint16_t handle, 2274646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg gboolean delayed) 2275646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg{ 2276646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg struct remote_version_req *req; 2277646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2278646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg req = g_new0(struct remote_version_req, 1); 2279646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg req->handle = handle; 2280646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg req->index = index; 2281646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2282646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg if (!delayed) { 2283646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg get_remote_version(req); 2284646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg g_free(req); 2285646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg return 0; 2286646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg } 2287646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2288646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 1, get_remote_version, 2289646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg req, g_free); 2290646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 2291646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg return 0; 2292646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg} 2293646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg 229434c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic struct btd_adapter_ops hci_ops = { 229534c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .setup = hciops_setup, 229634c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .cleanup = hciops_cleanup, 2297076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode .start = hciops_start, 22984e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode .stop = hciops_stop, 2299030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode .set_powered = hciops_powered, 23008b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode .set_connectable = hciops_connectable, 230155927114c520807297b2fc63148aa467bed60218Alok Barsode .set_discoverable = hciops_discoverable, 2302eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode .set_limited_discoverable = hciops_set_limited_discoverable, 23033af792e57b7ccb82d3139748a2b3c6b44d2e7ce2Claudio Takahasi .start_inquiry = hciops_start_inquiry, 23043af792e57b7ccb82d3139748a2b3c6b44d2e7ce2Claudio Takahasi .stop_inquiry = hciops_stop_inquiry, 230570cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi .start_scanning = hciops_start_scanning, 230670cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi .stop_scanning = hciops_stop_scanning, 2307ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode .resolve_name = hciops_resolve_name, 2308b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode .cancel_resolve_name = hciops_cancel_resolve_name, 2309164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode .set_name = hciops_set_name, 2310d209c50141349ee9413d0717002af3d036db4762Alok Barsode .read_name = hciops_read_name, 2311d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode .set_class = hciops_set_class, 231261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy .set_fast_connectable = hciops_fast_connectable, 23135bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter .read_clock = hciops_read_clock, 23145bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter .get_conn_handle = hciops_conn_handle, 2315e070bc11469123aefc412ce4e408fe5ad5b525e5Johan Hedberg .write_eir_data = hciops_write_eir_data, 2316b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg .read_bdaddr = hciops_read_bdaddr, 23173e2860479cdb722a849a569495e22366949f8d18Johan Hedberg .set_event_mask = hciops_set_event_mask, 2318c0af129926e28403c10a272cd90770ed9facfe2bJohan Hedberg .write_inq_mode = hciops_write_inq_mode, 23197dedff71686cac5556b0c3a3137ffd0b8c6fb28fJohan Hedberg .read_inq_tx_pwr = hciops_read_inq_tx_pwr, 2320885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg .block_device = hciops_block_device, 2321885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg .unblock_device = hciops_unblock_device, 2322f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg .get_conn_list = hciops_get_conn_list, 2323e38fdde63c8f385b99bf17c9e5794e7f08575f7eJohan Hedberg .read_local_version = hciops_read_local_version, 232448e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg .read_local_features = hciops_read_local_features, 23259ebc8d3b0f66a24f3821bf243dcd3f59527e8612Claudio Takahasi .read_local_ext_features = hciops_read_local_ext_features, 23260133f1bc40e609103b90b7544e17aa19819c3c03Johan Hedberg .init_ssp_mode = hciops_init_ssp_mode, 232798dbebb8edf59666e226386caf38824e40c8ff33Johan Hedberg .read_link_policy = hciops_read_link_policy, 232806dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg .disconnect = hciops_disconnect, 23291bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg .remove_bonding = hciops_remove_bonding, 2330424ffb26405690b9d9653a9418a9c4d332a85176Johan Hedberg .request_authentication = hciops_request_authentication, 2331e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg .pincode_reply = hciops_pincode_reply, 2332df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg .confirm_reply = hciops_confirm_reply, 2333889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg .passkey_reply = hciops_passkey_reply, 23344b625a87bd009aa6a61443d802d63a5f81c58cc8Johan Hedberg .get_auth_info = hciops_get_auth_info, 2335f8b7d84e2cceed2f113d1688c87326ea2505cd16Johan Hedberg .read_scan_enable = hciops_read_scan_enable, 2336132374b5125787fd2be0ea9c6985ad9a88600474Johan Hedberg .read_ssp_mode = hciops_read_ssp_mode, 23377ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi .write_le_host = hciops_write_le_host, 2338646f0c7e6b557c5413825ce7b04bee52bf0129e8Johan Hedberg .get_remote_version = hciops_get_remote_version, 2339abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg .encrypt_link = hciops_encrypt_link, 234034c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode}; 234134c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 234234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_init(void) 234334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 2344d30044157466e7f34e7f2d5d7ce70215ea013338Johan Hedberg return btd_register_adapter_ops(&hci_ops, FALSE); 234534c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 2346d57934d1d09c34d1b136c572cad1dff6306c8c48Johan Hedberg 234794e91856179a268805256055ffd5155d1468b99cAlok Barsodestatic void hciops_exit(void) 234894e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 2349929393b82db06368ff5fa4074bc209d1d4d03a48Marcel Holtmann btd_adapter_cleanup_ops(&hci_ops); 235094e91856179a268805256055ffd5155d1468b99cAlok Barsode} 235194e91856179a268805256055ffd5155d1468b99cAlok Barsode 235294e91856179a268805256055ffd5155d1468b99cAlok BarsodeBLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, 23531ab388feb37980f1afc940c7cf530b9baadeabb1Marcel Holtmann BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit) 2354