hciops.c revision a04c1f0249e1899e4b3d237931f9b5d97f30cebe
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> 383e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg#include <bluetooth/sdp.h> 393e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg#include <bluetooth/sdp_lib.h> 4094e91856179a268805256055ffd5155d1468b99cAlok Barsode 41cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include <glib.h> 42cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 43cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode#include "hcid.h" 44a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include "sdpd.h" 45b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg#include "btio.h" 46a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include "adapter.h" 4750fb53c4a7520e210244d909be9ef1accf5cfdfeVinicius Costa Gomes#include "device.h" 4894e91856179a268805256055ffd5155d1468b99cAlok Barsode#include "plugin.h" 49e891f7df6225c758da0d95f7554c6cc67f72f31eGustavo F. Padovan#include "log.h" 505288199788ecb17183d6517da3062cd94692a900Johan Hedberg#include "storage.h" 515288199788ecb17183d6517da3062cd94692a900Johan Hedberg#include "event.h" 52a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode#include "manager.h" 5323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc#include "oob.h" 54991a7a4f09049c91297d74f9d28497fad166268eClaudio Takahasi#include "eir.h" 55a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 562a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes#define DISCOV_HALTED 0 572a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes#define DISCOV_INQ 1 582a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes#define DISCOV_SCAN 2 592a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 608be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes#define TIMEOUT_BR_LE_SCAN 5120 /* TGAP(100)/2 */ 618be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes#define TIMEOUT_LE_SCAN 10240 /* TGAP(gen_disc_scan_min) */ 628be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 638be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes#define LENGTH_BR_INQ 0x08 648be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes#define LENGTH_BR_LE_INQ 0x04 658be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 668be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedesstatic int hciops_start_scanning(int index, int timeout); 678be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 6818e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedbergstatic int child_pipe[2] = { -1, -1 }; 6994e91856179a268805256055ffd5155d1468b99cAlok Barsode 708b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedbergstatic guint child_io_id = 0; 718b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedbergstatic guint ctl_io_id = 0; 728b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 738be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedesenum adapter_type { 748be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes BR_EDR, 758be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes LE_ONLY, 768be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes BR_EDR_LE, 778be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes UNKNOWN, 788be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes}; 798be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 80be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg/* Commands sent by kernel on starting an adapter */ 81be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedbergenum { 82be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg PENDING_BDADDR, 83be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg PENDING_VERSION, 84be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg PENDING_FEATURES, 85fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg PENDING_NAME, 86be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg}; 87be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 88b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstruct bt_conn { 89b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev; 90bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg bdaddr_t bdaddr; 91bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg uint16_t handle; 92b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t loc_cap; 93b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t loc_auth; 94b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t rem_cap; 95b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t rem_auth; 9623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc uint8_t rem_oob_data; 97b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg gboolean bonding_initiator; 98b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg gboolean secmode3; 99b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg GIOChannel *io; /* For raw L2CAP socket (bonding) */ 100bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg}; 101bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 10223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Jancstruct oob_data { 10323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc bdaddr_t bdaddr; 10423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc uint8_t hash[16]; 10523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc uint8_t randomizer[16]; 10623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc}; 10723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 1086844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedbergstatic int max_dev = -1; 109ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedbergstatic struct dev_info { 110b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg int id; 111ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg int sk; 112a352058752e541539b09e55124d411a534cc14afJohan Hedberg bdaddr_t bdaddr; 11300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg char name[249]; 114cef88385008d999c515366ebe6c01e3f6967fb61Bruna Moreira uint8_t eir[HCI_MAX_EIR_LENGTH]; 115be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg uint8_t features[8]; 11694e7feb45fb9938d4d8f7363dfc7dee34940389eAndre Guedes uint8_t extfeatures[8]; 11700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint8_t ssp_mode; 11800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 11900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg int8_t tx_power; 12000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1212a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes int discov_state; 1222a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 12300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint32_t current_cod; 12400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint32_t wanted_cod; 12500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint32_t pending_cod; 12600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg gboolean cache_enable; 1275c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg gboolean already_up; 1285c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg gboolean registered; 129b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg gboolean pairable; 130b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 131b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t io_capability; 13200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 133be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg struct hci_version ver; 134be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 13500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint16_t did_vendor; 13600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint16_t did_product; 13700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint16_t did_version; 13800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1395a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg gboolean up; 140ab8a3b836133345ce2e29f4a079aaff1f5a33b70Rafal Michalski uint32_t pending; 14155694454017b04a416931a81964bb695f48b3d93Johan Hedberg 142fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg GIOChannel *io; 14355694454017b04a416931a81964bb695f48b3d93Johan Hedberg guint watch_id; 144b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 145dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg gboolean debug_keys; 146b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg GSList *keys; 1471522d6568002afa27ee7a3280b3166f7ecb02f06Johan Hedberg uint8_t pin_length; 1483e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 14923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *oob_data; 15023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 1513e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg GSList *uuids; 152bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 153bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg GSList *connections; 1549235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 1559235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes guint stop_scan_id; 156ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg} *devs = NULL; 157ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg 1582a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline int get_state(int index) 1592a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 1602a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes struct dev_info *dev = &devs[index]; 1612a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 1622a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return dev->discov_state; 1632a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 1642a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 1658be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedesstatic inline gboolean is_resolvname_enabled(void) 1668be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes{ 1678be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return main_opts.name_resolv ? TRUE : FALSE; 1688be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes} 1698be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 1702a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic void set_state(int index, int state) 1712a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 1728be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes struct btd_adapter *adapter; 1732a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes struct dev_info *dev = &devs[index]; 1742a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 1752a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (dev->discov_state == state) 1762a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 1772a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 1788be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter = manager_find_adapter_by_id(index); 1798be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (!adapter) { 1808be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes error("No matching adapter found"); 1818be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return; 1828be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } 1838be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 1842a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes dev->discov_state = state; 1852a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 1862a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes DBG("hci%d: new state %d", index, dev->discov_state); 1872a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 1882a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes switch (dev->discov_state) { 1892a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes case DISCOV_HALTED: 1908be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (adapter_get_state(adapter) == STATE_SUSPENDED) 1918be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return; 1928be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 1938be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (is_resolvname_enabled() && 1948be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_has_discov_sessions(adapter)) 1958be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_set_state(adapter, STATE_RESOLVNAME); 1968be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes else 1978be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_set_state(adapter, STATE_IDLE); 1982a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes break; 1992a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes case DISCOV_INQ: 2002a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes case DISCOV_SCAN: 2018be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_set_state(adapter, STATE_DISCOV); 2022a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes break; 2032a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 2042a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 2052a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 2068be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedesstatic inline gboolean is_le_capable(int index) 2078be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes{ 2088be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes struct dev_info *dev = &devs[index]; 2098be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 2108be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return (main_opts.le && dev->features[4] & LMP_LE && 2118be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes dev->extfeatures[0] & LMP_HOST_LE) ? TRUE : FALSE; 2128be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes} 2138be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 2148be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedesstatic inline gboolean is_bredr_capable(int index) 2158be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes{ 2168be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes struct dev_info *dev = &devs[index]; 2178be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 2188be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return (dev->features[4] & LMP_NO_BREDR) == 0 ? TRUE : FALSE; 2198be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes} 2208be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 2218be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedesstatic int get_adapter_type(int index) 2228be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes{ 2238be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (is_le_capable(index) && is_bredr_capable(index)) 2248be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return BR_EDR_LE; 2258be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes else if (is_le_capable(index)) 2268be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return LE_ONLY; 2278be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes else if (is_bredr_capable(index)) 2288be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return BR_EDR; 2298be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 2308be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return UNKNOWN; 2318be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes} 2328be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 233db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedbergstatic int ignore_device(struct hci_dev_info *di) 234db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg{ 235db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg return hci_test_bit(HCI_RAW, &di->flags) || di->type >> 4 != HCI_BREDR; 236db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg} 237db5266f0afedc33e2fd6fc3601c16498865f746dJohan Hedberg 23871ba00415bd2941db24958d1e6e265611945194eJohan Hedbergstatic struct dev_info *init_dev_info(int index, int sk, gboolean registered, 239149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz gboolean already_up) 240ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg{ 241fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 242fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 243fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memset(dev, 0, sizeof(*dev)); 244fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 245b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->id = index; 246fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->sk = sk; 247fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->cache_enable = TRUE; 248fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->registered = registered; 249149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz dev->already_up = already_up; 250b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->io_capability = 0x03; /* No Input No Output */ 2512a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes dev->discov_state = DISCOV_HALTED; 25271ba00415bd2941db24958d1e6e265611945194eJohan Hedberg 25371ba00415bd2941db24958d1e6e265611945194eJohan Hedberg return dev; 254ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg} 2556844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 256abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg/* Async HCI command handling with callback support */ 257abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 258abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergstruct hci_cmd_data { 259abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg bt_hci_result_t cb; 260abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t handle; 261abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t ocf; 262abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg gpointer caller_data; 263abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg}; 264abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 265abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergstatic gboolean hci_event_watch(GIOChannel *io, 266abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg GIOCondition cond, gpointer user_data) 267abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg{ 268abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg unsigned char buf[HCI_MAX_EVENT_SIZE], *body; 269abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_cmd_data *cmd = user_data; 270abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_cmd_status *evt_status; 271abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_auth_complete *evt_auth; 272abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_encrypt_change *evt_enc; 273abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_event_hdr *hdr; 274abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg set_conn_encrypt_cp cp; 275abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg int dd; 276abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t ocf; 277abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint8_t status = HCI_OE_POWER_OFF; 278abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 279abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (cond & G_IO_NVAL) { 280abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->cb(status, cmd->caller_data); 281abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return FALSE; 282abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 283abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 284abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (cond & (G_IO_ERR | G_IO_HUP)) 285abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 286abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 287abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg dd = g_io_channel_unix_get_fd(io); 288abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 289abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (read(dd, buf, sizeof(buf)) < 0) 290abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 291abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 292abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hdr = (hci_event_hdr *) (buf + 1); 293abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg body = buf + (1 + HCI_EVENT_HDR_SIZE); 294abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 295abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg switch (hdr->evt) { 296abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case EVT_CMD_STATUS: 297abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_status = (evt_cmd_status *) body; 298abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg ocf = cmd_opcode_ocf(evt_status->opcode); 299abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (ocf != cmd->ocf) 300abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 301abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg switch (ocf) { 302abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case OCF_AUTH_REQUESTED: 303abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case OCF_SET_CONN_ENCRYPT: 304abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_status->status != 0) { 305abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Baseband rejected command */ 306abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = evt_status->status; 307abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 308abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 309abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg break; 310abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg default: 311abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 312abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 313abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Wait for the next event */ 314abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 315abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case EVT_AUTH_COMPLETE: 316abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_auth = (evt_auth_complete *) body; 317abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_auth->handle != cmd->handle) { 318abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Skipping */ 319abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 320abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 321abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 322abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_auth->status != 0x00) { 323abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = evt_auth->status; 324abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Abort encryption */ 325abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 326abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 327abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 328abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg memset(&cp, 0, sizeof(cp)); 329abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cp.handle = cmd->handle; 330abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cp.encrypt = 1; 331abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 332abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->ocf = OCF_SET_CONN_ENCRYPT; 333abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 334abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, 335abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg SET_CONN_ENCRYPT_CP_SIZE, &cp) < 0) { 336abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = HCI_COMMAND_DISALLOWED; 337abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg goto failed; 338abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 339abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Wait for encrypt change event */ 340abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 341abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg case EVT_ENCRYPT_CHANGE: 342abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg evt_enc = (evt_encrypt_change *) body; 343abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (evt_enc->handle != cmd->handle) 344abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 345abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 346abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Procedure finished: reporting status */ 347abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg status = evt_enc->status; 348abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg break; 349abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg default: 350abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg /* Skipping */ 351abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return TRUE; 352abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 353abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 354abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergfailed: 355abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->cb(status, cmd->caller_data); 356abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_shutdown(io, TRUE, NULL); 357abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 358abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return FALSE; 359abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg} 360abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 361b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedbergstatic int write_inq_mode(int index, uint8_t mode) 362b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg{ 363fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 364b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg write_inquiry_mode_cp cp; 365b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 366b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg memset(&cp, 0, sizeof(cp)); 367b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg cp.mode = mode; 368b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 369fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE, 370b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg WRITE_INQUIRY_MODE_CP_SIZE, &cp) < 0) 371b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return -errno; 372b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 373b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 0; 374b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg} 375b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 376b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedbergstatic uint8_t get_inquiry_mode(int index) 377b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg{ 378fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 379fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 380fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->features[6] & LMP_EXT_INQ) 381b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 2; 382b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 383fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->features[3] & LMP_RSSI_INQ) 384b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 1; 385b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 386fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.manufacturer == 11 && dev->ver.hci_rev == 0x00 && 387fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_subver == 0x0757) 388b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 1; 389b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 390fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.manufacturer == 15) { 391fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.hci_rev == 0x03 && 392fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_subver == 0x6963) 393b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 1; 394fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.hci_rev == 0x09 && 395fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_subver == 0x6963) 396b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 1; 397fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.hci_rev == 0x00 && 398fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_subver == 0x6965) 399b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 1; 400b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg } 401b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 402fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.manufacturer == 31 && dev->ver.hci_rev == 0x2005 && 403fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_subver == 0x1805) 404b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 1; 405b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 406b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg return 0; 407b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg} 408b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 409be49c2621d577da4fafd462265b611289547f183Johan Hedbergstatic int init_ssp_mode(int index) 410be49c2621d577da4fafd462265b611289547f183Johan Hedberg{ 411fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 412be49c2621d577da4fafd462265b611289547f183Johan Hedberg write_simple_pairing_mode_cp cp; 413be49c2621d577da4fafd462265b611289547f183Johan Hedberg 414fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (ioctl(dev->sk, HCIGETAUTHINFO, NULL) < 0 && errno == EINVAL) 415be49c2621d577da4fafd462265b611289547f183Johan Hedberg return 0; 416be49c2621d577da4fafd462265b611289547f183Johan Hedberg 417be49c2621d577da4fafd462265b611289547f183Johan Hedberg memset(&cp, 0, sizeof(cp)); 418be49c2621d577da4fafd462265b611289547f183Johan Hedberg cp.mode = 0x01; 419be49c2621d577da4fafd462265b611289547f183Johan Hedberg 420fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, 421be49c2621d577da4fafd462265b611289547f183Johan Hedberg OCF_WRITE_SIMPLE_PAIRING_MODE, 422be49c2621d577da4fafd462265b611289547f183Johan Hedberg WRITE_SIMPLE_PAIRING_MODE_CP_SIZE, &cp) < 0) 423be49c2621d577da4fafd462265b611289547f183Johan Hedberg return -errno; 424be49c2621d577da4fafd462265b611289547f183Johan Hedberg 425be49c2621d577da4fafd462265b611289547f183Johan Hedberg return 0; 426be49c2621d577da4fafd462265b611289547f183Johan Hedberg} 427be49c2621d577da4fafd462265b611289547f183Johan Hedberg 4285c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergstatic int hciops_set_discoverable(int index, gboolean discoverable) 4295c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg{ 430fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 4315c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg uint8_t mode; 4325c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 4335c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (discoverable) 4345c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg mode = (SCAN_PAGE | SCAN_INQUIRY); 4355c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg else 4365c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg mode = SCAN_PAGE; 4375c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 4385c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d discoverable %d", index, discoverable); 4395c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 440fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 4415c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 1, &mode) < 0) 4425c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return -errno; 4435c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 4445c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return 0; 4455c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg} 4465c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 44763ff6738abc6bf21becbbfde583062502e7728a6Johan Hedbergstatic int hciops_set_pairable(int index, gboolean pairable) 44863ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg{ 4496964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg struct btd_adapter *adapter; 4506964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg 45163ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg DBG("hci%d pairable %d", index, pairable); 4526964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg 4536964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg adapter = manager_find_adapter(&devs[index].bdaddr); 4546964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg if (adapter) 4556964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg btd_adapter_pairable_changed(adapter, pairable); 4566964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg 457b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg devs[index].pairable = pairable; 458b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 4596964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9Johan Hedberg return 0; 46063ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg} 46163ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg 46263ff6738abc6bf21becbbfde583062502e7728a6Johan Hedbergstatic int hciops_power_off(int index) 4635c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg{ 464fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 4655c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 4665c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d", index); 4675c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 46863ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg if (ioctl(dev->sk, HCIDEVDOWN, index) < 0 && errno != EALREADY) 46963ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg return -errno; 4705c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 47163ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg return 0; 4725c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg} 4735c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 4745b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedbergstatic void set_event_mask(int index) 475b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg{ 476fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 477bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 478bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 479bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg * command otherwise */ 480bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg uint8_t events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 481b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 4825b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg /* Events for 1.2 and newer controllers */ 483fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.lmp_ver > 1) { 4845b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 4855b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 4865b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 4875b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 4885b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 4895b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg } 490b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 4915b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[3] & LMP_RSSI_INQ) 4925b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 493b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 4945b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[5] & LMP_SNIFF_SUBR) 4955b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 4965b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 4975b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[5] & LMP_PAUSE_ENC) 4985b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 4995b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5005b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[6] & LMP_EXT_INQ) 5015b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 5025b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5035b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[6] & LMP_NFLUSH_PKTS) 5045b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 5055b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5065b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[7] & LMP_LSTO) 5075b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 5085b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5095b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[6] & LMP_SIMPLE_PAIR) { 5105b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 5115b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 5125b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 5135b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 5145b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 5155b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 5165b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 5175b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 5185b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 5195b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg * Features Notification */ 520b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg } 521b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 5225b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[4] & LMP_LE) 5235b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 5245b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5255b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_SET_EVENT_MASK, 5265b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg sizeof(events), events); 5275b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg} 5285b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5295b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedbergstatic void start_adapter(int index) 5305b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg{ 5315b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg struct dev_info *dev = &devs[index]; 5325b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg uint8_t inqmode; 5335b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg uint16_t link_policy; 5345b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5355b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg set_event_mask(index); 5365b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 537fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->features[6] & LMP_SIMPLE_PAIR) 538be49c2621d577da4fafd462265b611289547f183Johan Hedberg init_ssp_mode(index); 539be49c2621d577da4fafd462265b611289547f183Johan Hedberg 540b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg inqmode = get_inquiry_mode(index); 541b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg if (inqmode) 542b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg write_inq_mode(index, inqmode); 543b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 544fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->features[7] & LMP_INQ_TX_PWR) 545fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, 546b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL, 0, NULL); 547b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 548b59dabdd2515aa111ebc56d946259e4bbdf20c61Pawel Wieczorkiewicz /* Set default link policy */ 549ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy = main_opts.link_policy; 550ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg 551fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[0] & LMP_RSWITCH)) 552ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_RSWITCH; 553fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[0] & LMP_HOLD)) 554ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_HOLD; 555fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[0] & LMP_SNIFF)) 556ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_SNIFF; 557fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[1] & LMP_PARK)) 558ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_PARK; 559b59dabdd2515aa111ebc56d946259e4bbdf20c61Pawel Wieczorkiewicz 560ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy = htobs(link_policy); 561fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_POLICY, OCF_WRITE_DEFAULT_LINK_POLICY, 562ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg sizeof(link_policy), &link_policy); 563b59dabdd2515aa111ebc56d946259e4bbdf20c61Pawel Wieczorkiewicz 564fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->current_cod = 0; 565fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memset(dev->eir, 0, sizeof(dev->eir)); 5665c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg} 56700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 568dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentzstatic int hciops_stop_inquiry(int index) 569dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz{ 570dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz struct dev_info *dev = &devs[index]; 571dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 572dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz DBG("hci%d", index); 573dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 57417baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_INQUIRY_CANCEL, 0, 0) < 0) 575dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz return -errno; 576dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 57717baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return 0; 578dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz} 579dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 5805c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergstatic gboolean init_adapter(int index) 5815c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg{ 582fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 5835c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg struct btd_adapter *adapter = NULL; 584fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg gboolean existing_adapter = dev->registered; 5855c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg uint8_t mode, on_mode; 5865c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg gboolean pairable, discoverable; 5875c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 588fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->registered) { 5895c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg adapter = btd_manager_register_adapter(index); 5905c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (adapter) 591fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->registered = TRUE; 5925c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg } else { 593fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg adapter = manager_find_adapter(&dev->bdaddr); 5945c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg /* FIXME: manager_find_adapter should return a new ref */ 5955c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_adapter_ref(adapter); 5965c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg } 5975c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 5985c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (adapter == NULL) 5995c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return FALSE; 6005c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6018440ce6ac89fdb290e566ab01edc4dcb6935a682Johan Hedberg btd_adapter_get_mode(adapter, &mode, &on_mode, &pairable); 6025c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6035c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (existing_adapter) 6045c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg mode = on_mode; 6055c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6065c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (mode == MODE_OFF) { 60763ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg hciops_power_off(index); 6085c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg goto done; 6095c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg } 6105c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6115c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg start_adapter(index); 6125c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_adapter_start(adapter); 6135c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6145c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg discoverable = (mode == MODE_DISCOVERABLE); 6155c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6165c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg hciops_set_discoverable(index, discoverable); 6175c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg hciops_set_pairable(index, pairable); 6185c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 619dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz if (dev->already_up) 620dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz hciops_stop_inquiry(index); 621dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 6225c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergdone: 6235c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_adapter_unref(adapter); 6245c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return TRUE; 625b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg} 626b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 627abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergstatic int hciops_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb, 628abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg gpointer user_data) 629abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg{ 630abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg GIOChannel *io; 631abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_cmd_data *cmd; 632abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_conn_info_req *cr; 633abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg auth_requested_cp cp; 634abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_filter nf; 635abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg int dd, err; 636abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint32_t link_mode; 637abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t handle; 638abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 639684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg dd = hci_open_dev(index); 640684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (dd < 0) 641684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg return -errno; 642684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg 643abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info)); 644abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cr->type = ACL_LINK; 645abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg bacpy(&cr->bdaddr, dst); 646abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 647684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = ioctl(dd, HCIGETCONNINFO, cr); 648abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg link_mode = cr->conn_info->link_mode; 649abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg handle = cr->conn_info->handle; 650abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_free(cr); 651abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 652684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (err < 0) { 653684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = -errno; 654684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 655684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg } 656abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 657684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (link_mode & HCI_LM_ENCRYPT) { 658684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = -EALREADY; 659684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 660684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg } 661abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 662abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg memset(&cp, 0, sizeof(cp)); 663abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cp.handle = htobs(handle); 664abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 665684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_AUTH_REQUESTED, 666684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg AUTH_REQUESTED_CP_SIZE, &cp) < 0) { 667684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = -errno; 668684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 669684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg } 670abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 671abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd = g_new0(struct hci_cmd_data, 1); 672abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->handle = handle; 673abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->ocf = OCF_AUTH_REQUESTED; 674abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->cb = cb; 675abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->caller_data = user_data; 676abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 677abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_clear(&nf); 678abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_ptype(HCI_EVENT_PKT, &nf); 679abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_CMD_STATUS, &nf); 680abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_AUTH_COMPLETE, &nf); 681abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_ENCRYPT_CHANGE, &nf); 682abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 683abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { 684abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg err = -errno; 685abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_free(cmd); 686684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 687abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 688abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 689684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg io = g_io_channel_unix_new(dd); 690abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_set_close_on_unref(io, FALSE); 691abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_add_watch_full(io, G_PRIORITY_DEFAULT, 692abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg G_IO_HUP | G_IO_ERR | G_IO_NVAL | G_IO_IN, 693abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_event_watch, cmd, g_free); 694abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_unref(io); 695abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 696abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return 0; 697684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg 698684b1d3be105b64f3994e621335f69b45e34125fJohan Hedbergfail: 699684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg close(dd); 700684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg return err; 701abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg} 702abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 70300c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_set_did(int index, uint16_t vendor, uint16_t product, 70400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint16_t version) 70500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 706fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 707fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 708fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->did_vendor = vendor; 709fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->did_product = product; 710fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->did_version = version; 71100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 71200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 71300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 71400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 715abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg/* End async HCI command handling */ 716abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 7175288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Start of HCI event callbacks */ 7185288199788ecb17183d6517da3062cd94692a900Johan Hedberg 719b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic gint conn_handle_cmp(gconstpointer a, gconstpointer b) 720b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 721b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg const struct bt_conn *conn = a; 722b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint16_t handle = *((const uint16_t *) b); 723b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 724b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return (int) conn->handle - (int) handle; 725b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 726b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 727b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic struct bt_conn *find_conn_by_handle(struct dev_info *dev, 728b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint16_t handle) 729b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 730b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg GSList *match; 731b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 732b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg match = g_slist_find_custom(dev->connections, &handle, 733b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn_handle_cmp); 734b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (match) 735b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return match->data; 736b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 737b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return NULL; 738b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 739b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 740b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic gint conn_bdaddr_cmp(gconstpointer a, gconstpointer b) 741b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 742b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg const struct bt_conn *conn = a; 743b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg const bdaddr_t *bdaddr = b; 744b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 745b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return bacmp(&conn->bdaddr, bdaddr); 746b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 747b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 748b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic struct bt_conn *find_connection(struct dev_info *dev, bdaddr_t *bdaddr) 749b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg{ 750bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg GSList *match; 751b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 752b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg match = g_slist_find_custom(dev->connections, bdaddr, conn_bdaddr_cmp); 753b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (match) 754b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return match->data; 755b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 756b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return NULL; 757b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 758b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 759b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic struct bt_conn *get_connection(struct dev_info *dev, bdaddr_t *bdaddr) 760b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 761b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 762b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 763b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 764b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn) 765b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return conn; 766b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 767b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = g_new0(struct bt_conn, 1); 768b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 769b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->dev = dev; 770b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_cap = dev->io_capability; 771b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0xff; 772b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->rem_auth = 0xff; 773b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bacpy(&conn->bdaddr, bdaddr); 774b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 775b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->connections = g_slist_append(dev->connections, conn); 776b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 777b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return conn; 778b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 779b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 780b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int get_handle(int index, bdaddr_t *bdaddr, uint16_t *handle) 781b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 782b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 783b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 7845a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg char addr[18]; 785b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 7865a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg ba2str(bdaddr, addr); 7875a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg DBG("hci%d dba %s", index, addr); 788b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 789b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 790b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 791bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return -ENOENT; 792b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 793bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg *handle = conn->handle; 7945a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg 795bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return 0; 796b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg} 797b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 798b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedbergstatic int disconnect_addr(int index, bdaddr_t *dba, uint8_t reason) 7995288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 8005a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg disconnect_cp cp; 8015a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg uint16_t handle; 8025a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg int err; 8035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8045a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg err = get_handle(index, dba, &handle); 8055a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg if (err < 0) 8065a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg return err; 8075288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8085a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg memset(&cp, 0, sizeof(cp)); 8095a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg cp.handle = htobs(handle); 8105a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg cp.reason = reason; 811b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 8125a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg if (hci_send_cmd(devs[index].sk, OGF_LINK_CTL, OCF_DISCONNECT, 8135a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg DISCONNECT_CP_SIZE, &cp) < 0) 8145a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg return -errno; 8155288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8165a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg return 0; 8175288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8185288199788ecb17183d6517da3062cd94692a900Johan Hedberg 819b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic void bonding_complete(struct dev_info *dev, struct bt_conn *conn, 820b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t status) 8215288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 822b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("status 0x%02x", status); 8235288199788ecb17183d6517da3062cd94692a900Johan Hedberg 824b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io != NULL) { 8251cd99f445e0a11ae936d9e80b44f504f807ce35aJohan Hedberg /* bonding_connect_cb takes care of the successul case */ 8261cd99f445e0a11ae936d9e80b44f504f807ce35aJohan Hedberg if (status != 0) 8271cd99f445e0a11ae936d9e80b44f504f807ce35aJohan Hedberg g_io_channel_shutdown(conn->io, TRUE, NULL); 828b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_unref(conn->io); 829b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->io = NULL; 830b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 8315288199788ecb17183d6517da3062cd94692a900Johan Hedberg 832b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->bonding_initiator = FALSE; 8335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 834fa41c93fe1dd04c1c25d34956d02c54f19ac3130Johan Hedberg btd_event_bonding_complete(&dev->bdaddr, &conn->bdaddr, status); 835b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 8365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 837b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth) 838b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 839b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 840b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct hci_auth_info_req req; 841b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg char addr[18]; 8425288199788ecb17183d6517da3062cd94692a900Johan Hedberg 843b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg ba2str(bdaddr, addr); 844b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("hci%d dba %s", index, addr); 845b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 846b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg memset(&req, 0, sizeof(req)); 847b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bacpy(&req.bdaddr, bdaddr); 8485288199788ecb17183d6517da3062cd94692a900Johan Hedberg 849b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (ioctl(dev->sk, HCIGETAUTHINFO, (unsigned long) &req) < 0) 850b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -errno; 851b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 852b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (auth) 853b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg *auth = req.type; 854b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 855b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 8565288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8575288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8585288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Link Key handling */ 8595288199788ecb17183d6517da3062cd94692a900Johan Hedberg 86042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void link_key_request(int index, bdaddr_t *dba) 8615288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 862fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 863b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg struct link_key_info *key_info; 864b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 865b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg GSList *match; 8660e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 8675288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8680e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(dba, da); 8690e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, da); 8705288199788ecb17183d6517da3062cd94692a900Johan Hedberg 871b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, dba); 872b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->handle == 0) 873b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->secmode3 = TRUE; 8745288199788ecb17183d6517da3062cd94692a900Johan Hedberg 875b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg get_auth_info(index, dba, &conn->loc_auth); 8765288199788ecb17183d6517da3062cd94692a900Johan Hedberg 877b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("kernel auth requirements = 0x%02x", conn->loc_auth); 8785288199788ecb17183d6517da3062cd94692a900Johan Hedberg 879b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg match = g_slist_find_custom(dev->keys, dba, (GCompareFunc) bacmp); 880b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (match) 881b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = match->data; 882b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg else 883b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = NULL; 884b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 885b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg DBG("Matching key %s", key_info ? "found" : "not found"); 886b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 887dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg if (key_info == NULL || (!dev->debug_keys && key_info->type == 0x03)) { 8885288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Link key not found */ 889fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 89042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg 6, dba); 8915288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 8925288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 8935288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8945288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Link key found */ 8955288199788ecb17183d6517da3062cd94692a900Johan Hedberg 896a61d0e8e738e905604c3339309718f3b2eadbdf7Johan Hedberg DBG("link key type 0x%02x", key_info->type); 8975288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8985288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Don't use unauthenticated combination keys if MITM is 8995288199788ecb17183d6517da3062cd94692a900Johan Hedberg * required */ 900b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_info->type == 0x04 && conn->loc_auth != 0xff && 901b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->loc_auth & 0x01)) 902fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 9035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6, dba); 9045288199788ecb17183d6517da3062cd94692a900Johan Hedberg else { 9055288199788ecb17183d6517da3062cd94692a900Johan Hedberg link_key_reply_cp lr; 9065288199788ecb17183d6517da3062cd94692a900Johan Hedberg 907a61d0e8e738e905604c3339309718f3b2eadbdf7Johan Hedberg memcpy(lr.link_key, key_info->key, 16); 9085288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&lr.bdaddr, dba); 9095288199788ecb17183d6517da3062cd94692a900Johan Hedberg 910fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_LINK_KEY_REPLY, 9115288199788ecb17183d6517da3062cd94692a900Johan Hedberg LINK_KEY_REPLY_CP_SIZE, &lr); 9125288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 9135288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 9145288199788ecb17183d6517da3062cd94692a900Johan Hedberg 91542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void link_key_notify(int index, void *ptr) 9165288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 917fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 9185288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_link_key_notify *evt = ptr; 9195288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t *dba = &evt->bdaddr; 920b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg struct link_key_info *key_info; 921b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t old_key_type, key_type; 922b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 923b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg GSList *match; 9240e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 925b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t status = 0; 9265288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9270e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(dba, da); 9280e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s type %d", index, da, evt->key_type); 9295288199788ecb17183d6517da3062cd94692a900Johan Hedberg 930b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, &evt->bdaddr); 931b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 932b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg match = g_slist_find_custom(dev->keys, dba, (GCompareFunc) bacmp); 933b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (match) 934b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = match->data; 935b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg else 936b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = NULL; 937b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 938b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (key_info == NULL) { 939b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = g_new0(struct link_key_info, 1); 940b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg bacpy(&key_info->bdaddr, &evt->bdaddr); 941c614654d76da74a51a18c7d4474a8046ca6bda01Johan Hedberg old_key_type = 0xff; 942b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } else { 943b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg dev->keys = g_slist_remove(dev->keys, key_info); 944b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg old_key_type = key_info->type; 945b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } 946b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 947b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg memcpy(key_info->key, evt->link_key, sizeof(evt->link_key)); 948b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info->type = evt->key_type; 949b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info->pin_len = dev->pin_length; 9505288199788ecb17183d6517da3062cd94692a900Johan Hedberg 951b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_type = evt->key_type; 9525288199788ecb17183d6517da3062cd94692a900Johan Hedberg 953b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("key type 0x%02x old key type 0x%02x", key_type, old_key_type); 954b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("local auth 0x%02x and remote auth 0x%02x", 955b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth, conn->rem_auth); 956b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 957b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_type == 0x06) { 958b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Some buggy controller combinations generate a changed 959b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * combination key for legacy pairing even when there's no 960b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * previous key */ 961e37b81fa945fcc41ddaee2a338a666c5736724a7Szymon Janc if (conn->rem_auth == 0xff && old_key_type == 0xff) 962b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_type = 0x00; 963b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else if (old_key_type != 0xff) 964b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_type = old_key_type; 965b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else 966b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* This is Changed Combination Link Key for 967b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * a temporary link key.*/ 968b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 969b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } 9705288199788ecb17183d6517da3062cd94692a900Johan Hedberg 971b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_info->type = key_type; 9725288199788ecb17183d6517da3062cd94692a900Johan Hedberg 973b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Skip the storage check if this is a debug key */ 974b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_type == 0x03) 975b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 976b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 977b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Store the link key persistently if one of the following is true: 978b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 1. this is a legacy link key 979b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 2. this is a changed combination key and there was a previously 980b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * stored one 981b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 3. neither local nor remote side had no-bonding as a requirement 982b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 4. the local side had dedicated bonding as a requirement 983b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 5. the remote side is using dedicated bonding since in that case 984b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * also the local requirements are set to dedicated bonding 985b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * If none of the above match only keep the link key around for 986b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * this connection and set the temporary flag for the device. 987b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg */ 988b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_type < 0x03 || (key_type == 0x06 && old_key_type != 0xff) || 989b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->loc_auth > 0x01 && conn->rem_auth > 0x01) || 990b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->loc_auth == 0x02 || conn->loc_auth == 0x03) || 991b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->rem_auth == 0x02 || conn->rem_auth == 0x03)) { 992b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg int err; 993b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 994b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg err = btd_event_link_key_notify(&dev->bdaddr, dba, 995b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg evt->link_key, key_type, 996b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->pin_length); 997b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 998b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err == -ENODEV) 999b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg status = HCI_OE_LOW_RESOURCES; 1000b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else if (err < 0) 1001b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg status = HCI_MEMORY_FULL; 1002b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1003b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 1004b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 10055288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1006b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergdone: 1007b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->pin_length = 0; 1008b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1009b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (status != 0) { 1010b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_free(key_info); 1011b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, status); 1012b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg disconnect_addr(index, dba, status); 1013b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1014b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1015b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 10165ac0142426d3e286117962cb997c5822633e43d5Johan Hedberg dev->keys = g_slist_prepend(dev->keys, key_info); 10175288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1018b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If we're connected and not dedicated bonding initiators we're 1019b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * done with the bonding process */ 1020b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!conn->bonding_initiator && conn->handle != 0) 1021b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, 0); 10225288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10235288199788ecb17183d6517da3062cd94692a900Johan Hedberg 102442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void return_link_keys(int index, void *ptr) 10255288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1026fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 10275288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_return_link_keys *evt = ptr; 10285288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = evt->num_keys; 10295288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char key[16]; 10300e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 10315288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t dba; 10325288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 10335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10340e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d num_keys %u", index, num); 10350e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 10365288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr++; 10375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10385288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 10395288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&dba, ptr); ba2str(&dba, da); 10405288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(key, ptr + 6, 16); 10415288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10420e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d returned key for %s", index, da); 10435288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1044fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_returned_link_key(&dev->bdaddr, &dba); 10455288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10465288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += 22; 10475288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 10485288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10505288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Simple Pairing handling */ 10515288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10524d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedbergstatic int hciops_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success) 10534d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg{ 10544d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg struct dev_info *dev = &devs[index]; 10554d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg user_confirm_reply_cp cp; 10564d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg char addr[18]; 10574d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg int err; 10584d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10594d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg ba2str(bdaddr, addr); 10604d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg DBG("hci%d dba %s success %d", index, addr, success); 10614d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10624d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg memset(&cp, 0, sizeof(cp)); 10634d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg bacpy(&cp.bdaddr, bdaddr); 10644d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10654d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg if (success) 10664d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 10674d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg OCF_USER_CONFIRM_REPLY, 10684d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg USER_CONFIRM_REPLY_CP_SIZE, &cp); 10694d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg else 10704d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 10714d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg OCF_USER_CONFIRM_NEG_REPLY, 10724d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg USER_CONFIRM_REPLY_CP_SIZE, &cp); 10734d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10744d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg if (err < 0) 10754d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg err = -errno; 10764d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10774d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg return err; 10784d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg} 10794d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 108042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void user_confirm_request(int index, void *ptr) 10815288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1082fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 10835288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_confirm_request *req = ptr; 10844d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg gboolean loc_mitm, rem_mitm; 1085b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 10867050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh struct agent *agent; 10875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10880e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 10890e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1090b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, &req->bdaddr); 1091b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 1092b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1093b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1094b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg loc_mitm = (conn->loc_auth & 0x01) ? TRUE : FALSE; 1095b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg rem_mitm = (conn->rem_auth & 0x01) ? TRUE : FALSE; 1096b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1097b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If we require MITM but the remote device can't provide that 1098b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 1099b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * request. The only exception is when we're dedicated bonding 1100b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * initiators since then we always have the MITM bit set. */ 1101b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!conn->bonding_initiator && loc_mitm && conn->rem_cap == 0x03) { 1102b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg error("Rejecting request: remote device can't provide MITM"); 1103b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto fail; 1104b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1105b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 11067050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh /* If local IO capabilities are DisplayYesNo and remote IO 11077050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh * capabiltiies are DisplayOnly or NoInputNoOutput; 11087050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh * call PairingConsent callback for incoming requests. */ 11097050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh if (conn->bonding_initiator == FALSE) { 11107050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh if ((conn->loc_cap == 0x01) && 11117050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh (conn->rem_cap == 0x00 || conn->rem_cap == 0x03)) { 11127050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh if (btd_event_user_consent(&dev->bdaddr, &req->bdaddr) 11137050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh < 0) 11147050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh goto fail; 11157050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh return; 11167050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh } 11177050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh } 11187050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh 1119b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If no side requires MITM protection; auto-accept */ 1120b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if ((conn->loc_auth == 0xff || !loc_mitm || conn->rem_cap == 0x03) && 1121b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (!rem_mitm || conn->loc_cap == 0x03)) { 1122b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("auto accept of confirmation"); 11234d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 11244d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg /* Wait 5 milliseconds before doing auto-accept */ 11254d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg usleep(5000); 11264d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 11274d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg if (hciops_confirm_reply(index, &req->bdaddr, TRUE) < 0) 11284d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg goto fail; 11294d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 11304d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg return; 11314d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg } 1132b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1133fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (btd_event_user_confirm(&dev->bdaddr, &req->bdaddr, 11344d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg btohl(req->passkey)) == 0) 1135b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1136b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1137b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergfail: 1138b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY, 1139b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 6, ptr); 11405288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 11415288199788ecb17183d6517da3062cd94692a900Johan Hedberg 114242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void user_passkey_request(int index, void *ptr) 11435288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1144fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 11455288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_passkey_request *req = ptr; 11465288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11470e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 11480e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1149fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (btd_event_user_passkey(&dev->bdaddr, &req->bdaddr) < 0) 1150fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, 11515288199788ecb17183d6517da3062cd94692a900Johan Hedberg OCF_USER_PASSKEY_NEG_REPLY, 6, ptr); 11525288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 11535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 115442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void user_passkey_notify(int index, void *ptr) 11555288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1156fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 11575288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_passkey_notify *req = ptr; 11585288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11590e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 11600e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1161fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_user_notify(&dev->bdaddr, &req->bdaddr, 116242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg btohl(req->passkey)); 11635288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 11645288199788ecb17183d6517da3062cd94692a900Johan Hedberg 116523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Jancstatic gint oob_bdaddr_cmp(gconstpointer a, gconstpointer b) 116623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc{ 116723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc const struct oob_data *data = a; 116823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc const bdaddr_t *bdaddr = b; 116923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 117023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return bacmp(&data->bdaddr, bdaddr); 117123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc} 117223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 117323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Jancstatic void remote_oob_data_request(int index, bdaddr_t *bdaddr) 11745288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1175fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 117623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 1177fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 11780e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 1179fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 118023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, bdaddr, oob_bdaddr_cmp); 118123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 118223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (match) { 118323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct oob_data *data; 118423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc remote_oob_data_reply_cp cp; 118523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 118623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc data = match->data; 118723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 118823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc bacpy(&cp.bdaddr, &data->bdaddr); 118923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 119023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 119123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 119223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc dev->oob_data = g_slist_delete_link(dev->oob_data, match); 119323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 119423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY, 119523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp); 119623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 119723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } else { 119823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc hci_send_cmd(dev->sk, OGF_LINK_CTL, 119923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, bdaddr); 120023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } 12015288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 12025288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1203b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int get_io_cap(int index, bdaddr_t *bdaddr, uint8_t *cap, uint8_t *auth) 1204b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 1205b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 1206b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 1207b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg int err; 1208b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1209b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 1210b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 1211b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -ENOENT; 1212b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1213b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg err = get_auth_info(index, bdaddr, &conn->loc_auth); 1214b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err < 0) 1215b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return err; 1216b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1217b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("initial authentication requirement is 0x%02x", conn->loc_auth); 1218b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1219b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!dev->pairable && !conn->bonding_initiator) { 1220b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth < 0x02) { 1221b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("Allowing no bonding in non-bondable mode"); 1222b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Kernel defaults to general bonding and so 1223b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * overwrite for this special case. Otherwise 1224b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * non-pairable test cases will fail. */ 1225b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = conn->rem_auth; 1226b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 1227b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1228b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1229b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -EPERM; 1230b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1231b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1232b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If the kernel doesn't know the local requirement just mirror 1233b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * the remote one */ 1234b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->loc_auth == 0xff) 1235b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = conn->rem_auth; 1236b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1237b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->loc_auth == 0x00 || conn->loc_auth == 0x04) { 1238b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 1239b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth == 0x02 || conn->rem_auth == 0x03) { 1240b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1241b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If both remote and local IO capabilities allow MITM 1242b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * then require it, otherwise don't */ 1243b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_cap == 0x03 || conn->loc_cap == 0x03) 1244b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0x02; 1245b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else 1246b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0x03; 1247b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1248b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1249b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If remote indicates no bonding then follow that. This 1250b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * is important since the kernel might give general bonding 1251b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * as default. */ 1252b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth == 0x00 || conn->rem_auth == 0x01) 1253b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0x00; 1254b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1255b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If remote requires MITM then also require it, unless 1256b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * our IO capability is NoInputNoOutput (so some 1257b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * just-works security cases can be tested) */ 1258b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth != 0xff && (conn->rem_auth & 0x01) && 1259b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_cap != 0x03) 1260b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth |= 0x01; 1261b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1262b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1263b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergdone: 1264b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg *cap = conn->loc_cap; 1265b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg *auth = conn->loc_auth; 1266b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1267b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("final authentication requirement is 0x%02x", *auth); 1268b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1269b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 1270b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 1271b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 127242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void io_capa_request(int index, void *ptr) 12735288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1274fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 127542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg bdaddr_t *dba = ptr; 1276b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t cap, auth = 0xff; 12770e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 1278b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg int err; 12795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12800e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(dba, da); 12810e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d IO capability request for %s", index, da); 12825288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1283b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg err = get_io_cap(index, dba, &cap, &auth); 1284b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err < 0) { 12855288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capability_neg_reply_cp cp; 1286b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1287b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg error("Getting IO capability failed: %s (%d)", 1288b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg strerror(-err), -err); 1289b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 12905288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&cp, 0, sizeof(cp)); 12915288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&cp.bdaddr, dba); 12925288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.reason = HCI_PAIRING_NOT_ALLOWED; 1293fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, 129442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg OCF_IO_CAPABILITY_NEG_REPLY, 12955288199788ecb17183d6517da3062cd94692a900Johan Hedberg IO_CAPABILITY_NEG_REPLY_CP_SIZE, &cp); 12965288199788ecb17183d6517da3062cd94692a900Johan Hedberg } else { 12975288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capability_reply_cp cp; 129823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct bt_conn *conn; 129923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 130023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 13015288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&cp, 0, sizeof(cp)); 13025288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&cp.bdaddr, dba); 13035288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.capability = cap; 13045288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.authentication = auth; 130523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 130623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc conn = find_connection(dev, dba); 130723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, dba, oob_bdaddr_cmp); 130823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 130923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if ((conn->bonding_initiator || conn->rem_oob_data == 0x01) && 131023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match) 131123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc cp.oob_data = 0x01; 131223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc else 131323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc cp.oob_data = 0x00; 131423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 1315fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY, 13165288199788ecb17183d6517da3062cd94692a900Johan Hedberg IO_CAPABILITY_REPLY_CP_SIZE, &cp); 13175288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 13185288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13195288199788ecb17183d6517da3062cd94692a900Johan Hedberg 132042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void io_capa_response(int index, void *ptr) 13215288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1322fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 13235288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_io_capability_response *evt = ptr; 1324b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 13250e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 13265288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13270e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(&evt->bdaddr, da); 13280e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d IO capability response from %s", index, da); 13295288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1330b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, &evt->bdaddr); 1331b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn) { 1332b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->rem_cap = evt->capability; 1333b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->rem_auth = evt->authentication; 133423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc conn->rem_oob_data = evt->oob_data; 1335b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 13365288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13385288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* PIN code handling */ 13395288199788ecb17183d6517da3062cd94692a900Johan Hedberg 134042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void pin_code_request(int index, bdaddr_t *dba) 13415288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1342fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1343b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 134453a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg char addr[18]; 134553a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg int err; 13465288199788ecb17183d6517da3062cd94692a900Johan Hedberg 134753a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg ba2str(dba, addr); 134853a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg DBG("hci%d PIN request for %s", index, addr); 13495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1350b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, dba); 1351b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->handle == 0) 1352b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->secmode3 = TRUE; 1353b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1354b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Check if the adapter is not pairable and if there isn't a bonding in 1355b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * progress */ 1356b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!dev->pairable && !conn->bonding_initiator) { 1357b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("Rejecting PIN request in non-pairable mode"); 1358b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto reject; 1359b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1360b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 136153a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg err = btd_event_request_pin(&dev->bdaddr, dba); 136253a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg if (err < 0) { 136353a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg error("PIN code negative reply: %s", strerror(-err)); 1364b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto reject; 13655288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 1366b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1367b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1368b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1369b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergreject: 1370b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba); 13715288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13725288199788ecb17183d6517da3062cd94692a900Johan Hedberg 137342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_features_notify(int index, void *ptr) 13745288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1375fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 13765288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_remote_host_features_notify *evt = ptr; 13775288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13785288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->features[0] & 0x01) 1379fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_set_legacy_pairing(&dev->bdaddr, &evt->bdaddr, 138042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg FALSE); 13815288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 1382fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_set_legacy_pairing(&dev->bdaddr, &evt->bdaddr, 138342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg TRUE); 13845288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1385fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg write_features_info(&dev->bdaddr, &evt->bdaddr, NULL, evt->features); 13865288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13882db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedbergstatic void write_le_host_complete(int index, uint8_t status) 13895288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1390fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 13912db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg uint8_t page_num = 0x01; 13925288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13935288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (status) 13945288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 13955288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1396fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_INFO_PARAM, 13972db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg OCF_READ_LOCAL_EXT_FEATURES, 1, &page_num) < 0) 13982db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg error("Unable to read extended local features: %s (%d)", 13992db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg strerror(errno), errno); 14005288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 14015288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1402be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedbergstatic void read_local_version_complete(int index, 1403be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg const read_local_version_rp *rp) 1404be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg{ 1405fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1406fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 1407be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg if (rp->status) 1408be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1409be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1410fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.manufacturer = btohs(bt_get_unaligned(&rp->manufacturer)); 1411fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.hci_ver = rp->hci_ver; 1412fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.hci_rev = btohs(bt_get_unaligned(&rp->hci_rev)); 1413fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_ver = rp->lmp_ver; 1414fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_subver = btohs(bt_get_unaligned(&rp->lmp_subver)); 1415be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1416fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 1417be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1418be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1419fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_VERSION, &dev->pending); 1420be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1421be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg DBG("Got version for hci%d", index); 1422be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1423fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending && dev->up) 14245c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 1425be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg} 1426be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1427be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedbergstatic void read_local_features_complete(int index, 1428be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg const read_local_features_rp *rp) 1429be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg{ 1430fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1431fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 1432be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg if (rp->status) 1433be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1434be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1435fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->features, rp->features, 8); 1436be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1437fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 1438be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1439be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1440fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_FEATURES, &dev->pending); 1441be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1442be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg DBG("Got features for hci%d", index); 1443be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1444fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending && dev->up) 14455c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 1446be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg} 1447be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 144800c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic void update_ext_inquiry_response(int index) 144900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1450fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 145100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_ext_inquiry_response_cp cp; 145200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 145300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d", index); 145400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1455fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[6] & LMP_EXT_INQ)) 145600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 145700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1458fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ssp_mode == 0) 145900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 146000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1461fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->cache_enable) 146200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 146300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 146400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memset(&cp, 0, sizeof(cp)); 146500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1466991a7a4f09049c91297d74f9d28497fad166268eClaudio Takahasi eir_create(dev->name, dev->tx_power, dev->did_vendor, dev->did_product, 1467991a7a4f09049c91297d74f9d28497fad166268eClaudio Takahasi dev->did_version, dev->uuids, cp.data); 146800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1469fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (memcmp(cp.data, dev->eir, sizeof(cp.data)) == 0) 147000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 147100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1472fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->eir, cp.data, sizeof(cp.data)); 147300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1474fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, 147500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg OCF_WRITE_EXT_INQUIRY_RESPONSE, 147600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0) 147700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg error("Unable to write EIR data: %s (%d)", 147800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg strerror(errno), errno); 147900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 148000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 148119084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedbergstatic void update_name(int index, const char *name) 148219084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg{ 148319084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg struct btd_adapter *adapter; 148419084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg 1485f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg adapter = manager_find_adapter_by_id(index); 148619084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg if (adapter) 148719084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg adapter_update_local_name(adapter, name); 148800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 148900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 149019084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg} 149119084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg 1492fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedbergstatic void read_local_name_complete(int index, read_local_name_rp *rp) 1493fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg{ 1494fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1495fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 14960e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 14970e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1498fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg if (rp->status) 1499fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg return; 1500fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1501fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->name, rp->name, 248); 150200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1503fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) { 150419084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg update_name(index, (char *) rp->name); 1505fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg return; 1506fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg } 1507fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1508fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_NAME, &dev->pending); 1509fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1510fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg DBG("Got name for hci%d", index); 1511fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 15129f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg /* Even though it shouldn't happen (assuming the kernel behaves 15139f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * properly) it seems like we might miss the very first 15149f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * initialization commands that the kernel sends. So check for 15159f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * it here (since read_local_name is one of the last init 15169f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * commands) and resend the first ones if we haven't seen 15179f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * their results yet */ 15189f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg 1519fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_test_bit(PENDING_FEATURES, &dev->pending)) 1520fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_INFO_PARAM, 15219f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg OCF_READ_LOCAL_FEATURES, 0, NULL); 15229f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg 1523fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_test_bit(PENDING_VERSION, &dev->pending)) 1524fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_INFO_PARAM, 15259f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg OCF_READ_LOCAL_VERSION, 0, NULL); 15269f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg 15274f8d6ba3531fc2d27d17a54e073e3db529fc1cf5Johan Hedberg if (!dev->pending && dev->up) 15285c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 1529fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg} 1530fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1531e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedbergstatic void read_tx_power_complete(int index, void *ptr) 1532e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg{ 1533fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1534fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 1535e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg read_inq_response_tx_power_level_rp *rp = ptr; 1536e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg 15370e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15380e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1539e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg if (rp->status) 1540e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg return; 1541e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg 1542fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->tx_power = rp->level; 154300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 1544e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg} 1545e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg 1546af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedbergstatic void read_simple_pairing_mode_complete(int index, void *ptr) 1547af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg{ 1548700d2ae37c0008e87bc7d3e25027cf80b8ba98e5Johan Hedberg struct dev_info *dev = &devs[index]; 1549af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg read_simple_pairing_mode_rp *rp = ptr; 1550af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg 15510e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15520e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1553af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg if (rp->status) 1554af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg return; 1555af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg 1556fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ssp_mode = rp->mode; 155700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 1558af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg} 1559af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg 15600e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedbergstatic void read_local_ext_features_complete(int index, 15615288199788ecb17183d6517da3062cd94692a900Johan Hedberg const read_local_ext_features_rp *rp) 15625288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 156394e7feb45fb9938d4d8f7363dfc7dee34940389eAndre Guedes struct dev_info *dev = &devs[index]; 15645288199788ecb17183d6517da3062cd94692a900Johan Hedberg 15650e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15660e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 15675288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (rp->status) 15685288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 15695288199788ecb17183d6517da3062cd94692a900Johan Hedberg 15705288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Local Extended feature page number is 1 */ 15715288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (rp->page_num != 1) 15725288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 15735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 157494e7feb45fb9938d4d8f7363dfc7dee34940389eAndre Guedes memcpy(dev->extfeatures, rp->features, sizeof(dev->extfeatures)); 15755288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 15765288199788ecb17183d6517da3062cd94692a900Johan Hedberg 15775a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedbergstatic void read_bd_addr_complete(int index, read_bd_addr_rp *rp) 15785a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg{ 1579fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1580fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 15810e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15820e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 15835a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg if (rp->status) 15845a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg return; 15855a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1586fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(&dev->bdaddr, &rp->bdaddr); 15875a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1588fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 15895a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg return; 15905a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1591fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_BDADDR, &dev->pending); 15925a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 159328c405b17a3131494c11599705885ae630c52ee2Johan Hedberg DBG("Got bdaddr for hci%d", index); 15945a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1595fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending && dev->up) 15965c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 15975a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg} 15985a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 15992a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void cs_inquiry_evt(int index, uint8_t status) 16002a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 16012a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 16022a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("Inquiry Failed with status 0x%02x", status); 16032a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 16042a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 16052a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 16062a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_INQ); 16072a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 16082a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 160942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void cmd_status(int index, void *ptr) 16105288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 16115288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_status *evt = ptr; 16125288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint16_t opcode = btohs(evt->opcode); 16135288199788ecb17183d6517da3062cd94692a900Johan Hedberg 16145288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY)) 16152a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes cs_inquiry_evt(index, evt->status); 16165288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 16175288199788ecb17183d6517da3062cd94692a900Johan Hedberg 161842bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void read_scan_complete(int index, uint8_t status, void *ptr) 16195288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 16205288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 16215288199788ecb17183d6517da3062cd94692a900Johan Hedberg read_scan_enable_rp *rp = ptr; 16225288199788ecb17183d6517da3062cd94692a900Johan Hedberg 16230e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, status); 16240e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1625f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg adapter = manager_find_adapter_by_id(index); 16265288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 16275288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Unable to find matching adapter"); 16285288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 16295288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 16305288199788ecb17183d6517da3062cd94692a900Johan Hedberg 16315288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_mode_changed(adapter, rp->enable); 16325288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 16335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1634914a9093c108cf67a1ef08bffc7db2e4c9a5b1b9Johan Hedbergstatic int write_class(int index, uint32_t class) 163500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1636fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 163700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_class_of_dev_cp cp; 163800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 163900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d class 0x%06x", index, class); 164000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 164100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memcpy(cp.dev_class, &class, 3); 164200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1643fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, 164400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0) 164500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return -errno; 164600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1647fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->pending_cod = class; 164800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 164900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 165000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 165100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 165200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg/* Limited Discoverable bit mask in CoD */ 165300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg#define LIMITED_BIT 0x002000 165400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 165500c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_set_limited_discoverable(int index, gboolean limited) 165600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1657fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 165800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg int num = (limited ? 2 : 1); 165900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e }; 166000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_current_iac_lap_cp cp; 166100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 166200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d limited %d", index, limited); 166300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 166400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Check if limited bit needs to be set/reset */ 166500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (limited) 1666fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod |= LIMITED_BIT; 166700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg else 1668fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod &= ~LIMITED_BIT; 166900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 167000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* If we dont need the toggling, save an unnecessary CoD write */ 1671fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->pending_cod || dev->wanted_cod == dev->current_cod) 167200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 167300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 167400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* 167500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * 1: giac 167600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * 2: giac + liac 167700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg */ 167800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memset(&cp, 0, sizeof(cp)); 167900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg cp.num_current_iac = num; 168000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memcpy(&cp.lap, lap, num * 3); 168100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1682fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP, 168300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg (num * 3 + 1), &cp) < 0) 168400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return -errno; 168500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1686fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg return write_class(index, dev->wanted_cod); 168700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 168800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 168900c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic void write_class_complete(int index, uint8_t status) 169000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1691fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 169200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg struct btd_adapter *adapter; 169300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 169400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (status) 169500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 169600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1697fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->pending_cod == 0) 169800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 169900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1700fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->current_cod = dev->pending_cod; 1701fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->pending_cod = 0; 170200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1703fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg adapter = manager_find_adapter(&dev->bdaddr); 170400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (adapter) 1705fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_adapter_class_changed(adapter, dev->current_cod); 170600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 170700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 170800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1709fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->wanted_cod == dev->current_cod) 171000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 171100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1712fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->wanted_cod & LIMITED_BIT && 1713fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg !(dev->current_cod & LIMITED_BIT)) 171400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg hciops_set_limited_discoverable(index, TRUE); 1715fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg else if (!(dev->wanted_cod & LIMITED_BIT) && 1716fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg (dev->current_cod & LIMITED_BIT)) 171700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg hciops_set_limited_discoverable(index, FALSE); 171800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg else 1719fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg write_class(index, dev->wanted_cod); 172000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 172100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 172223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Jancstatic void read_local_oob_data_complete(int index, uint8_t status, 172323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc read_local_oob_data_rp *rp) 172423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc{ 172523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct btd_adapter *adapter = manager_find_adapter_by_id(index); 172623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 172723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (!adapter) 172823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return; 172923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 173023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (status) 173123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc oob_read_local_data_complete(adapter, NULL, NULL); 173223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc else 173323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc oob_read_local_data_complete(adapter, rp->hash, rp->randomizer); 173423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc} 173523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 17362a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void inquiry_complete_evt(int index, uint8_t status) 17372a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 17388be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes int adapter_type; 17398be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes struct btd_adapter *adapter; 17408be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 17412a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 17422a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("Inquiry Failed with status 0x%02x", status); 17432a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 17442a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 17452a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17468be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter = manager_find_adapter_by_id(index); 17478be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (!adapter) { 17488be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes error("No matching adapter found"); 17498be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return; 17508be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } 17518be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 17528be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_type = get_adapter_type(index); 17538be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 17548be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (adapter_type == BR_EDR_LE && 17558be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_has_discov_sessions(adapter)) { 17568be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes int err = hciops_start_scanning(index, TIMEOUT_BR_LE_SCAN); 17578be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (err < 0) 17588be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes set_state(index, DISCOV_HALTED); 17598be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } else { 17608be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes set_state(index, DISCOV_HALTED); 17618be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } 17622a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 17632a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17642a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void cc_inquiry_cancel(int index, uint8_t status) 17652a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 17662a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 17672a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("Inquiry Cancel Failed with status 0x%02x", status); 17682a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 17692a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 17702a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17712a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_HALTED); 17722a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 17732a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17742a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void cc_le_set_scan_enable(int index, uint8_t status) 17752a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 17762a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes int state; 17772a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17782a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 17792a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("LE Set Scan Enable Failed with status 0x%02x", status); 17802a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 17812a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 17822a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17832a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes state = get_state(index); 17842a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (state == DISCOV_SCAN) 17852a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_HALTED); 17862a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes else 17872a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_SCAN); 17882a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 17892a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 179042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void cmd_complete(int index, void *ptr) 17915288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1792fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 17935288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_complete *evt = ptr; 17945288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint16_t opcode = btohs(evt->opcode); 17955288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t status = *((uint8_t *) ptr + EVT_CMD_COMPLETE_SIZE); 17965288199788ecb17183d6517da3062cd94692a900Johan Hedberg 17975288199788ecb17183d6517da3062cd94692a900Johan Hedberg switch (opcode) { 1798be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION): 1799be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg ptr += sizeof(evt_cmd_complete); 1800be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg read_local_version_complete(index, ptr); 1801be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg break; 1802be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES): 1803be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg ptr += sizeof(evt_cmd_complete); 1804be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg read_local_features_complete(index, ptr); 1805be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg break; 18065288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_EXT_FEATURES): 18075288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 18080e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg read_local_ext_features_complete(index, ptr); 18095288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18105a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BD_ADDR): 18115a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg ptr += sizeof(evt_cmd_complete); 18125a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg read_bd_addr_complete(index, ptr); 18135a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg break; 18145288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL): 18152a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes cc_inquiry_cancel(index, status); 18165288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18175288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_LE_HOST_SUPPORTED): 18182db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg write_le_host_complete(index, status); 18195288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18205288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE): 18212a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes cc_le_set_scan_enable(index, status); 18225288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18235288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME): 1824bd7f8939b50a12418476245f9b5117801f858b02Johan Hedberg if (!status) 1825fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, 1826bd7f8939b50a12418476245f9b5117801f858b02Johan Hedberg OCF_READ_LOCAL_NAME, 0, 0); 18275288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18285288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE): 1829073c798c8f77c9d63aa4008c2c56cd645f68c7afJohan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_SCAN_ENABLE, 1830073c798c8f77c9d63aa4008c2c56cd645f68c7afJohan Hedberg 0, NULL); 18315288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18325288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SCAN_ENABLE): 18335288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 183442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg read_scan_complete(index, status, ptr); 18355288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18365288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV): 183700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_class_complete(index, status); 18385288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18395288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SIMPLE_PAIRING_MODE): 18407afa48dcf311926269dcfb8ec1a2a12c94eb2d5bJohan Hedberg if (!status) 1841fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, 18427afa48dcf311926269dcfb8ec1a2a12c94eb2d5bJohan Hedberg OCF_READ_SIMPLE_PAIRING_MODE, 0, NULL); 18435288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18445288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SIMPLE_PAIRING_MODE): 18455288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 1846af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg read_simple_pairing_mode_complete(index, ptr); 18475288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18485288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_NAME): 18495288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 1850fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg read_local_name_complete(index, ptr); 18515288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 1852e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, 1853e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL): 18545288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 1855e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg read_tx_power_complete(index, ptr); 18565288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 185723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA): 185823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc ptr += sizeof(evt_cmd_complete); 185923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc read_local_oob_data_complete(index, status, ptr); 186023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc break; 18615288199788ecb17183d6517da3062cd94692a900Johan Hedberg }; 18625288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 18635288199788ecb17183d6517da3062cd94692a900Johan Hedberg 186442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_name_information(int index, void *ptr) 18655288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1866fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 18675288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_remote_name_req_complete *evt = ptr; 18685288199788ecb17183d6517da3062cd94692a900Johan Hedberg char name[MAX_NAME_LENGTH + 1]; 18695288199788ecb17183d6517da3062cd94692a900Johan Hedberg 18700e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 18710e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 18725288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(name, 0, sizeof(name)); 18735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 18745288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!evt->status) 18755288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(name, evt->name, MAX_NAME_LENGTH); 18765288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1877fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_remote_name(&dev->bdaddr, &evt->bdaddr, evt->status, name); 18785288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 18795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 188042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_version_information(int index, void *ptr) 18815288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1882fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 18835288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_read_remote_version_complete *evt = ptr; 1884b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 18855288199788ecb17183d6517da3062cd94692a900Johan Hedberg 18860e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 18870e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 18885288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->status) 18895288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 18905288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1891b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 1892b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 18935288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 18945288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1895b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg write_version_info(&dev->bdaddr, &conn->bdaddr, 1896b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg btohs(evt->manufacturer), evt->lmp_ver, 1897b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg btohs(evt->lmp_subver)); 18985288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 18995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 190042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void inquiry_result(int index, int plen, void *ptr) 19015288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1902fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19035288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 19045288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 19055288199788ecb17183d6517da3062cd94692a900Johan Hedberg 190617baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes /* Skip if it is not in Inquiry state */ 190717baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes if (get_state(index) != DISCOV_INQ) 190817baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return; 190917baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes 19105288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19115288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info *info = ptr; 191242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg uint32_t class = info->dev_class[0] | 191342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg (info->dev_class[1] << 8) | 191442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg (info->dev_class[2] << 16); 19155288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1916b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, class, 191742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg 0, NULL); 19185288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_SIZE; 19195288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19205288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19215288199788ecb17183d6517da3062cd94692a900Johan Hedberg 192242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void inquiry_result_with_rssi(int index, int plen, void *ptr) 19235288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1924fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19255288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 19265288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 19275288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19285288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!num) 19295288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 19305288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19315288199788ecb17183d6517da3062cd94692a900Johan Hedberg if ((plen - 1) / num == INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE) { 19325288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19335288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info_with_rssi_and_pscan_mode *info = ptr; 19345288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 193542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[1] << 8) 193642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[2] << 16); 19375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1938b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, 19395288199788ecb17183d6517da3062cd94692a900Johan Hedberg class, info->rssi, NULL); 19405288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE; 19415288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19425288199788ecb17183d6517da3062cd94692a900Johan Hedberg } else { 19435288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19445288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info_with_rssi *info = ptr; 19455288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 194642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[1] << 8) 194742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[2] << 16); 19485288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1949b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, 19505288199788ecb17183d6517da3062cd94692a900Johan Hedberg class, info->rssi, NULL); 19515288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_WITH_RSSI_SIZE; 19525288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19535288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19545288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19555288199788ecb17183d6517da3062cd94692a900Johan Hedberg 195642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void extended_inquiry_result(int index, int plen, void *ptr) 19575288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1958fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19595288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 19605288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 19615288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19625288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19635288199788ecb17183d6517da3062cd94692a900Johan Hedberg extended_inquiry_info *info = ptr; 19645288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 196542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[1] << 8) 196642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[2] << 16); 19675288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1968b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, class, 19695288199788ecb17183d6517da3062cd94692a900Johan Hedberg info->rssi, info->data); 19705288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += EXTENDED_INQUIRY_INFO_SIZE; 19715288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19725288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 197442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_features_information(int index, void *ptr) 19755288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1976fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19775288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_read_remote_features_complete *evt = ptr; 1978b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 19795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19800e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 19810e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 19825288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->status) 19835288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 19845288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1985b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 1986b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 19875288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 19885288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1989b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg write_features_info(&dev->bdaddr, &conn->bdaddr, evt->features, NULL); 19905288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19928e17ca3a784294aec947866071c38d934e21940dJohan Hedbergstruct remote_version_req { 19938e17ca3a784294aec947866071c38d934e21940dJohan Hedberg int index; 19948e17ca3a784294aec947866071c38d934e21940dJohan Hedberg uint16_t handle; 19958e17ca3a784294aec947866071c38d934e21940dJohan Hedberg}; 19968e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 19978e17ca3a784294aec947866071c38d934e21940dJohan Hedbergstatic gboolean __get_remote_version(gpointer user_data) 19988e17ca3a784294aec947866071c38d934e21940dJohan Hedberg{ 19998e17ca3a784294aec947866071c38d934e21940dJohan Hedberg struct remote_version_req *req = user_data; 20008e17ca3a784294aec947866071c38d934e21940dJohan Hedberg struct dev_info *dev = &devs[req->index]; 20018e17ca3a784294aec947866071c38d934e21940dJohan Hedberg read_remote_version_cp cp; 20028e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20038e17ca3a784294aec947866071c38d934e21940dJohan Hedberg DBG("hci%d handle %u", req->index, req->handle); 20048e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20058e17ca3a784294aec947866071c38d934e21940dJohan Hedberg memset(&cp, 0, sizeof(cp)); 20068e17ca3a784294aec947866071c38d934e21940dJohan Hedberg cp.handle = htobs(req->handle); 20078e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20088e17ca3a784294aec947866071c38d934e21940dJohan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_READ_REMOTE_VERSION, 20098e17ca3a784294aec947866071c38d934e21940dJohan Hedberg READ_REMOTE_VERSION_CP_SIZE, &cp); 20108e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20118e17ca3a784294aec947866071c38d934e21940dJohan Hedberg return FALSE; 20128e17ca3a784294aec947866071c38d934e21940dJohan Hedberg} 20138e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20148e17ca3a784294aec947866071c38d934e21940dJohan Hedbergstatic void get_remote_version(int index, uint16_t handle) 20158e17ca3a784294aec947866071c38d934e21940dJohan Hedberg{ 20168e17ca3a784294aec947866071c38d934e21940dJohan Hedberg struct remote_version_req *req; 20178e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20188e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req = g_new0(struct remote_version_req, 1); 20198e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req->handle = handle; 20208e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req->index = index; 20218e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20228e17ca3a784294aec947866071c38d934e21940dJohan Hedberg g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 1, __get_remote_version, 20238e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req, g_free); 20248e17ca3a784294aec947866071c38d934e21940dJohan Hedberg} 20258e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 2026b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic void conn_free(struct bt_conn *conn) 2027b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 2028b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io != NULL) { 2029b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_shutdown(conn->io, TRUE, NULL); 2030b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_unref(conn->io); 2031b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 2032b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 2033b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_free(conn); 2034b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 2035b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 203632c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedbergstatic inline void conn_failed(int index, bdaddr_t *bdaddr, uint8_t status) 203732c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg{ 203832c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg struct dev_info *dev = &devs[index]; 203932c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg struct bt_conn *conn; 204032c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 2041b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg btd_event_conn_failed(&dev->bdaddr, bdaddr, status); 204232c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 204332c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn = find_connection(dev, bdaddr); 204432c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg if (conn == NULL) 204532c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg return; 204632c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 2047d4a25e44a88e15da6f523183b30997e6669c481dJohan Hedberg bonding_complete(dev, conn, status); 204832c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 204932c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg dev->connections = g_slist_remove(dev->connections, conn); 205032c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn_free(conn); 205132c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg} 205232c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 205342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void conn_complete(int index, void *ptr) 20545288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2055fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 20565288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_conn_complete *evt = ptr; 20575288199788ecb17183d6517da3062cd94692a900Johan Hedberg char filename[PATH_MAX]; 20585288199788ecb17183d6517da3062cd94692a900Johan Hedberg char local_addr[18], peer_addr[18], *str; 2059b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 20605288199788ecb17183d6517da3062cd94692a900Johan Hedberg 20615288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->link_type != ACL_LINK) 20625288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 20635288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2064b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("status 0x%02x", evt->status); 2065bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 206632c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg if (evt->status != 0) { 206732c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn_failed(index, &evt->bdaddr, evt->status); 206832c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg return; 2069bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg } 2070bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 207132c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn = get_connection(dev, &evt->bdaddr); 207232c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn->handle = btohs(evt->handle); 20735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2074b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg btd_event_conn_complete(&dev->bdaddr, &evt->bdaddr); 20755288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2076b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->secmode3) 2077b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, 0); 2078b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 20795288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* check if the remote version needs be requested */ 2080fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg ba2str(&dev->bdaddr, local_addr); 20815288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(&evt->bdaddr, peer_addr); 20825288199788ecb17183d6517da3062cd94692a900Johan Hedberg 20835288199788ecb17183d6517da3062cd94692a900Johan Hedberg create_name(filename, sizeof(filename), STORAGEDIR, local_addr, 20845288199788ecb17183d6517da3062cd94692a900Johan Hedberg "manufacturers"); 20855288199788ecb17183d6517da3062cd94692a900Johan Hedberg 20865288199788ecb17183d6517da3062cd94692a900Johan Hedberg str = textfile_get(filename, peer_addr); 20875288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!str) 20888e17ca3a784294aec947866071c38d934e21940dJohan Hedberg get_remote_version(index, btohs(evt->handle)); 20895288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 20905288199788ecb17183d6517da3062cd94692a900Johan Hedberg free(str); 20915288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 20925288199788ecb17183d6517da3062cd94692a900Johan Hedberg 20935f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demariostatic inline void le_conn_complete(int index, void *ptr) 20945f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario{ 2095fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 20965f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario evt_le_connection_complete *evt = ptr; 20975f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario char filename[PATH_MAX]; 20985f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario char local_addr[18], peer_addr[18], *str; 2099b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg struct bt_conn *conn; 21005f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 2101b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg if (evt->status) { 2102b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg btd_event_conn_failed(&dev->bdaddr, &evt->peer_bdaddr, 2103b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg evt->status); 2104b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg return; 2105bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg } 2106bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2107b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg conn = get_connection(dev, &evt->peer_bdaddr); 2108b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg conn->handle = btohs(evt->handle); 21095f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 2110b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg btd_event_conn_complete(&dev->bdaddr, &evt->peer_bdaddr); 21115f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 21125f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario /* check if the remote version needs be requested */ 2113fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg ba2str(&dev->bdaddr, local_addr); 21145f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario ba2str(&evt->peer_bdaddr, peer_addr); 21155f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 21165f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario create_name(filename, sizeof(filename), STORAGEDIR, local_addr, 21175f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario "manufacturers"); 21185f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 21195f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario str = textfile_get(filename, peer_addr); 21205f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario if (!str) 21218e17ca3a784294aec947866071c38d934e21940dJohan Hedberg get_remote_version(index, btohs(evt->handle)); 21225f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario else 21235f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario free(str); 21245f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario} 21255f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 212642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void disconn_complete(int index, void *ptr) 21275288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2128fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21295288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_disconn_complete *evt = ptr; 2130b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 2131b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 2132b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("handle %u status 0x%02x", btohs(evt->handle), evt->status); 2133bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2134bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg if (evt->status != 0) 2135bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return; 21365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2137b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 2138b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 2139bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return; 2140bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2141b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->connections = g_slist_remove(dev->connections, conn); 2142bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2143bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg btd_event_disconn_complete(&dev->bdaddr, &conn->bdaddr); 2144bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2145b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn_free(conn); 21465288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21475288199788ecb17183d6517da3062cd94692a900Johan Hedberg 214842bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void auth_complete(int index, void *ptr) 21495288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2150fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21515288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_auth_complete *evt = ptr; 2152b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 21535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 21540e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 21550e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2156b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 2157b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 21585288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 21595288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2160b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, evt->status); 21615288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21625288199788ecb17183d6517da3062cd94692a900Johan Hedberg 216342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void simple_pairing_complete(int index, void *ptr) 21645288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2165fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21665288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_simple_pairing_complete *evt = ptr; 21675288199788ecb17183d6517da3062cd94692a900Johan Hedberg 21680e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 21690e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2170fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_simple_pairing_complete(&dev->bdaddr, &evt->bdaddr, 217142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg evt->status); 21725288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 217442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void conn_request(int index, void *ptr) 21755288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2176fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21775288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_conn_request *evt = ptr; 21785288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = evt->dev_class[0] | (evt->dev_class[1] << 8) 21795288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (evt->dev_class[2] << 16); 21805288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2181fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_remote_class(&dev->bdaddr, &evt->bdaddr, class); 21825288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 21845f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demariostatic inline void le_advertising_report(int index, evt_le_meta_event *meta) 21855288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2186fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21875288199788ecb17183d6517da3062cd94692a900Johan Hedberg le_advertising_info *info; 2188f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira uint8_t num_reports, rssi, eir[HCI_MAX_EIR_LENGTH]; 2189e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes const uint8_t RSSI_SIZE = 1; 21905288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2191e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes num_reports = meta->data[0]; 21925288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2193e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes info = (le_advertising_info *) &meta->data[1]; 21945b1f949a427b39091959537f196c5d322997453fBruna Moreira rssi = *(info->data + info->length); 21955b1f949a427b39091959537f196c5d322997453fBruna Moreira 2196f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memset(eir, 0, sizeof(eir)); 2197f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memcpy(eir, info->data, info->length); 2198f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira 2199f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira btd_event_device_found(&dev->bdaddr, &info->bdaddr, 0, rssi, eir); 22005b1f949a427b39091959537f196c5d322997453fBruna Moreira 2201e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes num_reports--; 2202e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes 2203e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes while (num_reports--) { 2204e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes info = (le_advertising_info *) (info->data + info->length + 2205e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes RSSI_SIZE); 22065b1f949a427b39091959537f196c5d322997453fBruna Moreira rssi = *(info->data + info->length); 22075b1f949a427b39091959537f196c5d322997453fBruna Moreira 2208f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memset(eir, 0, sizeof(eir)); 2209f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memcpy(eir, info->data, info->length); 2210f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira 22115b1f949a427b39091959537f196c5d322997453fBruna Moreira btd_event_device_found(&dev->bdaddr, &info->bdaddr, 0, rssi, 2212f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira eir); 22135288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 22145288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 22155288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22165f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demariostatic inline void le_metaevent(int index, void *ptr) 22175f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario{ 22185f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario evt_le_meta_event *meta = ptr; 22195f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 22205f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario DBG("hci%d LE Meta Event %u", index, meta->subevent); 22215f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 22225f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario switch (meta->subevent) { 22235f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario case EVT_LE_ADVERTISING_REPORT: 22245f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario le_advertising_report(index, meta); 22255f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario break; 22265f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 22275f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario case EVT_LE_CONN_COMPLETE: 22285f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario le_conn_complete(index, meta->data); 22295f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario break; 22305f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario } 22315f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario} 22325f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 223355694454017b04a416931a81964bb695f48b3d93Johan Hedbergstatic void stop_hci_dev(int index) 22345288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2235fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 22365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2237b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->sk < 0) 22385288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 22395288199788ecb17183d6517da3062cd94692a900Johan Hedberg 224055694454017b04a416931a81964bb695f48b3d93Johan Hedberg info("Stopping hci%d event socket", index); 22415288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2242b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->watch_id > 0) 2243b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_source_remove(dev->watch_id); 2244b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 22459235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (dev->stop_scan_id > 0) 22469235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes g_source_remove(dev->stop_scan_id); 22479235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 2248b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->io != NULL) 2249b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_io_channel_unref(dev->io); 2250b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 2251fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_close_dev(dev->sk); 2252b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 2253b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_slist_foreach(dev->keys, (GFunc) g_free, NULL); 2254b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_slist_free(dev->keys); 2255b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 22563e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg g_slist_foreach(dev->uuids, (GFunc) g_free, NULL); 22573e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg g_slist_free(dev->uuids); 22583e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 2259b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_slist_foreach(dev->connections, (GFunc) conn_free, NULL); 2260bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg g_slist_free(dev->connections); 2261bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2262149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz init_dev_info(index, -1, dev->registered, dev->already_up); 22635288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 22645288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22655288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic gboolean io_security_event(GIOChannel *chan, GIOCondition cond, 22665288199788ecb17183d6517da3062cd94692a900Johan Hedberg gpointer data) 22675288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 22685288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf; 226942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg int type, index = GPOINTER_TO_INT(data); 2270fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 227142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg struct hci_dev_info di; 227290e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz ssize_t len; 22735288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_event_hdr *eh; 22745288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_status *evt; 227590e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz int fd; 22765288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22775288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { 227855694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 22795288199788ecb17183d6517da3062cd94692a900Johan Hedberg return FALSE; 22805288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 22815288199788ecb17183d6517da3062cd94692a900Johan Hedberg 228290e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz fd = g_io_channel_unix_get_fd(chan); 228390e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz 228490e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz len = read(fd, buf, sizeof(buf)); 228590e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (len < 0) { 228690e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (errno == EAGAIN) 22875288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 228855694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 22895288199788ecb17183d6517da3062cd94692a900Johan Hedberg return FALSE; 22905288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 22915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22925288199788ecb17183d6517da3062cd94692a900Johan Hedberg type = *ptr++; 22935288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22945288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (type != HCI_EVENT_PKT) 22955288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 22965288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22975288199788ecb17183d6517da3062cd94692a900Johan Hedberg eh = (hci_event_hdr *) ptr; 22985288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += HCI_EVENT_HDR_SIZE; 22995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 230042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg memset(&di, 0, sizeof(di)); 230142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg if (hci_devinfo(index, &di) == 0) { 2302fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(&dev->bdaddr, &di.bdaddr); 23035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 230442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg if (ignore_device(&di)) 230542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg return TRUE; 230642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg } 230755694454017b04a416931a81964bb695f48b3d93Johan Hedberg 23085288199788ecb17183d6517da3062cd94692a900Johan Hedberg switch (eh->evt) { 23095288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CMD_STATUS: 231042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg cmd_status(index, ptr); 23115288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23135288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CMD_COMPLETE: 231442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg cmd_complete(index, ptr); 23155288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23165288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23175288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_NAME_REQ_COMPLETE: 231842bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_name_information(index, ptr); 23195288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23215288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_READ_REMOTE_VERSION_COMPLETE: 232242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_version_information(index, ptr); 23235288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23245288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23255288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_READ_REMOTE_FEATURES_COMPLETE: 232642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_features_information(index, ptr); 23275288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23285288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23295288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_HOST_FEATURES_NOTIFY: 233042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_features_notify(index, ptr); 23315288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23325288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23335288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_COMPLETE: 23345288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt = (evt_cmd_status *) ptr; 23352a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes inquiry_complete_evt(index, evt->status); 23365288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23385288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_RESULT: 233942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg inquiry_result(index, eh->plen, ptr); 23405288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23415288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23425288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_RESULT_WITH_RSSI: 234342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg inquiry_result_with_rssi(index, eh->plen, ptr); 23445288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23455288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23465288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_EXTENDED_INQUIRY_RESULT: 234742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg extended_inquiry_result(index, eh->plen, ptr); 23485288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23505288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CONN_COMPLETE: 235142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg conn_complete(index, ptr); 23525288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23545288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_DISCONN_COMPLETE: 235542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg disconn_complete(index, ptr); 23565288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23575288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23585288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_AUTH_COMPLETE: 235942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg auth_complete(index, ptr); 23605288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23615288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23625288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_SIMPLE_PAIRING_COMPLETE: 236342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg simple_pairing_complete(index, ptr); 23645288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23655288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23665288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CONN_REQUEST: 236742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg conn_request(index, ptr); 23685288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23695288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LE_META_EVENT: 237042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg le_metaevent(index, ptr); 23715288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23725288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_PIN_CODE_REQ: 237342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg pin_code_request(index, (bdaddr_t *) ptr); 23745288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23755288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23765288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LINK_KEY_REQ: 237742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg link_key_request(index, (bdaddr_t *) ptr); 23785288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23805288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LINK_KEY_NOTIFY: 238142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg link_key_notify(index, ptr); 23825288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23845288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_RETURN_LINK_KEYS: 238542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg return_link_keys(index, ptr); 23865288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23885288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_IO_CAPABILITY_REQUEST: 238942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg io_capa_request(index, ptr); 23905288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23925288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_IO_CAPABILITY_RESPONSE: 239342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg io_capa_response(index, ptr); 23945288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23955288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23965288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_CONFIRM_REQUEST: 239742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg user_confirm_request(index, ptr); 23985288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24005288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_PASSKEY_REQUEST: 240142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg user_passkey_request(index, ptr); 24025288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24045288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_PASSKEY_NOTIFY: 240542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg user_passkey_notify(index, ptr); 24065288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24075288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24085288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_OOB_DATA_REQUEST: 240923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc remote_oob_data_request(index, (bdaddr_t *) ptr); 24105288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24115288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 24125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24135288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 24145288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 24155288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24165a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedbergstatic void start_hci_dev(int index) 24175288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2418fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2419fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg GIOChannel *chan = dev->io; 2420e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg GIOCondition cond; 24215288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_filter flt; 24225288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24235288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (chan) 24245288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 24255288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24265a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg info("Listening for HCI events on hci%d", index); 24275288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24285288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Set filter */ 24295288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_clear(&flt); 24305288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 24315288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CMD_STATUS, &flt); 24325288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CMD_COMPLETE, &flt); 24335288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_PIN_CODE_REQ, &flt); 24345288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LINK_KEY_REQ, &flt); 24355288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LINK_KEY_NOTIFY, &flt); 24365288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_RETURN_LINK_KEYS, &flt); 24375288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_IO_CAPABILITY_REQUEST, &flt); 24385288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_IO_CAPABILITY_RESPONSE, &flt); 24395288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_CONFIRM_REQUEST, &flt); 24405288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_PASSKEY_REQUEST, &flt); 24415288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_OOB_DATA_REQUEST, &flt); 24425288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_PASSKEY_NOTIFY, &flt); 24435288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_KEYPRESS_NOTIFY, &flt); 24445288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_SIMPLE_PAIRING_COMPLETE, &flt); 24455288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_AUTH_COMPLETE, &flt); 24465288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt); 24475288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_READ_REMOTE_VERSION_COMPLETE, &flt); 24485288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_READ_REMOTE_FEATURES_COMPLETE, &flt); 24495288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_HOST_FEATURES_NOTIFY, &flt); 24505288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt); 24515288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); 24525288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt); 24535288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_EXTENDED_INQUIRY_RESULT, &flt); 24545288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CONN_REQUEST, &flt); 24555288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CONN_COMPLETE, &flt); 24565288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_DISCONN_COMPLETE, &flt); 24575288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LE_META_EVENT, &flt); 2458fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (setsockopt(dev->sk, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 24595288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Can't set filter on hci%d: %s (%d)", 24605a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg index, strerror(errno), errno); 24615288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 24625288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 24635288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2464fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg chan = g_io_channel_unix_new(dev->sk); 2465e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg cond = G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR; 2466fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->watch_id = g_io_add_watch_full(chan, G_PRIORITY_LOW, cond, 2467e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg io_security_event, 2468e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg GINT_TO_POINTER(index), NULL); 2469fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->io = chan; 24701522d6568002afa27ee7a3280b3166f7ecb02f06Johan Hedberg dev->pin_length = 0; 24715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24725288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 24735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24745288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* End of HCI event callbacks */ 24755288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2476a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) 2477a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2478a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode int status, fd = g_io_channel_unix_get_fd(io); 2479a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t child_pid; 2480a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2481a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) { 2482a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("child_exit: unable to read child pid from pipe"); 2483a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 2484a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2485a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2486a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (waitpid(child_pid, &status, 0) != child_pid) 2487a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("waitpid(%d) failed", child_pid); 2488a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode else 24898e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d exited", child_pid); 2490a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2491a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 2492a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2493a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2494a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic void at_child_exit(void) 2495a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2496a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t pid = getpid(); 2497a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2498a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid)) 2499a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("unable to write to child pipe"); 2500a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2501a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2502fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedbergstatic void device_devup_setup(int index) 2503a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2504fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2505a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_info di; 25065a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg read_stored_link_key_cp cp; 2507a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 25080e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 25090e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2510ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (hci_devinfo(index, &di) < 0) 2511a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 2512a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 251365bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (ignore_device(&di)) 2514a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 2515a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2516fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(&dev->bdaddr, &di.bdaddr); 2517fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->features, di.features, 8); 2518a352058752e541539b09e55124d411a534cc14afJohan Hedberg 2519a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set page timeout */ 2520a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if ((main_opts.flags & (1 << HCID_SET_PAGETO))) { 2521a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode write_page_timeout_cp cp; 2522a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2523a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode cp.timeout = htobs(main_opts.pageto); 2524fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, 2525a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode WRITE_PAGE_TIMEOUT_CP_SIZE, &cp); 2526a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2527a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 25285a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg bacpy(&cp.bdaddr, BDADDR_ANY); 25295a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg cp.read_all = 1; 2530fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY, 25316d2ce6e859049d6cf56e5db2197e02b0359ac442Johan Hedberg READ_STORED_LINK_KEY_CP_SIZE, &cp); 2532fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg 2533fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 25345c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 2535a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2536a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2537be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedbergstatic void init_pending(int index) 2538be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg{ 2539fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2540fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 2541fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_BDADDR, &dev->pending); 2542fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_VERSION, &dev->pending); 2543fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_FEATURES, &dev->pending); 2544fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_NAME, &dev->pending); 2545be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg} 2546be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 254771ba00415bd2941db24958d1e6e265611945194eJohan Hedbergstatic struct dev_info *init_device(int index, gboolean already_up) 2548a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 254971ba00415bd2941db24958d1e6e265611945194eJohan Hedberg struct dev_info *dev; 2550a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_req dr; 2551c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg int dd; 25526844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg pid_t pid; 25536844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 25540e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 25550e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 25566844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg dd = hci_open_dev(index); 25576844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (dd < 0) { 25586844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Unable to open hci%d: %s (%d)", index, 25596844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg strerror(errno), errno); 256071ba00415bd2941db24958d1e6e265611945194eJohan Hedberg return NULL; 25616844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg } 25626844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 25636844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (index > max_dev) { 25646844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg max_dev = index; 2565ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg devs = g_realloc(devs, sizeof(devs[0]) * (max_dev + 1)); 25666844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg } 25676844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 256871ba00415bd2941db24958d1e6e265611945194eJohan Hedberg dev = init_dev_info(index, dd, FALSE, already_up); 2569be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg init_pending(index); 25705a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg start_hci_dev(index); 2571a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2572149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz /* Avoid forking if nothing else has to be done */ 2573149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz if (already_up) 257471ba00415bd2941db24958d1e6e265611945194eJohan Hedberg return dev; 2575149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz 2576a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Do initialization in the separate process */ 2577a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid = fork(); 2578a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (pid) { 2579a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case 0: 2580a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode atexit(at_child_exit); 2581a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2582a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case -1: 2583a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Fork failed. Can't init device hci%d: %s (%d)", 2584c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg index, strerror(errno), errno); 2585a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode default: 25868e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d forked", pid); 258771ba00415bd2941db24958d1e6e265611945194eJohan Hedberg return dev; 2588a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2589a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2590a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode memset(&dr, 0, sizeof(dr)); 2591ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode dr.dev_id = index; 2592a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2593a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set link mode */ 2594a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode dr.dev_opt = main_opts.link_mode; 2595c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0) 2596a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't set link mode on hci%d: %s (%d)", 2597ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg index, strerror(errno), errno); 2598a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2599a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Start HCI device */ 2600ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (ioctl(dd, HCIDEVUP, index) < 0 && errno != EALREADY) { 2601a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't init device hci%d: %s (%d)", 2602ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode index, strerror(errno), errno); 2603a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode goto fail; 2604a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2605a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2606a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 2607a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(0); 2608a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2609a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodefail: 2610a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 2611a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(1); 2612a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2613a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2614cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedbergstatic void init_conn_list(int index) 2615cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg{ 2616cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg struct dev_info *dev = &devs[index]; 2617cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg struct hci_conn_list_req *cl; 2618cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg struct hci_conn_info *ci; 2619b671636c82f5c2eff114d3eb98cae8ff599f3fdcSzymon Janc int i; 2620cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2621cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg DBG("hci%d", index); 2622cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2623cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); 2624cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2625cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg cl->dev_id = index; 2626cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg cl->conn_num = 10; 2627cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg ci = cl->conn_info; 2628cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2629cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg if (ioctl(dev->sk, HCIGETCONNLIST, cl) < 0) { 2630cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg error("Unable to get connection list: %s (%d)", 2631cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg strerror(errno), errno); 2632cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg goto failed; 2633cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg } 2634cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2635cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg for (i = 0; i < cl->conn_num; i++, ci++) { 2636b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 2637cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2638cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg if (ci->type != ACL_LINK) 2639cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg continue; 2640cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2641b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, &ci->bdaddr); 2642cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg conn->handle = ci->handle; 2643cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg } 2644cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2645cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedbergfailed: 2646cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg g_free(cl); 2647cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg} 2648cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2649ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void device_event(int event, int index) 2650a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2651a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (event) { 2652a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_REG: 2653ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d registered", index); 2654149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz init_device(index, FALSE); 2655a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2656a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2657a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UNREG: 2658ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d unregistered", index); 265955694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 2660fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (devs[index].registered) 26615c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_manager_unregister_adapter(index); 2662a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2663a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2664a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UP: 2665ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d up", index); 2666fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].up = TRUE; 2667ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode device_devup_setup(index); 2668a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2669a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2670a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_DOWN: 2671ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d down", index); 2672fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].up = FALSE; 2673fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].pending_cod = 0; 2674fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].cache_enable = TRUE; 2675fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!devs[index].pending) { 267665edd4d5397d00d204123432fd83326486860783Johan Hedberg struct btd_adapter *adapter; 267765edd4d5397d00d204123432fd83326486860783Johan Hedberg 2678f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg adapter = manager_find_adapter_by_id(index); 267965edd4d5397d00d204123432fd83326486860783Johan Hedberg if (adapter) 2680f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg btd_adapter_stop(adapter); 268165edd4d5397d00d204123432fd83326486860783Johan Hedberg 2682be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg init_pending(index); 26835a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg } 2684a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2685a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2686a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2687cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2688f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedbergstatic gboolean init_known_adapters(gpointer user_data) 268994e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 2690cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_list_req *dl; 2691cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_req *dr; 2692f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg int i, err, ctl = GPOINTER_TO_INT(user_data); 2693ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg size_t req_size; 2694cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 26950e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 26960e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2697ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg req_size = HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t); 2698ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg 2699ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg dl = g_try_malloc0(req_size); 2700cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (!dl) { 2701ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg error("Can't allocate devlist buffer"); 2702f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 2703cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2704cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2705cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dl->dev_num = HCI_MAX_DEV; 2706cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dr = dl->dev_req; 2707cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2708ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg if (ioctl(ctl, HCIGETDEVLIST, dl) < 0) { 2709c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2710ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg error("Can't get device list: %s (%d)", strerror(-err), -err); 271183003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi g_free(dl); 2712f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 2713cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2714cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2715cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode for (i = 0; i < dl->dev_num; i++, dr++) { 2716fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev; 2717149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz gboolean already_up; 2718fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 2719149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz already_up = hci_test_bit(HCI_UP, &dr->dev_opt); 2720cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 272171ba00415bd2941db24958d1e6e265611945194eJohan Hedberg dev = init_device(dr->dev_id, already_up); 272271ba00415bd2941db24958d1e6e265611945194eJohan Hedberg if (dev == NULL) 272371ba00415bd2941db24958d1e6e265611945194eJohan Hedberg continue; 27245c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 2725fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->already_up) 2726be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg continue; 2727be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 27289ac53f53be09b96ebd6379b3c7113a05324b47dfLuiz Augusto von Dentz init_conn_list(dr->dev_id); 27295c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 2730fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->pending = 0; 2731fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_VERSION, &dev->pending); 2732fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_INFO_PARAM, 2733be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg OCF_READ_LOCAL_VERSION, 0, NULL); 2734be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg device_event(HCI_DEV_UP, dr->dev_id); 2735cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2736cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2737cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_free(dl); 2738f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg 2739f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 274094e91856179a268805256055ffd5155d1468b99cAlok Barsode} 274194e91856179a268805256055ffd5155d1468b99cAlok Barsode 2742cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsodestatic gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, 2743cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode gpointer data) 2744cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 2745cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; 2746cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_stack_internal *si; 2747cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_si_device *sd; 2748cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_event_hdr *eh; 274990e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz int type, fd; 275090e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz ssize_t len; 2751cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2752cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr = buf; 2753cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 275490e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz fd = g_io_channel_unix_get_fd(chan); 275590e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz 275690e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz len = read(fd, buf, sizeof(buf)); 275790e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (len < 0) { 275890e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (errno == EAGAIN) 2759cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2760cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2761cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode error("Read from control socket failed: %s (%d)", 2762ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg strerror(errno), errno); 2763cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return FALSE; 2764cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2765cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2766cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode type = *ptr++; 2767cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2768cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (type != HCI_EVENT_PKT) 2769cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2770cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2771cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode eh = (hci_event_hdr *) ptr; 2772cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (eh->evt != EVT_STACK_INTERNAL) 2773cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2774cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2775cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr += HCI_EVENT_HDR_SIZE; 2776cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2777cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode si = (evt_stack_internal *) ptr; 2778cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode switch (si->type) { 2779cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode case EVT_SI_DEVICE: 2780cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sd = (void *) &si->data; 2781cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(sd->event, sd->dev_id); 2782cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode break; 2783cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2784cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2785cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2786cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 2787cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 278834c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_setup(void) 2789cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 2790cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct sockaddr_hci addr; 2791cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_filter flt; 2792a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode GIOChannel *ctl_io, *child_io; 279318e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg int sock, err; 279418e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg 27950e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 27960e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 279718e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg if (child_pipe[0] != -1) 279818e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg return -EALREADY; 2799cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2800a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (pipe(child_pipe) < 0) { 2801c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2802c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("pipe(): %s (%d)", strerror(-err), -err); 2803c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2804a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2805a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2806a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode child_io = g_io_channel_unix_new(child_pipe[0]); 2807a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_set_close_on_unref(child_io, TRUE); 28088b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = g_io_add_watch(child_io, 28098b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 28108b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_exit, NULL); 2811a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_unref(child_io); 2812a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2813cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Create and bind HCI socket */ 2814cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 2815cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (sock < 0) { 2816c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2817c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("Can't open HCI socket: %s (%d)", strerror(-err), 2818c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg -err); 2819c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2820cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2821cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2822cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Set filter */ 2823cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_clear(&flt); 2824cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 2825cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_event(EVT_STACK_INTERNAL, &flt); 28266844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 2827c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2828c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("Can't set filter: %s (%d)", strerror(-err), -err); 2829c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2830cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2831cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2832cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode memset(&addr, 0, sizeof(addr)); 2833cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_family = AF_BLUETOOTH; 2834cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_dev = HCI_DEV_NONE; 28356844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2836c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 28376844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Can't bind HCI socket: %s (%d)", strerror(-err), -err); 2838c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2839cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2840cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2841cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ctl_io = g_io_channel_unix_new(sock); 2842cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_set_close_on_unref(ctl_io, TRUE); 2843cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 28448b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); 2845cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2846cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_unref(ctl_io); 2847cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2848f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg g_idle_add(init_known_adapters, GINT_TO_POINTER(sock)); 2849f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg 2850f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return 0; 2851cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 2852cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 285334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic void hciops_cleanup(void) 285434c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 28556844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int i; 28566844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 28570e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 28580e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2859b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg for (i = 0; i <= max_dev; i++) 2860b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg stop_hci_dev(i); 28616844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 28626844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg g_free(devs); 28636844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg devs = NULL; 28646844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg max_dev = -1; 28656844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 28668b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_io_id) { 28678b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(child_io_id); 28688b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = 0; 28698b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 28708b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 28718b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (ctl_io_id) { 28728b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(ctl_io_id); 28738b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = 0; 28748b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 28758b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 28768b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[0] >= 0) { 28778b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[0]); 28788b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[0] = -1; 28798b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 28808b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 28818b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[1] >= 0) { 28828b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[1]); 28838b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[1] = -1; 28848b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 288534c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 288634c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 288727c58425af807521e618f29b08e7a99496aeda3bJohan Hedbergstatic int hciops_set_powered(int index, gboolean powered) 2888076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode{ 2889fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 28906844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 2891076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 289227c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg DBG("hci%d powered %d", index, powered); 289327c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg 289427c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg if (powered == FALSE) 289527c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg return hciops_power_off(index); 28960e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2897fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (ioctl(dev->sk, HCIDEVUP, index) == 0) 28986844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2899076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 29006844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (errno == EALREADY) 29016844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2902076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 29036844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 29046844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Can't init device hci%d: %s (%d)", 29056844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg index, strerror(-err), -err); 2906076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 2907c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2908076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode} 2909076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 291000c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_set_dev_class(int index, uint8_t major, uint8_t minor) 2911d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode{ 2912fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 291300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg int err; 2914d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 29155c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d major %u minor %u", index, major, minor); 29165c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 291700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Update only the major and minor class bits keeping remaining bits 291800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * intact*/ 2919fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod &= 0xffe000; 2920fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod |= ((major & 0x1f) << 8) | minor; 2921d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 2922fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->wanted_cod == dev->current_cod || 2923fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->cache_enable || dev->pending_cod) 292400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 29250e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2926fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg DBG("Changing Major/Minor class to 0x%06x", dev->wanted_cod); 2927eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 2928fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = write_class(index, dev->wanted_cod); 292900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (err < 0) 293000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg error("Adapter class update failed: %s (%d)", 293100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg strerror(-err), -err); 2932d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 293300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return err; 2934eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode} 2935eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 2936e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedesstatic int hciops_start_inquiry(int index, uint8_t length) 2937a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode{ 2938fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2939a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; 294017baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes inquiry_cp inq_cp; 2941a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 2942e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedes DBG("hci%d length %u", index, length); 29430e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 294417baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes memset(&inq_cp, 0, sizeof(inq_cp)); 294517baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes memcpy(&inq_cp.lap, lap, 3); 294617baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes inq_cp.length = length; 294717baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes inq_cp.num_rsp = 0x00; 2948a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 294917baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes if (hci_send_cmd(dev->sk, OGF_LINK_CTL, 295017baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes OCF_INQUIRY, INQUIRY_CP_SIZE, &inq_cp) < 0) 295117baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return -errno; 2952a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 295317baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return 0; 2954a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode} 2955a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 29563ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasistatic int le_set_scan_enable(int index, uint8_t enable) 295770cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi{ 2958fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 29593ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi le_set_scan_enable_cp cp; 29603ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 29610e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d enable %u", index, enable); 29620e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 29633ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi memset(&cp, 0, sizeof(cp)); 29643ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.enable = enable; 29653ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.filter_dup = 0; 296670cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 2967fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, 29683ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi LE_SET_SCAN_ENABLE_CP_SIZE, &cp) < 0) 29696844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 297070cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 29716844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 297270cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi} 297370cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 29749235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedesstatic gboolean stop_le_scan_cb(gpointer user_data) 29759235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes{ 29769235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes struct dev_info *dev = user_data; 29779235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes int err; 29789235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29799235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes err = le_set_scan_enable(dev->id, 0); 29809235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (err < 0) 29819235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return TRUE; 29829235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29839235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes dev->stop_scan_id = 0; 29849235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29859235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return FALSE; 29869235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes} 29879235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29889235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedesstatic int hciops_start_scanning(int index, int timeout) 298970cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi{ 2990fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 29913ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi le_set_scan_parameters_cp cp; 29929235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes int err; 29933ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 29940e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 29950e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 29963ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi memset(&cp, 0, sizeof(cp)); 29973ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.type = 0x01; /* Active scanning */ 2998051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira /* The recommended value for scan interval and window is 11.25 msec. 2999051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira * It is calculated by: time = n * 0.625 msec */ 3000051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira cp.interval = htobs(0x0012); 3001051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira cp.window = htobs(0x0012); 30023ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.own_bdaddr_type = 0; /* Public address */ 30033ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.filter = 0; /* Accept all adv packets */ 30043ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 3005fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, 30063ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi LE_SET_SCAN_PARAMETERS_CP_SIZE, &cp) < 0) 300770cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi return -errno; 300870cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 30099235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes err = le_set_scan_enable(index, 1); 30109235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (err < 0) 30119235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return err; 30129235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30139235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes /* Schedule a le scan disable in 'timeout' milliseconds */ 30149235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes dev->stop_scan_id = g_timeout_add(timeout, stop_le_scan_cb, dev); 30159235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30169235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return 0; 30173ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi} 30183ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 30193ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasistatic int hciops_stop_scanning(int index) 30203ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi{ 30219235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes struct dev_info *dev = &devs[index]; 30229235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30230e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 30240e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 30259235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (dev->stop_scan_id > 0) { 30269235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes g_source_remove(dev->stop_scan_id); 30279235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes dev->stop_scan_id = 0; 30289235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes } 30299235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30303ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi return le_set_scan_enable(index, 0); 303170cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi} 303270cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 3033ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsodestatic int hciops_resolve_name(int index, bdaddr_t *bdaddr) 3034ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode{ 3035fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3036ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode remote_name_req_cp cp; 30370e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 30380e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 30390e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 30400e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 3041ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 3042ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode memset(&cp, 0, sizeof(cp)); 3043ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode bacpy(&cp.bdaddr, bdaddr); 3044ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode cp.pscan_rep_mode = 0x02; 3045ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 3046fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, 30476844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg REMOTE_NAME_REQ_CP_SIZE, &cp) < 0) 30486844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3049ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 30506844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3051ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode} 3052ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 3053164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsodestatic int hciops_set_name(int index, const char *name) 3054164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode{ 3055fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3056164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode change_local_name_cp cp; 3057164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 30580e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d, name %s", index, name); 30590e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3060164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode memset(&cp, 0, sizeof(cp)); 3061164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode strncpy((char *) cp.name, name, sizeof(cp.name)); 3062164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 3063fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, 30646844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg CHANGE_LOCAL_NAME_CP_SIZE, &cp) < 0) 30656844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3066164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 3067fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->name, cp.name, 248); 306800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 306900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 30706844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3071164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode} 3072164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 3073b96f44db8e91325968a0149595b2522d4a22481aAlok Barsodestatic int hciops_cancel_resolve_name(int index, bdaddr_t *bdaddr) 3074b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode{ 3075fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3076b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode remote_name_req_cancel_cp cp; 30770e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 30780e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 30790e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 30800e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 3081b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 3082b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode memset(&cp, 0, sizeof(cp)); 3083b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode bacpy(&cp.bdaddr, bdaddr); 3084b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 3085fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL, 30866844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg REMOTE_NAME_REQ_CANCEL_CP_SIZE, &cp) < 0) 30876844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3088b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 30896844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3090b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode} 3091b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 30924cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedesstatic int hciops_start_discovery(int index) 30934cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes{ 30948be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes int adapter_type = get_adapter_type(index); 30958be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 30968be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes switch (adapter_type) { 30978be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes case BR_EDR_LE: 3098e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedes return hciops_start_inquiry(index, LENGTH_BR_LE_INQ); 30998be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes case BR_EDR: 3100e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedes return hciops_start_inquiry(index, LENGTH_BR_INQ); 31018be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes case LE_ONLY: 31028be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return hciops_start_scanning(index, TIMEOUT_LE_SCAN); 31038be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes default: 31048be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return -EINVAL; 31058be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } 31064cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes} 31074cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes 31084cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedesstatic int hciops_stop_discovery(int index) 31094cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes{ 311057bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes struct dev_info *dev = &devs[index]; 311157bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes 31124cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes DBG("index %d", index); 311357bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes 311457bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes switch (dev->discov_state) { 311557bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes case DISCOV_INQ: 311657bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes return hciops_stop_inquiry(index); 311757bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes case DISCOV_SCAN: 311857bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes return hciops_stop_scanning(index); 311957bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes default: 312057bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes return -EINVAL; 312157bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes } 31224cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes} 31234cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes 312461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliystatic int hciops_fast_connectable(int index, gboolean enable) 312561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy{ 3126fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 312761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy write_page_activity_cp cp; 312861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy uint8_t type; 312961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 31300e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d enable %d", index, enable); 31310e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 313261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy if (enable) { 313361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_INTERLACED; 313461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0024; /* 22.5 msec page scan interval */ 313561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } else { 313661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_STANDARD; /* default */ 313761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0800; /* default 1.28 sec page scan */ 313861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } 313961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 314061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.window = 0x0012; /* default 11.25 msec page scan window */ 314161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 3142fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY, 314361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy WRITE_PAGE_ACTIVITY_CP_SIZE, &cp) < 0) 31446844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3145fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg else if (hci_send_cmd(dev->sk, OGF_HOST_CTL, 31466844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_PAGE_SCAN_TYPE, 1, &type) < 0) 31476844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 314861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 31496844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 315061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy} 315161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 31526b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedbergstatic int hciops_read_clock(int index, bdaddr_t *bdaddr, int which, 315358b68d33c5fad024f2b235555be0234e97721920Johan Hedberg int timeout, uint32_t *clock, 315458b68d33c5fad024f2b235555be0234e97721920Johan Hedberg uint16_t *accuracy) 31555bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter{ 3156fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 31576b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg uint16_t handle = 0; 31586b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg char addr[18]; 31596b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg int ret; 3160fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 31616b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg ba2str(bdaddr, addr); 31626b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg DBG("hci%d addr %s which %d timeout %d", index, addr, which, timeout); 31636b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg 31646b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg ret = get_handle(index, bdaddr, &handle); 31656b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg if (ret < 0) 31666b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg return ret; 31670e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 316858b68d33c5fad024f2b235555be0234e97721920Johan Hedberg if (hci_read_clock(dev->sk, htobs(handle), which, clock, accuracy, 31696844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg timeout) < 0) 31706844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 31715bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 31726844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 31735bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter} 31745bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 3175b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedbergstatic int hciops_read_bdaddr(int index, bdaddr_t *bdaddr) 3176b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg{ 3177fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3178fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 31790e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 3180fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3181fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(bdaddr, &dev->bdaddr); 3182fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 31836844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3184b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg} 3185b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg 3186885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedbergstatic int hciops_block_device(int index, bdaddr_t *bdaddr) 3187885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg{ 3188fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 31890e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 31900e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 31910e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 31920e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 31930e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3194fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (ioctl(dev->sk, HCIBLOCKADDR, bdaddr) < 0) 3195885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg return -errno; 3196885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 31976844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3198885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg} 3199885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 3200885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedbergstatic int hciops_unblock_device(int index, bdaddr_t *bdaddr) 3201885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg{ 3202fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 32030e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 32040e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 32050e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 32060e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 32070e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3208fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (ioctl(dev->sk, HCIUNBLOCKADDR, bdaddr) < 0) 3209885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg return -errno; 3210885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 32116844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3212885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg} 3213885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 3214f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedbergstatic int hciops_get_conn_list(int index, GSList **conns) 3215f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg{ 3216fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3217cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg GSList *l; 3218f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 32190e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 32200e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3221f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg *conns = NULL; 3222f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 3223cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg for (l = dev->connections; l != NULL; l = g_slist_next(l)) { 3224b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn = l->data; 3225cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 322676522723bdf7cb46a692f88a6ad616045bfa46e8Johan Hedberg *conns = g_slist_append(*conns, 3227cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg g_memdup(&conn->bdaddr, sizeof(bdaddr_t))); 3228cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg } 3229f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 3230cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg return 0; 3231f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg} 3232f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 323348e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedbergstatic int hciops_read_local_features(int index, uint8_t *features) 323448e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg{ 3235fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3236fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 32370e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 3238fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3239fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(features, dev->features, 8); 3240fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 32416844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 324248e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg} 324348e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg 3244bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedbergstatic int hciops_disconnect(int index, bdaddr_t *bdaddr) 324506dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg{ 3246bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg DBG("hci%d", index); 324706dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 3248bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return disconnect_addr(index, bdaddr, HCI_OE_USER_ENDED_CONNECTION); 324906dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg} 325006dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 32511bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedbergstatic int hciops_remove_bonding(int index, bdaddr_t *bdaddr) 32521bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg{ 3253fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 325473c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg delete_stored_link_key_cp cp; 3255b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg GSList *match; 32560e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 32570e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 32580e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 32590e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 32601bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 3261b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg match = g_slist_find_custom(dev->keys, bdaddr, (GCompareFunc) bacmp); 3262b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (match) { 3263b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_free(match->data); 3264b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg dev->keys = g_slist_delete_link(dev->keys, match); 3265b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } 3266b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 326773c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg memset(&cp, 0, sizeof(cp)); 326873c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg bacpy(&cp.bdaddr, bdaddr); 326973c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg 32701bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg /* Delete the link key from the Bluetooth chip */ 3271fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_DELETE_STORED_LINK_KEY, 327273c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg DELETE_STORED_LINK_KEY_CP_SIZE, &cp) < 0) 32736844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 32741bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 32756844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 32761bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg} 32771bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 32782d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmannstatic int hciops_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin, 32792d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann size_t pin_len) 3280e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg{ 3281fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 32820e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 32836844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 3284e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 32850e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 32860e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 32870e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3288e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg if (pin) { 3289e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg pin_code_reply_cp pr; 3290e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 32912d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann dev->pin_length = pin_len; 329242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg 3293e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg memset(&pr, 0, sizeof(pr)); 3294e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg bacpy(&pr.bdaddr, bdaddr); 32952d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann memcpy(pr.pin_code, pin, pin_len); 32962d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann pr.pin_len = pin_len; 3297fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 32986844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_PIN_CODE_REPLY, 3299e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg PIN_CODE_REPLY_CP_SIZE, &pr); 3300e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg } else 3301fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 3302e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg OCF_PIN_CODE_NEG_REPLY, 6, bdaddr); 3303e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 33046844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (err < 0) 33056844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 3306e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 3307e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg return err; 3308e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg} 3309e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 3310889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedbergstatic int hciops_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey) 3311889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg{ 3312fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 33130e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 33146844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 3315889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 33160e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 33170e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 33180e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3319889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg if (passkey != INVALID_PASSKEY) { 3320889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg user_passkey_reply_cp cp; 3321889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 3322889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg memset(&cp, 0, sizeof(cp)); 3323889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg bacpy(&cp.bdaddr, bdaddr); 3324889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg cp.passkey = passkey; 3325889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 3326fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 33276844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_USER_PASSKEY_REPLY, 3328889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg USER_PASSKEY_REPLY_CP_SIZE, &cp); 3329889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg } else 3330fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 3331889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg OCF_USER_PASSKEY_NEG_REPLY, 6, bdaddr); 3332889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 33336844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (err < 0) 33346844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 3335889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 3336889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg return err; 3337889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg} 3338889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 33395c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergstatic int hciops_enable_le(int index) 33407ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi{ 3341fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 33427ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi write_le_host_supported_cp cp; 33437ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 33445c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d", index); 33455c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 3346fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[4] & LMP_LE)) 33475c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return -ENOTSUP; 33480e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 33495c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg cp.le = 0x01; 3350fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg cp.simul = (dev->features[6] & LMP_LE_BREDR) ? 0x01 : 0x00; 33517ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 3352fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, 33536844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_LE_HOST_SUPPORTED, 33546844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg WRITE_LE_HOST_SUPPORTED_CP_SIZE, &cp) < 0) 33556844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 33567ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 33576844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 33587ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi} 33597ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 33603e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedbergstatic uint8_t generate_service_class(int index) 336100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 3362fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 33633e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg GSList *l; 33643e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg uint8_t val = 0; 33653e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33663e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg for (l = dev->uuids; l != NULL; l = g_slist_next(l)) { 3367006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg struct uuid_info *uuid = l->data; 33683e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 3369006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg val |= uuid->svc_hint; 33703e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg } 33713e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33723e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg return val; 33733e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg} 33743e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33753e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedbergstatic int update_service_classes(int index) 33763e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg{ 33773e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg struct dev_info *dev = &devs[index]; 33783e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg uint8_t value; 337900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg int err; 338000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 33813e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg value = generate_service_class(index); 33823e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33835c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d value %u", index, value); 33845c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 338500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Update only the service class, keep the limited bit, 338600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * major/minor class bits intact */ 3387fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod &= 0x00ffff; 3388fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod |= (value << 16); 338900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 339000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* If the cache is enabled or an existing CoD write is in progress 339100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * just bail out */ 3392fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->cache_enable || dev->pending_cod) 339300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 339400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 339500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* If we already have the CoD we want, update EIR and return */ 3396fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->current_cod == dev->wanted_cod) { 339700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 339800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 339900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg } 340000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3401fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg DBG("Changing service classes to 0x%06x", dev->wanted_cod); 340200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3403fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = write_class(index, dev->wanted_cod); 340400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (err < 0) 340500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg error("Adapter class update failed: %s (%d)", 340600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg strerror(-err), -err); 340700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 340800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return err; 340900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 341000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3411006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedbergstatic int hciops_add_uuid(int index, uuid_t *uuid, uint8_t svc_hint) 341200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 34133e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg struct dev_info *dev = &devs[index]; 3414006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg struct uuid_info *info; 341500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 341600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d", index); 341700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3418006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg info = g_new0(struct uuid_info, 1); 3419006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg memcpy(&info->uuid, uuid, sizeof(*uuid)); 3420006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg info->svc_hint = svc_hint; 3421006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg 3422006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg dev->uuids = g_slist_append(dev->uuids, info); 342300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34243e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg return update_service_classes(index); 34253e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg} 342600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34273e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedbergstatic int hciops_remove_uuid(int index, uuid_t *uuid) 34283e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg{ 34293e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg struct dev_info *dev = &devs[index]; 34303e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg GSList *match; 343100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34323e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg match = g_slist_find_custom(dev->uuids, uuid, sdp_uuid_cmp); 34333e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg if (match) { 34343e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg g_free(match->data); 34353e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg dev->uuids = g_slist_delete_link(dev->uuids, match); 343600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg } 343700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34383e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg DBG("hci%d", index); 34393e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 34403e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg return update_service_classes(index); 344100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 344200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 344300c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_disable_cod_cache(int index) 344400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 3445fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 344600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3447fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg DBG("hci%d cache_enable %d", index, dev->cache_enable); 3448fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3449fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->cache_enable) 345000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 345100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 345200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d current_cod 0x%06x wanted_cod 0x%06x", index, 3453fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->current_cod, dev->wanted_cod); 345400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 345500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Disable and flush svc cache. All successive service class 345600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * updates * will be written to the device */ 3457fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->cache_enable = FALSE; 345800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3459fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->current_cod == dev->wanted_cod) { 346000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 346100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 346200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg } 346300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3464fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg return write_class(index, dev->wanted_cod); 346500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 346600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34675c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergstatic int hciops_restore_powered(int index) 34685c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg{ 3469fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3470fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3471fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->already_up && dev->up) 347263ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg return hciops_power_off(index); 34735c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 34745c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return 0; 34755c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg} 34765c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 3477dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedbergstatic int hciops_load_keys(int index, GSList *keys, gboolean debug_keys) 3478b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg{ 3479b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg struct dev_info *dev = &devs[index]; 3480b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3481dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg DBG("hci%d keys %d debug_keys %d", index, g_slist_length(keys), 3482dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg debug_keys); 3483b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3484b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->keys != NULL) 3485b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg return -EEXIST; 3486b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3487b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg dev->keys = keys; 3488dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg dev->debug_keys = debug_keys; 3489b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3490b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg return 0; 3491b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg} 3492b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 34939634f5c410e761219037129f71c591459a854391Johan Hedbergstatic int hciops_set_io_capability(int index, uint8_t io_capability) 34949634f5c410e761219037129f71c591459a854391Johan Hedberg{ 3495b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 3496b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3497b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->io_capability = io_capability; 3498b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3499b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 3500b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 3501b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3502596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedbergstatic int request_authentication(int index, bdaddr_t *bdaddr) 3503596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg{ 3504596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg struct dev_info *dev = &devs[index]; 3505596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg auth_requested_cp cp; 3506596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg uint16_t handle; 3507596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg int err; 3508596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3509596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg DBG("hci%d", index); 3510596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3511596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg err = get_handle(index, bdaddr, &handle); 3512596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg if (err < 0) 3513596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg return err; 3514596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3515596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg memset(&cp, 0, sizeof(cp)); 3516596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg cp.handle = htobs(handle); 3517596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3518596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_AUTH_REQUESTED, 3519596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg AUTH_REQUESTED_CP_SIZE, &cp) < 0) 3520596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg return -errno; 3521596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3522596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg return 0; 3523596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg} 3524596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3525b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic void bonding_connect_cb(GIOChannel *io, GError *err, gpointer user_data) 3526b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 3527b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn = user_data; 3528b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = conn->dev; 3529b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3530b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!conn->io) { 3531b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!err) 3532b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_shutdown(io, TRUE, NULL); 3533b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 3534b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 3535b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3536b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err) 3537b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Wait proper error to be propagated by bonding complete */ 3538b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 3539b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3540596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg if (request_authentication(dev->id, &conn->bdaddr) < 0) 3541b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto failed; 3542b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3543b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 3544b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3545b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergfailed: 3546b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, HCI_UNSPECIFIED_ERROR); 3547b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 3548b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3549b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int hciops_create_bonding(int index, bdaddr_t *bdaddr, uint8_t io_cap) 3550b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 3551b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 3552b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BtIOSecLevel sec_level; 3553b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 3554b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg GError *err = NULL; 3555b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3556b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, bdaddr); 3557b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3558b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io != NULL) 3559b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -EBUSY; 3560b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3561b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_cap = io_cap; 3562b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3563b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If our IO capability is NoInputNoOutput use medium security 3564b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * level (i.e. don't require MITM protection) else use high 3565b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * security level */ 3566b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (io_cap == 0x03) 3567b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg sec_level = BT_IO_SEC_MEDIUM; 3568b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else 3569b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg sec_level = BT_IO_SEC_HIGH; 3570b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3571b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->io = bt_io_connect(BT_IO_L2RAW, bonding_connect_cb, conn, 3572b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg NULL, &err, 3573b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_SOURCE_BDADDR, &dev->bdaddr, 3574b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_DEST_BDADDR, bdaddr, 3575b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_SEC_LEVEL, sec_level, 3576b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_INVALID); 3577b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io == NULL) { 3578b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg error("bt_io_connect: %s", err->message); 3579b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_error_free(err); 3580b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -EIO; 3581b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 3582b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3583b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->bonding_initiator = TRUE; 3584b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3585b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 3586b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 3587b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3588b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int hciops_cancel_bonding(int index, bdaddr_t *bdaddr) 3589b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 3590b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 3591b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 3592b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3593629c9dbe7f161c0c285749bb014f55a2b30fd65cJohan Hedberg DBG("hci%d", index); 3594629c9dbe7f161c0c285749bb014f55a2b30fd65cJohan Hedberg 3595b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 3596b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL || conn->io == NULL) 3597b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -ENOTCONN; 3598b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3599b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_shutdown(conn->io, TRUE, NULL); 3600b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_unref(conn->io); 3601b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->io = NULL; 3602b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 36039634f5c410e761219037129f71c591459a854391Johan Hedberg return 0; 36049634f5c410e761219037129f71c591459a854391Johan Hedberg} 36059634f5c410e761219037129f71c591459a854391Johan Hedberg 360675397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Jancstatic int hciops_read_local_oob_data(int index) 360775397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc{ 360823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct dev_info *dev = &devs[index]; 360923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 361075397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc DBG("hci%d", index); 361175397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 361223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA, 0, 0) 361323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc < 0) 361423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return -errno; 361523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 361623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return 0; 361775397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc} 361875397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 361975397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Jancstatic int hciops_add_remote_oob_data(int index, bdaddr_t *bdaddr, 362075397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc uint8_t *hash, uint8_t *randomizer) 362175397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc{ 362275397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc char addr[18]; 362323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct dev_info *dev = &devs[index]; 362423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 362523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct oob_data *data; 362675397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 362775397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc ba2str(bdaddr, addr); 362875397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc DBG("hci%d bdaddr %s", index, addr); 362975397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 363023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, &bdaddr, oob_bdaddr_cmp); 363123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 363223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (match) { 363323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc data = match->data; 363423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } else { 363523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc data = g_new(struct oob_data, 1); 363623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc bacpy(&data->bdaddr, bdaddr); 363723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc dev->oob_data = g_slist_prepend(dev->oob_data, data); 363823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } 363923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 364023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(data->hash, hash, sizeof(data->hash)); 364123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); 364223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 364323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return 0; 364475397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc} 364575397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 364675397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Jancstatic int hciops_remove_remote_oob_data(int index, bdaddr_t *bdaddr) 364775397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc{ 364875397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc char addr[18]; 364923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct dev_info *dev = &devs[index]; 365023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 365175397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 365275397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc ba2str(bdaddr, addr); 365375397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc DBG("hci%d bdaddr %s", index, addr); 365475397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 365523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, &bdaddr, oob_bdaddr_cmp); 365623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 365723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (!match) 365823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return -ENOENT; 365923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 366023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc g_free(match->data); 366123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc dev->oob_data = g_slist_delete_link(dev->oob_data, match); 366223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 366323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return 0; 366475397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc} 366575397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 3666a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganeshstatic int hciops_set_link_timeout(int index, bdaddr_t *bdaddr, uint32_t num_slots) 3667a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh{ 3668a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh int dd, err; 3669a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh uint16_t handle; 3670a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh char addr[18]; 3671a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3672a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh ba2str(bdaddr, addr); 3673a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh DBG("hci%d, addr %s, num_slots %d", index, bdaddr, num_slots); 3674a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3675a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh dd = hci_open_dev(index); 3676a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3677a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh if (dd < 0) 3678a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh return EIO; 3679a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3680a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh handle = get_handle(index, bdaddr, &handle); 3681a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh err = hci_write_link_supervision_timeout(dd, htobs(handle), 3682a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh htobs(num_slots), 1000); 3683a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh if (err < 0) 3684a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh err = -errno; 3685a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3686a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh hci_close_dev(dd); 3687a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3688a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh return err; 3689a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh} 3690a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3691a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 369234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic struct btd_adapter_ops hci_ops = { 369334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .setup = hciops_setup, 369434c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .cleanup = hciops_cleanup, 369527c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg .set_powered = hciops_set_powered, 36965c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .set_discoverable = hciops_set_discoverable, 36975c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .set_pairable = hciops_set_pairable, 3698eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode .set_limited_discoverable = hciops_set_limited_discoverable, 36994cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes .start_discovery = hciops_start_discovery, 37004cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes .stop_discovery = hciops_stop_discovery, 3701ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode .resolve_name = hciops_resolve_name, 3702b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode .cancel_resolve_name = hciops_cancel_resolve_name, 3703164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode .set_name = hciops_set_name, 370400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg .set_dev_class = hciops_set_dev_class, 370561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy .set_fast_connectable = hciops_fast_connectable, 37065bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter .read_clock = hciops_read_clock, 3707b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg .read_bdaddr = hciops_read_bdaddr, 3708885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg .block_device = hciops_block_device, 3709885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg .unblock_device = hciops_unblock_device, 3710f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg .get_conn_list = hciops_get_conn_list, 371148e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg .read_local_features = hciops_read_local_features, 371206dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg .disconnect = hciops_disconnect, 37131bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg .remove_bonding = hciops_remove_bonding, 3714e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg .pincode_reply = hciops_pincode_reply, 3715df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg .confirm_reply = hciops_confirm_reply, 3716889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg .passkey_reply = hciops_passkey_reply, 37175c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .enable_le = hciops_enable_le, 3718abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg .encrypt_link = hciops_encrypt_link, 371900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg .set_did = hciops_set_did, 37203e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg .add_uuid = hciops_add_uuid, 37213e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg .remove_uuid = hciops_remove_uuid, 372200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg .disable_cod_cache = hciops_disable_cod_cache, 37235c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .restore_powered = hciops_restore_powered, 3724b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg .load_keys = hciops_load_keys, 37259634f5c410e761219037129f71c591459a854391Johan Hedberg .set_io_capability = hciops_set_io_capability, 3726b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg .create_bonding = hciops_create_bonding, 3727b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg .cancel_bonding = hciops_cancel_bonding, 372875397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc .read_local_oob_data = hciops_read_local_oob_data, 372975397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc .add_remote_oob_data = hciops_add_remote_oob_data, 373075397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc .remove_remote_oob_data = hciops_remove_remote_oob_data, 3731a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh .set_link_timeout = hciops_set_link_timeout, 373234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode}; 373334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 373434c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_init(void) 373534c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 37360e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 3737d30044157466e7f34e7f2d5d7ce70215ea013338Johan Hedberg return btd_register_adapter_ops(&hci_ops, FALSE); 373834c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 3739d57934d1d09c34d1b136c572cad1dff6306c8c48Johan Hedberg 374094e91856179a268805256055ffd5155d1468b99cAlok Barsodestatic void hciops_exit(void) 374194e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 37420e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 3743929393b82db06368ff5fa4074bc209d1d4d03a48Marcel Holtmann btd_adapter_cleanup_ops(&hci_ops); 374494e91856179a268805256055ffd5155d1468b99cAlok Barsode} 374594e91856179a268805256055ffd5155d1468b99cAlok Barsode 374694e91856179a268805256055ffd5155d1468b99cAlok BarsodeBLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, 37471ab388feb37980f1afc940c7cf530b9baadeabb1Marcel Holtmann BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit) 3748