hciops.c revision 61f0df8f18c417df50a296e10893c82b5eb83879
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" 46a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include "manager.h" 47a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 4818e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedbergstatic int child_pipe[2] = { -1, -1 }; 4994e91856179a268805256055ffd5155d1468b99cAlok Barsode 508b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedbergstatic guint child_io_id = 0; 518b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedbergstatic guint ctl_io_id = 0; 528b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 53a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) 54a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 55a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode int status, fd = g_io_channel_unix_get_fd(io); 56a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t child_pid; 57a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 58a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) { 59a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("child_exit: unable to read child pid from pipe"); 60a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 61a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 62a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 63a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (waitpid(child_pid, &status, 0) != child_pid) 64a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("waitpid(%d) failed", child_pid); 65a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode else 668e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d exited", child_pid); 67a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 68a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 69a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 70a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 71a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic void at_child_exit(void) 72a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 73a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t pid = getpid(); 74a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 75a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid)) 76a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("unable to write to child pipe"); 77a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 78a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 79fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedbergstatic void device_devup_setup(int index) 80a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 81a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_info di; 82a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode uint16_t policy; 8383003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 84a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 85ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (hci_devinfo(index, &di) < 0) 86a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 87a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 8865bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (ignore_device(&di)) 89a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 90a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 91ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode dd = hci_open_dev(index); 92a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (dd < 0) { 9383003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 94a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't open device hci%d: %s (%d)", 9583003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi index, strerror(err), err); 96a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 97a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 98a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 99a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set page timeout */ 100a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if ((main_opts.flags & (1 << HCID_SET_PAGETO))) { 101a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode write_page_timeout_cp cp; 102a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 103a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode cp.timeout = htobs(main_opts.pageto); 104a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, 105a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode WRITE_PAGE_TIMEOUT_CP_SIZE, &cp); 106a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 107a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 108a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set default link policy */ 109a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode policy = htobs(main_opts.link_policy); 110a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_send_cmd(dd, OGF_LINK_POLICY, 111a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode OCF_WRITE_DEFAULT_LINK_POLICY, 2, &policy); 112a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 113a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 114fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg 115fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg start_security_manager(index); 116fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg 117fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg /* Return value 1 means ioctl(DEVDOWN) was performed */ 118fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg if (manager_start_adapter(index) == 1) 119fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg stop_security_manager(index); 120a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 121a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 122ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void init_device(int index) 123a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 124a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_req dr; 12565bf1321203b55b11167ac8b869da28a86ce49d2David Scherba struct hci_dev_info di; 126a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t pid; 12783003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 128a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 129a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Do initialization in the separate process */ 130a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid = fork(); 131a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (pid) { 132a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case 0: 133a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode atexit(at_child_exit); 134a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 135a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case -1: 13683003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 137a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Fork failed. Can't init device hci%d: %s (%d)", 13883003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi index, strerror(err), err); 139a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode default: 1408e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d forked", pid); 141a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 142a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 143a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 144ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode dd = hci_open_dev(index); 145a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (dd < 0) { 14683003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 147a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't open device hci%d: %s (%d)", 14883003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi index, strerror(err), err); 149a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(1); 150a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 151a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 152a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode memset(&dr, 0, sizeof(dr)); 153ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode dr.dev_id = index; 154a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 155a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set link mode */ 156a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode dr.dev_opt = main_opts.link_mode; 157a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0) { 15883003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 159a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't set link mode on hci%d: %s (%d)", 16083003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi index, strerror(err), err); 161a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 162a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 16365bf1321203b55b11167ac8b869da28a86ce49d2David Scherba /* Set link policy for BR/EDR HCI devices */ 16465bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (hci_devinfo(index, &di) < 0) 16565bf1321203b55b11167ac8b869da28a86ce49d2David Scherba goto fail; 16665bf1321203b55b11167ac8b869da28a86ce49d2David Scherba 16765bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (!ignore_device(&di)) { 16865bf1321203b55b11167ac8b869da28a86ce49d2David Scherba dr.dev_opt = main_opts.link_policy; 16965bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (ioctl(dd, HCISETLINKPOL, (unsigned long) &dr) < 0 && 170a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode errno != ENETDOWN) { 17165bf1321203b55b11167ac8b869da28a86ce49d2David Scherba error("Can't set link policy on hci%d: %s (%d)", 17265bf1321203b55b11167ac8b869da28a86ce49d2David Scherba index, strerror(errno), errno); 17365bf1321203b55b11167ac8b869da28a86ce49d2David Scherba } 174a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 175a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 176a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Start HCI device */ 177ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (ioctl(dd, HCIDEVUP, index) < 0 && errno != EALREADY) { 178a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't init device hci%d: %s (%d)", 179ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode index, strerror(errno), errno); 180a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode goto fail; 181a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 182a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 183a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 184a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(0); 185a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 186a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodefail: 187a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 188a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(1); 189a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 190a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 191ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void device_devreg_setup(int index) 192a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 193a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_info di; 194a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode gboolean devup; 195a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 196ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode init_device(index); 197a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 198a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode memset(&di, 0, sizeof(di)); 199a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 200ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (hci_devinfo(index, &di) < 0) 201a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 202a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 203a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode devup = hci_test_bit(HCI_UP, &di.flags); 204a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 20565bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (!ignore_device(&di)) 206ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode manager_register_adapter(index, devup); 207a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 208a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 209ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void device_event(int event, int index) 210a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 211a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (event) { 212a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_REG: 213ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d registered", index); 214ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode device_devreg_setup(index); 215a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 216a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 217a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UNREG: 218ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d unregistered", index); 219ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode manager_unregister_adapter(index); 220a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 221a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 222a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UP: 223ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d up", index); 224ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode device_devup_setup(index); 225a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 226a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 227a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_DOWN: 228ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d down", index); 229ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode manager_stop_adapter(index); 230ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode stop_security_manager(index); 231a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 232a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 233a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 234cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 235ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic int init_known_adapters(int ctl) 23694e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 237cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_list_req *dl; 238cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_req *dr; 23918e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg int i, err; 240cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 241cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dl = g_try_malloc0(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t)); 242cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (!dl) { 24383003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 24418e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg error("Can't allocate devlist buffer: %s (%d)", 24583003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi strerror(err), err); 24683003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 247cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 248cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 249cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dl->dev_num = HCI_MAX_DEV; 250cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dr = dl->dev_req; 251cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 252cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) { 25383003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 25418e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg error("Can't get device list: %s (%d)", 25583003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi strerror(err), err); 25683003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi g_free(dl); 25783003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 258cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 259cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 260cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode for (i = 0; i < dl->dev_num; i++, dr++) { 261cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(HCI_DEV_REG, dr->dev_id); 262cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 26383003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi if (hci_test_bit(HCI_UP, &dr->dev_opt)) 264cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(HCI_DEV_UP, dr->dev_id); 265cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 266cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 267cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_free(dl); 26894e91856179a268805256055ffd5155d1468b99cAlok Barsode return 0; 26994e91856179a268805256055ffd5155d1468b99cAlok Barsode} 27094e91856179a268805256055ffd5155d1468b99cAlok Barsode 271cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsodestatic gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, 272cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode gpointer data) 273cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 274cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; 275cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_stack_internal *si; 276cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_si_device *sd; 277cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_event_hdr *eh; 278cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode int type; 279cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode size_t len; 280cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode GIOError err; 281cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 282cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr = buf; 283cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 284cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); 285cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (err) { 286cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (err == G_IO_ERROR_AGAIN) 287cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 288cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 289cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode error("Read from control socket failed: %s (%d)", 290cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode strerror(errno), errno); 291cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return FALSE; 292cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 293cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 294cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode type = *ptr++; 295cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 296cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (type != HCI_EVENT_PKT) 297cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 298cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 299cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode eh = (hci_event_hdr *) ptr; 300cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (eh->evt != EVT_STACK_INTERNAL) 301cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 302cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 303cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr += HCI_EVENT_HDR_SIZE; 304cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 305cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode si = (evt_stack_internal *) ptr; 306cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode switch (si->type) { 307cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode case EVT_SI_DEVICE: 308cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sd = (void *) &si->data; 309cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(sd->event, sd->dev_id); 310cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode break; 311cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 312cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 313cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 314cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 315cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 31634c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_setup(void) 317cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 318cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct sockaddr_hci addr; 319cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_filter flt; 320a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode GIOChannel *ctl_io, *child_io; 32118e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg int sock, err; 32218e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg 32318e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg if (child_pipe[0] != -1) 32418e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg return -EALREADY; 325cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 326a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (pipe(child_pipe) < 0) { 32783003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 32883003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi error("pipe(): %s (%d)", strerror(err), err); 32983003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 330a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 331a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 332a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode child_io = g_io_channel_unix_new(child_pipe[0]); 333a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_set_close_on_unref(child_io, TRUE); 3348b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = g_io_add_watch(child_io, 3358b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 3368b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_exit, NULL); 337a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_unref(child_io); 338a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 339cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Create and bind HCI socket */ 340cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 341cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (sock < 0) { 34283003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 34383003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi error("Can't open HCI socket: %s (%d)", strerror(err), 34483003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err); 34583003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 346cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 347cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 348cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Set filter */ 349cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_clear(&flt); 350cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 351cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_event(EVT_STACK_INTERNAL, &flt); 352cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, 353cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sizeof(flt)) < 0) { 35483003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 35583003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi error("Can't set filter: %s (%d)", strerror(err), err); 35683003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 357cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 358cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 359cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode memset(&addr, 0, sizeof(addr)); 360cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_family = AF_BLUETOOTH; 361cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_dev = HCI_DEV_NONE; 362cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (bind(sock, (struct sockaddr *) &addr, 363cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sizeof(addr)) < 0) { 36483003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 365cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode error("Can't bind HCI socket: %s (%d)", 36683003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi strerror(err), err); 36783003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 368cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 369cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 370cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ctl_io = g_io_channel_unix_new(sock); 371cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_set_close_on_unref(ctl_io, TRUE); 372cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 3738b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); 374cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 375cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_unref(ctl_io); 376cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 377cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Initialize already connected devices */ 378ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode return init_known_adapters(sock); 379cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 380cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 38134c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic void hciops_cleanup(void) 38234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 3838b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_io_id) { 3848b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(child_io_id); 3858b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = 0; 3868b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 3878b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 3888b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (ctl_io_id) { 3898b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(ctl_io_id); 3908b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = 0; 3918b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 3928b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 3938b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[0] >= 0) { 3948b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[0]); 3958b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[0] = -1; 3968b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 3978b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 3988b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[1] >= 0) { 3998b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[1]); 4008b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[1] = -1; 4018b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 40234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 40334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 404076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsodestatic int hciops_start(int index) 405076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode{ 406076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode int dd; 407076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode int err = 0; 408076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 409076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode dd = hci_open_dev(index); 410076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode if (dd < 0) 411076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode return -EIO; 412076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 413076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode if (ioctl(dd, HCIDEVUP, index) == 0) 414076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode goto done; /* on success */ 415076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 416076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode if (errno != EALREADY) { 41783003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 418076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode error("Can't init device hci%d: %s (%d)", 41983003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi index, strerror(err), err); 420076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode } 421076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 422076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsodedone: 423076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode hci_close_dev(dd); 42483003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 425076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode} 426076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 4274e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsodestatic int hciops_stop(int index) 4284e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode{ 4294e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode int dd; 4304e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode int err = 0; 4314e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 4324e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode dd = hci_open_dev(index); 4334e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode if (dd < 0) 4344e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode return -EIO; 4354e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 4364e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode if (ioctl(dd, HCIDEVDOWN, index) == 0) 4374e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode goto done; /* on success */ 4384e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 4394e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode if (errno != EALREADY) { 44083003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi err = errno; 4414e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode error("Can't stop device hci%d: %s (%d)", 44283003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi index, strerror(err), err); 4434e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode } 4444e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 4454e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsodedone: 4464e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode hci_close_dev(dd); 44783003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi return -err; 4484e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode} 4494e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode 450030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsodestatic int hciops_powered(int index, gboolean powered) 451030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode{ 45290608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz int dd, err; 453030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode uint8_t mode = SCAN_DISABLED; 454030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 455030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode if (powered) 456030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode return hciops_start(index); 457030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 458030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode dd = hci_open_dev(index); 459030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode if (dd < 0) 460030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode return -EIO; 461030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 46290608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 463030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 1, &mode); 46490608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz if (err < 0) { 46590608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = -errno; 46690608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz hci_close_dev(dd); 46790608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz return err; 46890608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz } 469030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 470030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode hci_close_dev(dd); 471030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 472030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode return hciops_stop(index); 473030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode} 474030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode 4758b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsodestatic int hciops_connectable(int index) 4768b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode{ 47790608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz int dd, err; 4788b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode uint8_t mode = SCAN_PAGE; 4798b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 4808b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode dd = hci_open_dev(index); 4818b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode if (dd < 0) 4828b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode return -EIO; 4838b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 48490608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 4858b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 1, &mode); 48690608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz if (err < 0) 48790608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = -errno; 4888b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 4898b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode hci_close_dev(dd); 4908b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 49190608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz return err; 4928b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode} 4938b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode 49455927114c520807297b2fc63148aa467bed60218Alok Barsodestatic int hciops_discoverable(int index) 49555927114c520807297b2fc63148aa467bed60218Alok Barsode{ 49690608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz int dd, err; 49755927114c520807297b2fc63148aa467bed60218Alok Barsode uint8_t mode = (SCAN_PAGE | SCAN_INQUIRY); 49855927114c520807297b2fc63148aa467bed60218Alok Barsode 49955927114c520807297b2fc63148aa467bed60218Alok Barsode dd = hci_open_dev(index); 50055927114c520807297b2fc63148aa467bed60218Alok Barsode if (dd < 0) 50155927114c520807297b2fc63148aa467bed60218Alok Barsode return -EIO; 50255927114c520807297b2fc63148aa467bed60218Alok Barsode 50390608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 50455927114c520807297b2fc63148aa467bed60218Alok Barsode 1, &mode); 50590608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz if (err < 0) 50690608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = -errno; 50755927114c520807297b2fc63148aa467bed60218Alok Barsode 50855927114c520807297b2fc63148aa467bed60218Alok Barsode hci_close_dev(dd); 50955927114c520807297b2fc63148aa467bed60218Alok Barsode 51090608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz return err; 51155927114c520807297b2fc63148aa467bed60218Alok Barsode} 51255927114c520807297b2fc63148aa467bed60218Alok Barsode 513d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsodestatic int hciops_set_class(int index, uint32_t class) 514d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode{ 515d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode int dd, err; 516d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode write_class_of_dev_cp cp; 517d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 518d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode dd = hci_open_dev(index); 519d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode if (dd < 0) 520d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode return -EIO; 521d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 522d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode memcpy(cp.dev_class, &class, 3); 523d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 524d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, 525d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode WRITE_CLASS_OF_DEV_CP_SIZE, &cp); 526d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 527d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode if (err < 0) 528d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode err = -errno; 529d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 530d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode hci_close_dev(dd); 531d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 532d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode return err; 533d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode} 534d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 535d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsodestatic int hciops_set_limited_discoverable(int index, uint32_t class, 536eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode gboolean limited) 537eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode{ 53890608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz int dd, err; 539eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode int num = (limited ? 2 : 1); 540eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e }; 541d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode write_current_iac_lap_cp cp; 542d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 543eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode /* 544eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode * 1: giac 545eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode * 2: giac + liac 546eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode */ 547eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode dd = hci_open_dev(index); 548eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode if (dd < 0) 549eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode return -EIO; 550eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 551d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode memset(&cp, 0, sizeof(cp)); 552d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode cp.num_current_iac = num; 553d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode memcpy(&cp.lap, lap, num * 3); 554eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 55590608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP, 55683003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi (num * 3 + 1), &cp); 55790608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz if (err < 0) { 55890608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz err = -errno; 55990608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz hci_close_dev(dd); 56090608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz return err; 56190608519f3701763ca00b27d6ae133d6bbb07badLuiz Augusto von Dentz } 562eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 563eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode hci_close_dev(dd); 564d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 565d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode return hciops_set_class(index, class); 566eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode} 567eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 568a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsodestatic int hciops_start_discovery(int index, gboolean periodic) 569a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode{ 570a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; 57183003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 572a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 573a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode dd = hci_open_dev(index); 574a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode if (dd < 0) 575a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode return -EIO; 576a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 577a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode if (periodic) { 578a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode periodic_inquiry_cp cp; 579a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 580a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memset(&cp, 0, sizeof(cp)); 581a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memcpy(&cp.lap, lap, 3); 582a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode cp.max_period = htobs(24); 583a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode cp.min_period = htobs(16); 584a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode cp.length = 0x08; 585a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode cp.num_rsp = 0x00; 586a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 587a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_PERIODIC_INQUIRY, 588a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode PERIODIC_INQUIRY_CP_SIZE, &cp); 589a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode } else { 590a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode inquiry_cp inq_cp; 591a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 592a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memset(&inq_cp, 0, sizeof(inq_cp)); 593a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode memcpy(&inq_cp.lap, lap, 3); 594a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode inq_cp.length = 0x08; 595a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode inq_cp.num_rsp = 0x00; 596a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 597a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_INQUIRY, 598a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode INQUIRY_CP_SIZE, &inq_cp); 599a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode } 600a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 601a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode if (err < 0) 602a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode err = -errno; 603a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 604a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode hci_close_dev(dd); 605a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 606a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode return err; 607a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode} 608a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 609f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsodestatic int hciops_stop_discovery(int index) 610f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode{ 611f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode struct hci_dev_info di; 61283003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 613f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 614f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode if (hci_devinfo(index, &di) < 0) 615f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode return -errno; 616f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 617f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode dd = hci_open_dev(index); 618f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode if (dd < 0) 619f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode return -EIO; 620f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 621f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode if (hci_test_bit(HCI_INQUIRY, &di.flags)) 622f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_INQUIRY_CANCEL, 623f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 0, 0); 624f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode else 625f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_EXIT_PERIODIC_INQUIRY, 626f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 0, 0); 627f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode if (err < 0) 628f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode err = -errno; 629f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 630f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode hci_close_dev(dd); 631f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 632f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode return err; 633f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode} 634f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode 635ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsodestatic int hciops_resolve_name(int index, bdaddr_t *bdaddr) 636ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode{ 637ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode remote_name_req_cp cp; 63883003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 639ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 640ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode dd = hci_open_dev(index); 641ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode if (dd < 0) 642ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode return -EIO; 643ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 644ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode memset(&cp, 0, sizeof(cp)); 645ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode bacpy(&cp.bdaddr, bdaddr); 646ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode cp.pscan_rep_mode = 0x02; 647ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 648ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, 649ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode REMOTE_NAME_REQ_CP_SIZE, &cp); 650ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode if (err < 0) 651ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode err = -errno; 652ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 653ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode hci_close_dev(dd); 654ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 655ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode return err; 656ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode} 657ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 658164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsodestatic int hciops_set_name(int index, const char *name) 659164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode{ 660164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode change_local_name_cp cp; 66183003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 662164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 663164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode dd = hci_open_dev(index); 664164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode if (dd < 0) 665164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode return -EIO; 666164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 667164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode memset(&cp, 0, sizeof(cp)); 668164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode strncpy((char *) cp.name, name, sizeof(cp.name)); 669164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 670164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, 671164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode CHANGE_LOCAL_NAME_CP_SIZE, &cp); 672164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode if (err < 0) 673164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode err = -errno; 674164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 675164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode hci_close_dev(dd); 676164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 677164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode return err; 678164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode} 679164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 680d209c50141349ee9413d0717002af3d036db4762Alok Barsodestatic int hciops_read_name(int index) 681d209c50141349ee9413d0717002af3d036db4762Alok Barsode{ 68283003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 683d209c50141349ee9413d0717002af3d036db4762Alok Barsode 684d209c50141349ee9413d0717002af3d036db4762Alok Barsode dd = hci_open_dev(index); 685d209c50141349ee9413d0717002af3d036db4762Alok Barsode if (dd < 0) 686d209c50141349ee9413d0717002af3d036db4762Alok Barsode return -EIO; 687d209c50141349ee9413d0717002af3d036db4762Alok Barsode 688d209c50141349ee9413d0717002af3d036db4762Alok Barsode err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_READ_LOCAL_NAME, 0, 0); 689d209c50141349ee9413d0717002af3d036db4762Alok Barsode if (err < 0) 690d209c50141349ee9413d0717002af3d036db4762Alok Barsode err = -errno; 691d209c50141349ee9413d0717002af3d036db4762Alok Barsode 692d209c50141349ee9413d0717002af3d036db4762Alok Barsode hci_close_dev(dd); 693d209c50141349ee9413d0717002af3d036db4762Alok Barsode 694d209c50141349ee9413d0717002af3d036db4762Alok Barsode return err; 695d209c50141349ee9413d0717002af3d036db4762Alok Barsode} 696d209c50141349ee9413d0717002af3d036db4762Alok Barsode 697b96f44db8e91325968a0149595b2522d4a22481aAlok Barsodestatic int hciops_cancel_resolve_name(int index, bdaddr_t *bdaddr) 698b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode{ 699b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode remote_name_req_cancel_cp cp; 70083003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi int dd, err; 701b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 702b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode dd = hci_open_dev(index); 703b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode if (dd < 0) 704b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode return -EIO; 705b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 706b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode memset(&cp, 0, sizeof(cp)); 707b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode bacpy(&cp.bdaddr, bdaddr); 708b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 709b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode err = hci_send_cmd(dd, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL, 710b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode REMOTE_NAME_REQ_CANCEL_CP_SIZE, &cp); 711b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode if (err < 0) 712b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode err = -errno; 713b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 714b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode hci_close_dev(dd); 715b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 716b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode return err; 717b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode} 718b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 71961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliystatic int hciops_fast_connectable(int index, gboolean enable) 72061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy{ 72161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy int dd, err = 0; 72261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy write_page_activity_cp cp; 72361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy uint8_t type; 72461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 72561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy if (enable) { 72661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_INTERLACED; 72761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0024; /* 22.5 msec page scan interval */ 72861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } else { 72961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_STANDARD; /* default */ 73061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0800; /* default 1.28 sec page scan */ 73161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } 73261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 73361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.window = 0x0012; /* default 11.25 msec page scan window */ 73461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 73561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy dd = hci_open_dev(index); 73661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy if (dd < 0) 73761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy return -EIO; 73861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 73961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy if (hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY, 74061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy WRITE_PAGE_ACTIVITY_CP_SIZE, &cp) < 0) 74161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy err = -errno; 74261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy else if (hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_SCAN_TYPE, 74361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 1, &type) < 0) 74461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy err = -errno; 74561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 74661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy hci_close_dev(dd); 74761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 74861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy return err; 74961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy} 75061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 75134c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic struct btd_adapter_ops hci_ops = { 75234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .setup = hciops_setup, 75334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .cleanup = hciops_cleanup, 754076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode .start = hciops_start, 7554e71ac8617182584edf8ca57879e33d98879eb5dAlok Barsode .stop = hciops_stop, 756030d865e4a2c9ff498a925a63264a419ff6c0780Alok Barsode .set_powered = hciops_powered, 7578b000e17009d5b6772ab3b4367881dfcef763e7eAlok Barsode .set_connectable = hciops_connectable, 75855927114c520807297b2fc63148aa467bed60218Alok Barsode .set_discoverable = hciops_discoverable, 759eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode .set_limited_discoverable = hciops_set_limited_discoverable, 760a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode .start_discovery = hciops_start_discovery, 761f8c3e9f4a68af6e6687e754f871e03e2e8cc80b8Alok Barsode .stop_discovery = hciops_stop_discovery, 762ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode .resolve_name = hciops_resolve_name, 763b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode .cancel_resolve_name = hciops_cancel_resolve_name, 764164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode .set_name = hciops_set_name, 765d209c50141349ee9413d0717002af3d036db4762Alok Barsode .read_name = hciops_read_name, 766d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode .set_class = hciops_set_class, 76761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy .set_fast_connectable = hciops_fast_connectable, 76834c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode}; 76934c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 77034c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_init(void) 77134c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 77234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode return btd_register_adapter_ops(&hci_ops); 77334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 77494e91856179a268805256055ffd5155d1468b99cAlok Barsodestatic void hciops_exit(void) 77594e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 776929393b82db06368ff5fa4074bc209d1d4d03a48Marcel Holtmann btd_adapter_cleanup_ops(&hci_ops); 77794e91856179a268805256055ffd5155d1468b99cAlok Barsode} 77894e91856179a268805256055ffd5155d1468b99cAlok Barsode 77994e91856179a268805256055ffd5155d1468b99cAlok BarsodeBLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, 7801ab388feb37980f1afc940c7cf530b9baadeabb1Marcel Holtmann BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit) 781