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]; 4653a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie uint8_t mode; 4663a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie 4673a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie DBG("hci%d set scan mode off", index); 4683a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie mode = SCAN_DISABLED; 4693a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 4703a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie 1, &mode) < 0) 4713a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie return -errno; 4725c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 4733a4464a0a3af9c62342a16328f990f6fd25666b2Matthew Xie DBG("hci%d HCIDEVDOWN", index); 4745c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 47563ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg if (ioctl(dev->sk, HCIDEVDOWN, index) < 0 && errno != EALREADY) 47663ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg return -errno; 4775c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 47863ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg return 0; 4795c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg} 4805c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 4815b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedbergstatic void set_event_mask(int index) 482b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg{ 483fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 484bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 485bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 486bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg * command otherwise */ 487bca43a4edb640ecf56ada1166f7d83fad8a2ce0dJohan Hedberg uint8_t events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 488b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 4895b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg /* Events for 1.2 and newer controllers */ 490fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ver.lmp_ver > 1) { 4915b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 4925b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 4935b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 4945b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 4955b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 4965b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg } 497b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 4985b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[3] & LMP_RSSI_INQ) 4995b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 500b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 5015b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[5] & LMP_SNIFF_SUBR) 5025b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 5035b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5045b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[5] & LMP_PAUSE_ENC) 5055b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 5065b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5075b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[6] & LMP_EXT_INQ) 5085b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 5095b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5105b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[6] & LMP_NFLUSH_PKTS) 5115b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 5125b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5135b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[7] & LMP_LSTO) 5145b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 5155b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5165b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[6] & LMP_SIMPLE_PAIR) { 5175b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 5185b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 5195b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 5205b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 5215b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 5225b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 5235b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 5245b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 5255b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 5265b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg * Features Notification */ 527b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg } 528b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 5295b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg if (dev->features[4] & LMP_LE) 5305b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 5315b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5325b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_SET_EVENT_MASK, 5335b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg sizeof(events), events); 5345b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg} 5355b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5365b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedbergstatic void start_adapter(int index) 5375b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg{ 5385b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg struct dev_info *dev = &devs[index]; 5395b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg uint8_t inqmode; 5405b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg uint16_t link_policy; 5415b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 5425b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg set_event_mask(index); 5435b1a2a39dc7710f5a58e4f676389fea06764800bJohan Hedberg 544fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->features[6] & LMP_SIMPLE_PAIR) 545be49c2621d577da4fafd462265b611289547f183Johan Hedberg init_ssp_mode(index); 546be49c2621d577da4fafd462265b611289547f183Johan Hedberg 547b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg inqmode = get_inquiry_mode(index); 548b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg if (inqmode) 549b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg write_inq_mode(index, inqmode); 550b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 551fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->features[7] & LMP_INQ_TX_PWR) 552fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, 553b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL, 0, NULL); 554b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 555b59dabdd2515aa111ebc56d946259e4bbdf20c61Pawel Wieczorkiewicz /* Set default link policy */ 556ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy = main_opts.link_policy; 557ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg 558fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[0] & LMP_RSWITCH)) 559ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_RSWITCH; 560fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[0] & LMP_HOLD)) 561ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_HOLD; 562fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[0] & LMP_SNIFF)) 563ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_SNIFF; 564fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[1] & LMP_PARK)) 565ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy &= ~HCI_LP_PARK; 566b59dabdd2515aa111ebc56d946259e4bbdf20c61Pawel Wieczorkiewicz 567ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg link_policy = htobs(link_policy); 568fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_POLICY, OCF_WRITE_DEFAULT_LINK_POLICY, 569ea30b84b2349c01175ed8700e206bca1e019a635Johan Hedberg sizeof(link_policy), &link_policy); 570b59dabdd2515aa111ebc56d946259e4bbdf20c61Pawel Wieczorkiewicz 571fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->current_cod = 0; 572fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memset(dev->eir, 0, sizeof(dev->eir)); 5735c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg} 57400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 575dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentzstatic int hciops_stop_inquiry(int index) 576dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz{ 577dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz struct dev_info *dev = &devs[index]; 578dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 579dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz DBG("hci%d", index); 580dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 58117baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_INQUIRY_CANCEL, 0, 0) < 0) 582dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz return -errno; 583dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 58417baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return 0; 585dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz} 586dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 5875c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergstatic gboolean init_adapter(int index) 5885c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg{ 589fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 5905c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg struct btd_adapter *adapter = NULL; 591fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg gboolean existing_adapter = dev->registered; 5925c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg uint8_t mode, on_mode; 5935c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg gboolean pairable, discoverable; 5945c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 595fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->registered) { 5965c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg adapter = btd_manager_register_adapter(index); 5975c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (adapter) 598fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->registered = TRUE; 5995c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg } else { 600fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg adapter = manager_find_adapter(&dev->bdaddr); 6015c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg /* FIXME: manager_find_adapter should return a new ref */ 6025c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_adapter_ref(adapter); 6035c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg } 6045c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6055c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (adapter == NULL) 6065c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return FALSE; 6075c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6088440ce6ac89fdb290e566ab01edc4dcb6935a682Johan Hedberg btd_adapter_get_mode(adapter, &mode, &on_mode, &pairable); 6095c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6105c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (existing_adapter) 6115c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg mode = on_mode; 6125c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6135c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg if (mode == MODE_OFF) { 61463ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg hciops_power_off(index); 6155c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg goto done; 6165c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg } 6175c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6185c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg start_adapter(index); 6195c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_adapter_start(adapter); 6205c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6215c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg discoverable = (mode == MODE_DISCOVERABLE); 6225c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 6235c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg hciops_set_discoverable(index, discoverable); 6245c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg hciops_set_pairable(index, pairable); 6255c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 626dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz if (dev->already_up) 627dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz hciops_stop_inquiry(index); 628dc2860e16a2860a8c17af8dab1fd5e8b73dd38f7Luiz Augusto von Dentz 6295c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergdone: 6305c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_adapter_unref(adapter); 6315c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return TRUE; 632b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg} 633b8486f046aadbe0145519c86a087e880fd1d638fJohan Hedberg 634abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedbergstatic int hciops_encrypt_link(int index, bdaddr_t *dst, bt_hci_result_t cb, 635abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg gpointer user_data) 636abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg{ 637abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg GIOChannel *io; 638abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_cmd_data *cmd; 639abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_conn_info_req *cr; 640abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg auth_requested_cp cp; 641abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg struct hci_filter nf; 642abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg int dd, err; 643abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint32_t link_mode; 644abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg uint16_t handle; 645abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 646684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg dd = hci_open_dev(index); 647684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (dd < 0) 648684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg return -errno; 649684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg 650abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info)); 651abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cr->type = ACL_LINK; 652abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg bacpy(&cr->bdaddr, dst); 653abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 654684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = ioctl(dd, HCIGETCONNINFO, cr); 655abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg link_mode = cr->conn_info->link_mode; 656abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg handle = cr->conn_info->handle; 657abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_free(cr); 658abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 659684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (err < 0) { 660684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = -errno; 661684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 662684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg } 663abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 664684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (link_mode & HCI_LM_ENCRYPT) { 665684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = -EALREADY; 666684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 667684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg } 668abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 669abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg memset(&cp, 0, sizeof(cp)); 670abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cp.handle = htobs(handle); 671abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 672684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_AUTH_REQUESTED, 673684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg AUTH_REQUESTED_CP_SIZE, &cp) < 0) { 674684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg err = -errno; 675684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 676684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg } 677abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 678abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd = g_new0(struct hci_cmd_data, 1); 679abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->handle = handle; 680abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->ocf = OCF_AUTH_REQUESTED; 681abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->cb = cb; 682abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg cmd->caller_data = user_data; 683abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 684abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_clear(&nf); 685abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_ptype(HCI_EVENT_PKT, &nf); 686abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_CMD_STATUS, &nf); 687abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_AUTH_COMPLETE, &nf); 688abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_filter_set_event(EVT_ENCRYPT_CHANGE, &nf); 689abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 690abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { 691abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg err = -errno; 692abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_free(cmd); 693684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg goto fail; 694abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg } 695abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 696684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg io = g_io_channel_unix_new(dd); 697abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_set_close_on_unref(io, FALSE); 698abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_add_watch_full(io, G_PRIORITY_DEFAULT, 699abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg G_IO_HUP | G_IO_ERR | G_IO_NVAL | G_IO_IN, 700abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg hci_event_watch, cmd, g_free); 701abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg g_io_channel_unref(io); 702abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 703abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg return 0; 704684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg 705684b1d3be105b64f3994e621335f69b45e34125fJohan Hedbergfail: 706684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg close(dd); 707684b1d3be105b64f3994e621335f69b45e34125fJohan Hedberg return err; 708abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg} 709abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 71000c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_set_did(int index, uint16_t vendor, uint16_t product, 71100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint16_t version) 71200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 713fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 714fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 715fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->did_vendor = vendor; 716fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->did_product = product; 717fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->did_version = version; 71800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 71900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 72000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 72100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 722abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg/* End async HCI command handling */ 723abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg 7245288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Start of HCI event callbacks */ 7255288199788ecb17183d6517da3062cd94692a900Johan Hedberg 726b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic gint conn_handle_cmp(gconstpointer a, gconstpointer b) 727b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 728b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg const struct bt_conn *conn = a; 729b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint16_t handle = *((const uint16_t *) b); 730b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 731b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return (int) conn->handle - (int) handle; 732b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 733b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 734b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic struct bt_conn *find_conn_by_handle(struct dev_info *dev, 735b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint16_t handle) 736b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 737b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg GSList *match; 738b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 739b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg match = g_slist_find_custom(dev->connections, &handle, 740b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn_handle_cmp); 741b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (match) 742b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return match->data; 743b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 744b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return NULL; 745b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 746b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 747b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic gint conn_bdaddr_cmp(gconstpointer a, gconstpointer b) 748b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 749b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg const struct bt_conn *conn = a; 750b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg const bdaddr_t *bdaddr = b; 751b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 752b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return bacmp(&conn->bdaddr, bdaddr); 753b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 754b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 755b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic struct bt_conn *find_connection(struct dev_info *dev, bdaddr_t *bdaddr) 756b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg{ 757bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg GSList *match; 758b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 759b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg match = g_slist_find_custom(dev->connections, bdaddr, conn_bdaddr_cmp); 760b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (match) 761b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return match->data; 762b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 763b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return NULL; 764b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 765b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 766b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic struct bt_conn *get_connection(struct dev_info *dev, bdaddr_t *bdaddr) 767b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 768b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 769b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 770b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 771b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn) 772b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return conn; 773b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 774b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = g_new0(struct bt_conn, 1); 775b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 776b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->dev = dev; 777b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_cap = dev->io_capability; 778b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0xff; 779b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->rem_auth = 0xff; 780b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bacpy(&conn->bdaddr, bdaddr); 781b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 782b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->connections = g_slist_append(dev->connections, conn); 783b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 784b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return conn; 785b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 786b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 787b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int get_handle(int index, bdaddr_t *bdaddr, uint16_t *handle) 788b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 789b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 790b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 7915a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg char addr[18]; 792b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 7935a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg ba2str(bdaddr, addr); 7945a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg DBG("hci%d dba %s", index, addr); 795b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 796b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 797b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 798bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return -ENOENT; 799b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 800bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg *handle = conn->handle; 8015a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg 802bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return 0; 803b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg} 804b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 805b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedbergstatic int disconnect_addr(int index, bdaddr_t *dba, uint8_t reason) 8065288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 8075a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg disconnect_cp cp; 8085a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg uint16_t handle; 8095a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg int err; 8105288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8115a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg err = get_handle(index, dba, &handle); 8125a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg if (err < 0) 8135a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg return err; 8145288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8155a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg memset(&cp, 0, sizeof(cp)); 8165a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg cp.handle = htobs(handle); 8175a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg cp.reason = reason; 818b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 8195a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg if (hci_send_cmd(devs[index].sk, OGF_LINK_CTL, OCF_DISCONNECT, 8205a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg DISCONNECT_CP_SIZE, &cp) < 0) 8215a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg return -errno; 8225288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8235a50e2192ec53c4aeccabbb2a7dcacf7ee456dd4Johan Hedberg return 0; 8245288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8255288199788ecb17183d6517da3062cd94692a900Johan Hedberg 826b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic void bonding_complete(struct dev_info *dev, struct bt_conn *conn, 827b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t status) 8285288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 829b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("status 0x%02x", status); 8305288199788ecb17183d6517da3062cd94692a900Johan Hedberg 831b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io != NULL) { 8321cd99f445e0a11ae936d9e80b44f504f807ce35aJohan Hedberg /* bonding_connect_cb takes care of the successul case */ 8331cd99f445e0a11ae936d9e80b44f504f807ce35aJohan Hedberg if (status != 0) 8341cd99f445e0a11ae936d9e80b44f504f807ce35aJohan Hedberg g_io_channel_shutdown(conn->io, TRUE, NULL); 835b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_unref(conn->io); 836b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->io = NULL; 837b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 8385288199788ecb17183d6517da3062cd94692a900Johan Hedberg 839b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->bonding_initiator = FALSE; 8405288199788ecb17183d6517da3062cd94692a900Johan Hedberg 841fa41c93fe1dd04c1c25d34956d02c54f19ac3130Johan Hedberg btd_event_bonding_complete(&dev->bdaddr, &conn->bdaddr, status); 842b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 8435288199788ecb17183d6517da3062cd94692a900Johan Hedberg 844b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth) 845b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 846b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 847b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct hci_auth_info_req req; 848b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg char addr[18]; 8495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 850b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg ba2str(bdaddr, addr); 851b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("hci%d dba %s", index, addr); 852b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 853b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg memset(&req, 0, sizeof(req)); 854b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bacpy(&req.bdaddr, bdaddr); 8555288199788ecb17183d6517da3062cd94692a900Johan Hedberg 856b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (ioctl(dev->sk, HCIGETAUTHINFO, (unsigned long) &req) < 0) 857b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -errno; 858b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 859b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (auth) 860b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg *auth = req.type; 861b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 862b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 8635288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 8645288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8655288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Link Key handling */ 8665288199788ecb17183d6517da3062cd94692a900Johan Hedberg 86742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void link_key_request(int index, bdaddr_t *dba) 8685288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 869fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 870b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg struct link_key_info *key_info; 871b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 872b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg GSList *match; 8730e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 8745288199788ecb17183d6517da3062cd94692a900Johan Hedberg 8750e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(dba, da); 8760e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, da); 8775288199788ecb17183d6517da3062cd94692a900Johan Hedberg 878b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, dba); 879b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->handle == 0) 880b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->secmode3 = TRUE; 8815288199788ecb17183d6517da3062cd94692a900Johan Hedberg 882b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg get_auth_info(index, dba, &conn->loc_auth); 8835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 884b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("kernel auth requirements = 0x%02x", conn->loc_auth); 8855288199788ecb17183d6517da3062cd94692a900Johan Hedberg 886b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg match = g_slist_find_custom(dev->keys, dba, (GCompareFunc) bacmp); 887b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (match) 888b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = match->data; 889b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg else 890b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = NULL; 891b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 892b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg DBG("Matching key %s", key_info ? "found" : "not found"); 893b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 894dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg if (key_info == NULL || (!dev->debug_keys && key_info->type == 0x03)) { 8955288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Link key not found */ 896fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 89742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg 6, dba); 8985288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 8995288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 9005288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9015288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Link key found */ 9025288199788ecb17183d6517da3062cd94692a900Johan Hedberg 903a61d0e8e738e905604c3339309718f3b2eadbdf7Johan Hedberg DBG("link key type 0x%02x", key_info->type); 9045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9055288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Don't use unauthenticated combination keys if MITM is 9065288199788ecb17183d6517da3062cd94692a900Johan Hedberg * required */ 907b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_info->type == 0x04 && conn->loc_auth != 0xff && 908b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->loc_auth & 0x01)) 909fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 9105288199788ecb17183d6517da3062cd94692a900Johan Hedberg 6, dba); 9115288199788ecb17183d6517da3062cd94692a900Johan Hedberg else { 9125288199788ecb17183d6517da3062cd94692a900Johan Hedberg link_key_reply_cp lr; 9135288199788ecb17183d6517da3062cd94692a900Johan Hedberg 914a61d0e8e738e905604c3339309718f3b2eadbdf7Johan Hedberg memcpy(lr.link_key, key_info->key, 16); 9155288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&lr.bdaddr, dba); 9165288199788ecb17183d6517da3062cd94692a900Johan Hedberg 917fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_LINK_KEY_REPLY, 9185288199788ecb17183d6517da3062cd94692a900Johan Hedberg LINK_KEY_REPLY_CP_SIZE, &lr); 9195288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 9205288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 9215288199788ecb17183d6517da3062cd94692a900Johan Hedberg 92242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void link_key_notify(int index, void *ptr) 9235288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 924fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 9255288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_link_key_notify *evt = ptr; 9265288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t *dba = &evt->bdaddr; 927b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg struct link_key_info *key_info; 928b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t old_key_type, key_type; 929b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 930b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg GSList *match; 9310e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 932b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t status = 0; 9335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 9340e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(dba, da); 9350e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s type %d", index, da, evt->key_type); 9365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 937b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, &evt->bdaddr); 938b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 939b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg match = g_slist_find_custom(dev->keys, dba, (GCompareFunc) bacmp); 940b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (match) 941b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = match->data; 942b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg else 943b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = NULL; 944b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 945b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (key_info == NULL) { 946b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info = g_new0(struct link_key_info, 1); 947b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg bacpy(&key_info->bdaddr, &evt->bdaddr); 948c614654d76da74a51a18c7d4474a8046ca6bda01Johan Hedberg old_key_type = 0xff; 949b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } else { 950b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg dev->keys = g_slist_remove(dev->keys, key_info); 951b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg old_key_type = key_info->type; 952b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } 953b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 954b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg memcpy(key_info->key, evt->link_key, sizeof(evt->link_key)); 955b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info->type = evt->key_type; 956b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg key_info->pin_len = dev->pin_length; 9575288199788ecb17183d6517da3062cd94692a900Johan Hedberg 958b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_type = evt->key_type; 9595288199788ecb17183d6517da3062cd94692a900Johan Hedberg 960b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("key type 0x%02x old key type 0x%02x", key_type, old_key_type); 961b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("local auth 0x%02x and remote auth 0x%02x", 962b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth, conn->rem_auth); 963b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 964b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_type == 0x06) { 965b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Some buggy controller combinations generate a changed 966b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * combination key for legacy pairing even when there's no 967b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * previous key */ 968e37b81fa945fcc41ddaee2a338a666c5736724a7Szymon Janc if (conn->rem_auth == 0xff && old_key_type == 0xff) 969b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_type = 0x00; 970b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else if (old_key_type != 0xff) 971b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_type = old_key_type; 972b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else 973b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* This is Changed Combination Link Key for 974b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * a temporary link key.*/ 975b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 976b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } 9775288199788ecb17183d6517da3062cd94692a900Johan Hedberg 978b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg key_info->type = key_type; 9795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 980b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Skip the storage check if this is a debug key */ 981b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_type == 0x03) 982b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 983b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 984b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Store the link key persistently if one of the following is true: 985b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 1. this is a legacy link key 986b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 2. this is a changed combination key and there was a previously 987b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * stored one 988b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 3. neither local nor remote side had no-bonding as a requirement 989b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 4. the local side had dedicated bonding as a requirement 990b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * 5. the remote side is using dedicated bonding since in that case 991b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * also the local requirements are set to dedicated bonding 992b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * If none of the above match only keep the link key around for 993b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * this connection and set the temporary flag for the device. 994b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg */ 995b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (key_type < 0x03 || (key_type == 0x06 && old_key_type != 0xff) || 996b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->loc_auth > 0x01 && conn->rem_auth > 0x01) || 997b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->loc_auth == 0x02 || conn->loc_auth == 0x03) || 998b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (conn->rem_auth == 0x02 || conn->rem_auth == 0x03)) { 999b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg int err; 1000b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1001b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg err = btd_event_link_key_notify(&dev->bdaddr, dba, 1002b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg evt->link_key, key_type, 1003b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->pin_length); 1004b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1005b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err == -ENODEV) 1006b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg status = HCI_OE_LOW_RESOURCES; 1007b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else if (err < 0) 1008b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg status = HCI_MEMORY_FULL; 1009b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1010b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 1011b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 10125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1013b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergdone: 1014b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->pin_length = 0; 1015b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1016b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (status != 0) { 1017b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_free(key_info); 1018b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, status); 1019b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg disconnect_addr(index, dba, status); 1020b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1021b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1022b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 10235ac0142426d3e286117962cb997c5822633e43d5Johan Hedberg dev->keys = g_slist_prepend(dev->keys, key_info); 10245288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1025b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If we're connected and not dedicated bonding initiators we're 1026b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * done with the bonding process */ 1027b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!conn->bonding_initiator && conn->handle != 0) 1028b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, 0); 10295288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10305288199788ecb17183d6517da3062cd94692a900Johan Hedberg 103142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void return_link_keys(int index, void *ptr) 10325288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1033fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 10345288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_return_link_keys *evt = ptr; 10355288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = evt->num_keys; 10365288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char key[16]; 10370e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 10385288199788ecb17183d6517da3062cd94692a900Johan Hedberg bdaddr_t dba; 10395288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 10405288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10410e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d num_keys %u", index, num); 10420e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 10435288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr++; 10445288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10455288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 10465288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&dba, ptr); ba2str(&dba, da); 10475288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(key, ptr + 6, 16); 10485288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10490e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d returned key for %s", index, da); 10505288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1051fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_returned_link_key(&dev->bdaddr, &dba); 10525288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10535288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += 22; 10545288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 10555288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 10565288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10575288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* Simple Pairing handling */ 10585288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10594d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedbergstatic int hciops_confirm_reply(int index, bdaddr_t *bdaddr, gboolean success) 10604d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg{ 10614d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg struct dev_info *dev = &devs[index]; 10624d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg user_confirm_reply_cp cp; 10634d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg char addr[18]; 10644d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg int err; 10654d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10664d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg ba2str(bdaddr, addr); 10674d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg DBG("hci%d dba %s success %d", index, addr, success); 10684d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10694d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg memset(&cp, 0, sizeof(cp)); 10704d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg bacpy(&cp.bdaddr, bdaddr); 10714d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10724d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg if (success) 10734d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 10744d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg OCF_USER_CONFIRM_REPLY, 10754d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg USER_CONFIRM_REPLY_CP_SIZE, &cp); 10764d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg else 10774d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 10784d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg OCF_USER_CONFIRM_NEG_REPLY, 10794d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg USER_CONFIRM_REPLY_CP_SIZE, &cp); 10804d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10814d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg if (err < 0) 10824d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg err = -errno; 10834d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 10844d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg return err; 10854d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg} 10864d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 108742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void user_confirm_request(int index, void *ptr) 10885288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1089fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 10905288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_confirm_request *req = ptr; 10914d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg gboolean loc_mitm, rem_mitm; 1092b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 10937050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh struct agent *agent; 10945288199788ecb17183d6517da3062cd94692a900Johan Hedberg 10950e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 10960e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1097b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, &req->bdaddr); 1098b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 1099b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1100b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1101b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg loc_mitm = (conn->loc_auth & 0x01) ? TRUE : FALSE; 1102b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg rem_mitm = (conn->rem_auth & 0x01) ? TRUE : FALSE; 1103b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1104b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If we require MITM but the remote device can't provide that 1105b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 1106b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * request. The only exception is when we're dedicated bonding 1107b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * initiators since then we always have the MITM bit set. */ 1108b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!conn->bonding_initiator && loc_mitm && conn->rem_cap == 0x03) { 1109b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg error("Rejecting request: remote device can't provide MITM"); 1110b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto fail; 1111b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1112b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 11137050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh /* If local IO capabilities are DisplayYesNo and remote IO 11147050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh * capabiltiies are DisplayOnly or NoInputNoOutput; 11157050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh * call PairingConsent callback for incoming requests. */ 11167050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh if (conn->bonding_initiator == FALSE) { 11177050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh if ((conn->loc_cap == 0x01) && 11187050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh (conn->rem_cap == 0x00 || conn->rem_cap == 0x03)) { 11197050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh if (btd_event_user_consent(&dev->bdaddr, &req->bdaddr) 11207050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh < 0) 11217050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh goto fail; 11227050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh return; 11237050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh } 11247050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh } 11257050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh 1126b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If no side requires MITM protection; auto-accept */ 1127b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if ((conn->loc_auth == 0xff || !loc_mitm || conn->rem_cap == 0x03) && 1128b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg (!rem_mitm || conn->loc_cap == 0x03)) { 1129b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("auto accept of confirmation"); 11304d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 11314d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg /* Wait 5 milliseconds before doing auto-accept */ 11324d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg usleep(5000); 11334d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 11344d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg if (hciops_confirm_reply(index, &req->bdaddr, TRUE) < 0) 11354d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg goto fail; 11364d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg 11374d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg return; 11384d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg } 1139b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1140fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (btd_event_user_confirm(&dev->bdaddr, &req->bdaddr, 11414d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg btohl(req->passkey)) == 0) 1142b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1143b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1144b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergfail: 1145b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY, 1146b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 6, ptr); 11475288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 11485288199788ecb17183d6517da3062cd94692a900Johan Hedberg 114942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void user_passkey_request(int index, void *ptr) 11505288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1151fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 11525288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_passkey_request *req = ptr; 11535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11540e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 11550e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1156fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (btd_event_user_passkey(&dev->bdaddr, &req->bdaddr) < 0) 1157fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, 11585288199788ecb17183d6517da3062cd94692a900Johan Hedberg OCF_USER_PASSKEY_NEG_REPLY, 6, ptr); 11595288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 11605288199788ecb17183d6517da3062cd94692a900Johan Hedberg 116142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void user_passkey_notify(int index, void *ptr) 11625288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1163fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 11645288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_user_passkey_notify *req = ptr; 11655288199788ecb17183d6517da3062cd94692a900Johan Hedberg 11660e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 11670e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1168fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_user_notify(&dev->bdaddr, &req->bdaddr, 116942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg btohl(req->passkey)); 11705288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 11715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 117223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Jancstatic gint oob_bdaddr_cmp(gconstpointer a, gconstpointer b) 117323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc{ 117423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc const struct oob_data *data = a; 117523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc const bdaddr_t *bdaddr = b; 117623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 117723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return bacmp(&data->bdaddr, bdaddr); 117823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc} 117923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 118023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Jancstatic void remote_oob_data_request(int index, bdaddr_t *bdaddr) 11815288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1182fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 118323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 1184fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 11850e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 1186fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 118723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, bdaddr, oob_bdaddr_cmp); 118823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 118923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (match) { 119023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct oob_data *data; 119123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc remote_oob_data_reply_cp cp; 119223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 119323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc data = match->data; 119423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 119523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc bacpy(&cp.bdaddr, &data->bdaddr); 119623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 119723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 119823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 119923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc dev->oob_data = g_slist_delete_link(dev->oob_data, match); 120023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 120123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY, 120223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp); 120323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 120423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } else { 120523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc hci_send_cmd(dev->sk, OGF_LINK_CTL, 120623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, bdaddr); 120723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } 12085288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 12095288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1210b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int get_io_cap(int index, bdaddr_t *bdaddr, uint8_t *cap, uint8_t *auth) 1211b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 1212b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 1213b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 1214b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg int err; 1215b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1216b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 1217b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 1218b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -ENOENT; 1219b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1220b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg err = get_auth_info(index, bdaddr, &conn->loc_auth); 1221b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err < 0) 1222b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return err; 1223b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1224b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("initial authentication requirement is 0x%02x", conn->loc_auth); 1225b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1226b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!dev->pairable && !conn->bonding_initiator) { 1227b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth < 0x02) { 1228b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("Allowing no bonding in non-bondable mode"); 1229b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Kernel defaults to general bonding and so 1230b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * overwrite for this special case. Otherwise 1231b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * non-pairable test cases will fail. */ 1232b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = conn->rem_auth; 1233b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto done; 1234b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1235b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1236b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -EPERM; 1237b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1238b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1239b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If the kernel doesn't know the local requirement just mirror 1240b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * the remote one */ 1241b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->loc_auth == 0xff) 1242b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = conn->rem_auth; 1243b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1244b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->loc_auth == 0x00 || conn->loc_auth == 0x04) { 1245b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 1246b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth == 0x02 || conn->rem_auth == 0x03) { 1247b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1248b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If both remote and local IO capabilities allow MITM 1249b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * then require it, otherwise don't */ 1250b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_cap == 0x03 || conn->loc_cap == 0x03) 1251b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0x02; 1252b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else 1253b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0x03; 1254b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1255b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1256b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If remote indicates no bonding then follow that. This 1257b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * is important since the kernel might give general bonding 1258b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * as default. */ 1259b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth == 0x00 || conn->rem_auth == 0x01) 1260b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth = 0x00; 1261b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1262b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If remote requires MITM then also require it, unless 1263b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * our IO capability is NoInputNoOutput (so some 1264b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * just-works security cases can be tested) */ 1265b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->rem_auth != 0xff && (conn->rem_auth & 0x01) && 1266b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_cap != 0x03) 1267b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_auth |= 0x01; 1268b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1269b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1270b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergdone: 1271b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg *cap = conn->loc_cap; 1272b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg *auth = conn->loc_auth; 1273b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1274b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("final authentication requirement is 0x%02x", *auth); 1275b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1276b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 1277b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 1278b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 127942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void io_capa_request(int index, void *ptr) 12805288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1281fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 128242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg bdaddr_t *dba = ptr; 1283b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg uint8_t cap, auth = 0xff; 12840e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 1285b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg int err; 12865288199788ecb17183d6517da3062cd94692a900Johan Hedberg 12870e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(dba, da); 12880e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d IO capability request for %s", index, da); 12895288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1290b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg err = get_io_cap(index, dba, &cap, &auth); 1291b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err < 0) { 12925288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capability_neg_reply_cp cp; 1293b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1294b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg error("Getting IO capability failed: %s (%d)", 1295b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg strerror(-err), -err); 1296b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 12975288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&cp, 0, sizeof(cp)); 12985288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&cp.bdaddr, dba); 12995288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.reason = HCI_PAIRING_NOT_ALLOWED; 1300fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, 130142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg OCF_IO_CAPABILITY_NEG_REPLY, 13025288199788ecb17183d6517da3062cd94692a900Johan Hedberg IO_CAPABILITY_NEG_REPLY_CP_SIZE, &cp); 13035288199788ecb17183d6517da3062cd94692a900Johan Hedberg } else { 13045288199788ecb17183d6517da3062cd94692a900Johan Hedberg io_capability_reply_cp cp; 130523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct bt_conn *conn; 130623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 130723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 13085288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(&cp, 0, sizeof(cp)); 13095288199788ecb17183d6517da3062cd94692a900Johan Hedberg bacpy(&cp.bdaddr, dba); 13105288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.capability = cap; 13115288199788ecb17183d6517da3062cd94692a900Johan Hedberg cp.authentication = auth; 131223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 131323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc conn = find_connection(dev, dba); 131423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, dba, oob_bdaddr_cmp); 131523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 131623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if ((conn->bonding_initiator || conn->rem_oob_data == 0x01) && 131723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match) 131823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc cp.oob_data = 0x01; 131923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc else 132023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc cp.oob_data = 0x00; 132123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 1322fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY, 13235288199788ecb17183d6517da3062cd94692a900Johan Hedberg IO_CAPABILITY_REPLY_CP_SIZE, &cp); 13245288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 13255288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13265288199788ecb17183d6517da3062cd94692a900Johan Hedberg 132742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void io_capa_response(int index, void *ptr) 13285288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1329fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 13305288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_io_capability_response *evt = ptr; 1331b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 13320e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char da[18]; 13335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13340e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(&evt->bdaddr, da); 13350e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d IO capability response from %s", index, da); 13365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1337b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, &evt->bdaddr); 1338b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn) { 1339b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->rem_cap = evt->capability; 1340b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->rem_auth = evt->authentication; 134123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc conn->rem_oob_data = evt->oob_data; 1342b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 13435288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13445288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13455288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* PIN code handling */ 13465288199788ecb17183d6517da3062cd94692a900Johan Hedberg 134742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void pin_code_request(int index, bdaddr_t *dba) 13485288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1349fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1350b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 135153a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg char addr[18]; 135253a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg int err; 13535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 135453a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg ba2str(dba, addr); 135553a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg DBG("hci%d PIN request for %s", index, addr); 13565288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1357b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, dba); 1358b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->handle == 0) 1359b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->secmode3 = TRUE; 1360b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1361b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Check if the adapter is not pairable and if there isn't a bonding in 1362b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * progress */ 1363b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!dev->pairable && !conn->bonding_initiator) { 1364b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("Rejecting PIN request in non-pairable mode"); 1365b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto reject; 1366b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 1367b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 136853a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg err = btd_event_request_pin(&dev->bdaddr, dba); 136953a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg if (err < 0) { 137053a4fa31e72841c8db229c75fd9f798c90e29ee5Johan Hedberg error("PIN code negative reply: %s", strerror(-err)); 1371b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto reject; 13725288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 1373b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1374b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 1375b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 1376b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergreject: 1377b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba); 13785288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 138042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_features_notify(int index, void *ptr) 13815288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1382fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 13835288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_remote_host_features_notify *evt = ptr; 13845288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13855288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->features[0] & 0x01) 1386fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_set_legacy_pairing(&dev->bdaddr, &evt->bdaddr, 138742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg FALSE); 13885288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 1389fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_set_legacy_pairing(&dev->bdaddr, &evt->bdaddr, 139042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg TRUE); 13915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1392fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg write_features_info(&dev->bdaddr, &evt->bdaddr, NULL, evt->features); 13935288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 13945288199788ecb17183d6517da3062cd94692a900Johan Hedberg 13952db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedbergstatic void write_le_host_complete(int index, uint8_t status) 13965288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1397fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 13982db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg uint8_t page_num = 0x01; 13995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 14005288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (status) 14015288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 14025288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1403fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_INFO_PARAM, 14042db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg OCF_READ_LOCAL_EXT_FEATURES, 1, &page_num) < 0) 14052db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg error("Unable to read extended local features: %s (%d)", 14062db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg strerror(errno), errno); 14075288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 14085288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1409be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedbergstatic void read_local_version_complete(int index, 1410be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg const read_local_version_rp *rp) 1411be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg{ 1412fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1413fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 1414be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg if (rp->status) 1415be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1416be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1417fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.manufacturer = btohs(bt_get_unaligned(&rp->manufacturer)); 1418fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.hci_ver = rp->hci_ver; 1419fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.hci_rev = btohs(bt_get_unaligned(&rp->hci_rev)); 1420fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_ver = rp->lmp_ver; 1421fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ver.lmp_subver = btohs(bt_get_unaligned(&rp->lmp_subver)); 1422be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1423fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 1424be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1425be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1426fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_VERSION, &dev->pending); 1427be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1428be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg DBG("Got version for hci%d", index); 1429be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1430fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending && dev->up) 14315c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 1432be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg} 1433be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1434be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedbergstatic void read_local_features_complete(int index, 1435be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg const read_local_features_rp *rp) 1436be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg{ 1437fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1438fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 1439be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg if (rp->status) 1440be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1441be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1442fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->features, rp->features, 8); 1443be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1444fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 1445be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg return; 1446be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1447fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_FEATURES, &dev->pending); 1448be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1449be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg DBG("Got features for hci%d", index); 1450be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 1451fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending && dev->up) 14525c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 1453be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg} 1454be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 145500c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic void update_ext_inquiry_response(int index) 145600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1457fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 145800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_ext_inquiry_response_cp cp; 145900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 146000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d", index); 146100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1462fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[6] & LMP_EXT_INQ)) 146300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 146400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1465fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->ssp_mode == 0) 146600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 146700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1468fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->cache_enable) 146900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 147000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 147100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memset(&cp, 0, sizeof(cp)); 147200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1473991a7a4f09049c91297d74f9d28497fad166268eClaudio Takahasi eir_create(dev->name, dev->tx_power, dev->did_vendor, dev->did_product, 1474991a7a4f09049c91297d74f9d28497fad166268eClaudio Takahasi dev->did_version, dev->uuids, cp.data); 147500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1476fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (memcmp(cp.data, dev->eir, sizeof(cp.data)) == 0) 147700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 147800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1479fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->eir, cp.data, sizeof(cp.data)); 148000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1481fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, 148200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg OCF_WRITE_EXT_INQUIRY_RESPONSE, 148300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0) 148400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg error("Unable to write EIR data: %s (%d)", 148500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg strerror(errno), errno); 148600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 148700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 148819084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedbergstatic void update_name(int index, const char *name) 148919084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg{ 149019084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg struct btd_adapter *adapter; 149119084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg 1492f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg adapter = manager_find_adapter_by_id(index); 149319084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg if (adapter) 149419084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg adapter_update_local_name(adapter, name); 149500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 149600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 149719084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg} 149819084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg 1499fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedbergstatic void read_local_name_complete(int index, read_local_name_rp *rp) 1500fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg{ 1501fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1502fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 15030e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15040e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1505fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg if (rp->status) 1506fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg return; 1507fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1508fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->name, rp->name, 248); 150900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1510fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) { 151119084de6a65e4dfad006eb0364eb68e7ced3b46cJohan Hedberg update_name(index, (char *) rp->name); 1512fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg return; 1513fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg } 1514fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1515fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_NAME, &dev->pending); 1516fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1517fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg DBG("Got name for hci%d", index); 1518fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 15199f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg /* Even though it shouldn't happen (assuming the kernel behaves 15209f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * properly) it seems like we might miss the very first 15219f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * initialization commands that the kernel sends. So check for 15229f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * it here (since read_local_name is one of the last init 15239f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * commands) and resend the first ones if we haven't seen 15249f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg * their results yet */ 15259f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg 1526fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_test_bit(PENDING_FEATURES, &dev->pending)) 1527fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_INFO_PARAM, 15289f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg OCF_READ_LOCAL_FEATURES, 0, NULL); 15299f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg 1530fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_test_bit(PENDING_VERSION, &dev->pending)) 1531fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_INFO_PARAM, 15329f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg OCF_READ_LOCAL_VERSION, 0, NULL); 15339f524fe68a075edd9d0cfdbadea181c76cce4ff5Johan Hedberg 15344f8d6ba3531fc2d27d17a54e073e3db529fc1cf5Johan Hedberg if (!dev->pending && dev->up) 15355c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 1536fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg} 1537fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg 1538e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedbergstatic void read_tx_power_complete(int index, void *ptr) 1539e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg{ 1540fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1541fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 1542e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg read_inq_response_tx_power_level_rp *rp = ptr; 1543e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg 15440e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15450e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1546e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg if (rp->status) 1547e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg return; 1548e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg 1549fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->tx_power = rp->level; 155000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 1551e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg} 1552e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg 1553af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedbergstatic void read_simple_pairing_mode_complete(int index, void *ptr) 1554af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg{ 1555700d2ae37c0008e87bc7d3e25027cf80b8ba98e5Johan Hedberg struct dev_info *dev = &devs[index]; 1556af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg read_simple_pairing_mode_rp *rp = ptr; 1557af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg 15580e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15590e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1560af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg if (rp->status) 1561af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg return; 1562af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg 1563fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->ssp_mode = rp->mode; 156400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 1565af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg} 1566af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg 15670e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedbergstatic void read_local_ext_features_complete(int index, 15685288199788ecb17183d6517da3062cd94692a900Johan Hedberg const read_local_ext_features_rp *rp) 15695288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 157094e7feb45fb9938d4d8f7363dfc7dee34940389eAndre Guedes struct dev_info *dev = &devs[index]; 15715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 15720e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15730e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 15745288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (rp->status) 15755288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 15765288199788ecb17183d6517da3062cd94692a900Johan Hedberg 15775288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Local Extended feature page number is 1 */ 15785288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (rp->page_num != 1) 15795288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 15805288199788ecb17183d6517da3062cd94692a900Johan Hedberg 158194e7feb45fb9938d4d8f7363dfc7dee34940389eAndre Guedes memcpy(dev->extfeatures, rp->features, sizeof(dev->extfeatures)); 15825288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 15835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 15845a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedbergstatic void read_bd_addr_complete(int index, read_bd_addr_rp *rp) 15855a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg{ 1586fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 1587fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 15880e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, rp->status); 15890e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 15905a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg if (rp->status) 15915a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg return; 15925a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1593fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(&dev->bdaddr, &rp->bdaddr); 15945a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1595fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 15965a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg return; 15975a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1598fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_clear_bit(PENDING_BDADDR, &dev->pending); 15995a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 160028c405b17a3131494c11599705885ae630c52ee2Johan Hedberg DBG("Got bdaddr for hci%d", index); 16015a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 1602fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending && dev->up) 16035c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 16045a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg} 16055a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg 16062a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void cs_inquiry_evt(int index, uint8_t status) 16072a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 16082a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 16092a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("Inquiry Failed with status 0x%02x", status); 16102a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 16112a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 16122a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 16132a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_INQ); 16142a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 16152a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 161642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void cmd_status(int index, void *ptr) 16175288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 16185288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_status *evt = ptr; 16195288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint16_t opcode = btohs(evt->opcode); 16205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 16215288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY)) 16222a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes cs_inquiry_evt(index, evt->status); 16235288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 16245288199788ecb17183d6517da3062cd94692a900Johan Hedberg 162542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic void read_scan_complete(int index, uint8_t status, void *ptr) 16265288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 16275288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct btd_adapter *adapter; 16285288199788ecb17183d6517da3062cd94692a900Johan Hedberg read_scan_enable_rp *rp = ptr; 16295288199788ecb17183d6517da3062cd94692a900Johan Hedberg 16300e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, status); 16310e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 1632f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg adapter = manager_find_adapter_by_id(index); 16335288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!adapter) { 16345288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Unable to find matching adapter"); 16355288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 16365288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 16375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 16385288199788ecb17183d6517da3062cd94692a900Johan Hedberg adapter_mode_changed(adapter, rp->enable); 16395288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 16405288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1641914a9093c108cf67a1ef08bffc7db2e4c9a5b1b9Johan Hedbergstatic int write_class(int index, uint32_t class) 164200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1643fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 164400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_class_of_dev_cp cp; 164500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 164600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d class 0x%06x", index, class); 164700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 164800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memcpy(cp.dev_class, &class, 3); 164900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1650fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, 165100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0) 165200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return -errno; 165300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1654fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->pending_cod = class; 165500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 165600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 165700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 165800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 165900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg/* Limited Discoverable bit mask in CoD */ 166000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg#define LIMITED_BIT 0x002000 166100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 166200c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_set_limited_discoverable(int index, gboolean limited) 166300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1664fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 166500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg int num = (limited ? 2 : 1); 166600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e }; 166700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_current_iac_lap_cp cp; 166800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 166900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d limited %d", index, limited); 167000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 167100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Check if limited bit needs to be set/reset */ 167200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (limited) 1673fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod |= LIMITED_BIT; 167400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg else 1675fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod &= ~LIMITED_BIT; 167600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 167700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* If we dont need the toggling, save an unnecessary CoD write */ 1678fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->pending_cod || dev->wanted_cod == dev->current_cod) 167900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 168000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 168100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* 168200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * 1: giac 168300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * 2: giac + liac 168400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg */ 168500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memset(&cp, 0, sizeof(cp)); 168600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg cp.num_current_iac = num; 168700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg memcpy(&cp.lap, lap, num * 3); 168800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1689fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP, 169000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg (num * 3 + 1), &cp) < 0) 169100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return -errno; 169200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1693fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg return write_class(index, dev->wanted_cod); 169400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 169500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 169600c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic void write_class_complete(int index, uint8_t status) 169700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 1698fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 169900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg struct btd_adapter *adapter; 170000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 170100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (status) 170200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 170300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1704fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->pending_cod == 0) 170500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 170600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1707fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->current_cod = dev->pending_cod; 1708fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->pending_cod = 0; 170900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1710fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg adapter = manager_find_adapter(&dev->bdaddr); 171100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (adapter) 1712fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_adapter_class_changed(adapter, dev->current_cod); 171300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 171400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 171500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1716fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->wanted_cod == dev->current_cod) 171700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return; 171800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 1719fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->wanted_cod & LIMITED_BIT && 1720fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg !(dev->current_cod & LIMITED_BIT)) 172100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg hciops_set_limited_discoverable(index, TRUE); 1722fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg else if (!(dev->wanted_cod & LIMITED_BIT) && 1723fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg (dev->current_cod & LIMITED_BIT)) 172400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg hciops_set_limited_discoverable(index, FALSE); 172500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg else 1726fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg write_class(index, dev->wanted_cod); 172700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 172800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 172923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Jancstatic void read_local_oob_data_complete(int index, uint8_t status, 173023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc read_local_oob_data_rp *rp) 173123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc{ 173223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct btd_adapter *adapter = manager_find_adapter_by_id(index); 173323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 173423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (!adapter) 173523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return; 173623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 173723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (status) 173823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc oob_read_local_data_complete(adapter, NULL, NULL); 173923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc else 174023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc oob_read_local_data_complete(adapter, rp->hash, rp->randomizer); 174123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc} 174223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 17432a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void inquiry_complete_evt(int index, uint8_t status) 17442a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 17458be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes int adapter_type; 17468be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes struct btd_adapter *adapter; 17478be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 17482a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 17492a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("Inquiry Failed with status 0x%02x", status); 17502a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 17512a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 17522a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17538be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter = manager_find_adapter_by_id(index); 17548be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (!adapter) { 17558be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes error("No matching adapter found"); 17568be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return; 17578be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } 17588be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 17598be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_type = get_adapter_type(index); 17608be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 17618be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (adapter_type == BR_EDR_LE && 17628be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes adapter_has_discov_sessions(adapter)) { 17638be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes int err = hciops_start_scanning(index, TIMEOUT_BR_LE_SCAN); 17648be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes if (err < 0) 17658be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes set_state(index, DISCOV_HALTED); 17668be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } else { 17678be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes set_state(index, DISCOV_HALTED); 17688be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } 17692a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 17702a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17712a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void cc_inquiry_cancel(int index, uint8_t status) 17722a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 17732a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 17742a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("Inquiry Cancel Failed with status 0x%02x", status); 17752a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 17762a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 17772a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17782a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_HALTED); 17792a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 17802a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17812a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedesstatic inline void cc_le_set_scan_enable(int index, uint8_t status) 17822a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes{ 17832a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes int state; 17842a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17852a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (status) { 17862a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes error("LE Set Scan Enable Failed with status 0x%02x", status); 17872a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes return; 17882a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes } 17892a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 17902a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes state = get_state(index); 17912a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes if (state == DISCOV_SCAN) 17922a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_HALTED); 17932a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes else 17942a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes set_state(index, DISCOV_SCAN); 17952a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes} 17962a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes 179742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void cmd_complete(int index, void *ptr) 17985288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1799fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 18005288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_complete *evt = ptr; 18015288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint16_t opcode = btohs(evt->opcode); 18025288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t status = *((uint8_t *) ptr + EVT_CMD_COMPLETE_SIZE); 18035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 18045288199788ecb17183d6517da3062cd94692a900Johan Hedberg switch (opcode) { 1805be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION): 1806be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg ptr += sizeof(evt_cmd_complete); 1807be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg read_local_version_complete(index, ptr); 1808be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg break; 1809be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES): 1810be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg ptr += sizeof(evt_cmd_complete); 1811be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg read_local_features_complete(index, ptr); 1812be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg break; 18135288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_EXT_FEATURES): 18145288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 18150e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg read_local_ext_features_complete(index, ptr); 18165288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18175a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BD_ADDR): 18185a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg ptr += sizeof(evt_cmd_complete); 18195a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg read_bd_addr_complete(index, ptr); 18205a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg break; 18215288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL): 18222a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes cc_inquiry_cancel(index, status); 18235288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18245288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_LE_HOST_SUPPORTED): 18252db4f654cb730adffe7b55044327f68808cd1c9dJohan Hedberg write_le_host_complete(index, status); 18265288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18275288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE): 18282a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes cc_le_set_scan_enable(index, status); 18295288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18305288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME): 1831bd7f8939b50a12418476245f9b5117801f858b02Johan Hedberg if (!status) 1832fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, 1833bd7f8939b50a12418476245f9b5117801f858b02Johan Hedberg OCF_READ_LOCAL_NAME, 0, 0); 18345288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18355288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE): 1836073c798c8f77c9d63aa4008c2c56cd645f68c7afJohan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_SCAN_ENABLE, 1837073c798c8f77c9d63aa4008c2c56cd645f68c7afJohan Hedberg 0, NULL); 18385288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18395288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SCAN_ENABLE): 18405288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 184142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg read_scan_complete(index, status, ptr); 18425288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18435288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV): 184400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg write_class_complete(index, status); 18455288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18465288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SIMPLE_PAIRING_MODE): 18477afa48dcf311926269dcfb8ec1a2a12c94eb2d5bJohan Hedberg if (!status) 1848fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, 18497afa48dcf311926269dcfb8ec1a2a12c94eb2d5bJohan Hedberg OCF_READ_SIMPLE_PAIRING_MODE, 0, NULL); 18505288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18515288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SIMPLE_PAIRING_MODE): 18525288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 1853af56f3b6d5c0261d9faf8c95cf4da5b244a03caeJohan Hedberg read_simple_pairing_mode_complete(index, ptr); 18545288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 18555288199788ecb17183d6517da3062cd94692a900Johan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_NAME): 18565288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 1857fa472e0c7092af97d6f9d5c997003f443991aea9Johan Hedberg read_local_name_complete(index, ptr); 18585288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 1859e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg case cmd_opcode_pack(OGF_HOST_CTL, 1860e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL): 18615288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += sizeof(evt_cmd_complete); 1862e47f4351bcea802ee23a9db237ecd4802894e97eJohan Hedberg read_tx_power_complete(index, ptr); 18635288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 186423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA): 186523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc ptr += sizeof(evt_cmd_complete); 186623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc read_local_oob_data_complete(index, status, ptr); 186723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc break; 18685288199788ecb17183d6517da3062cd94692a900Johan Hedberg }; 18695288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 18705288199788ecb17183d6517da3062cd94692a900Johan Hedberg 187142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_name_information(int index, void *ptr) 18725288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1873fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 18745288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_remote_name_req_complete *evt = ptr; 18755288199788ecb17183d6517da3062cd94692a900Johan Hedberg char name[MAX_NAME_LENGTH + 1]; 18765288199788ecb17183d6517da3062cd94692a900Johan Hedberg 18770e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 18780e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 18795288199788ecb17183d6517da3062cd94692a900Johan Hedberg memset(name, 0, sizeof(name)); 18805288199788ecb17183d6517da3062cd94692a900Johan Hedberg 18815288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!evt->status) 18825288199788ecb17183d6517da3062cd94692a900Johan Hedberg memcpy(name, evt->name, MAX_NAME_LENGTH); 18835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1884fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_remote_name(&dev->bdaddr, &evt->bdaddr, evt->status, name); 18855288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 18865288199788ecb17183d6517da3062cd94692a900Johan Hedberg 188742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_version_information(int index, void *ptr) 18885288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1889fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 18905288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_read_remote_version_complete *evt = ptr; 1891b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 18925288199788ecb17183d6517da3062cd94692a900Johan Hedberg 18930e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 18940e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 18955288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->status) 18965288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 18975288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1898b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 1899b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 19005288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 19015288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1902b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg write_version_info(&dev->bdaddr, &conn->bdaddr, 1903b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg btohs(evt->manufacturer), evt->lmp_ver, 1904b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg btohs(evt->lmp_subver)); 19055288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19065288199788ecb17183d6517da3062cd94692a900Johan Hedberg 190742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void inquiry_result(int index, int plen, void *ptr) 19085288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1909fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19105288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 19115288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 19125288199788ecb17183d6517da3062cd94692a900Johan Hedberg 191317baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes /* Skip if it is not in Inquiry state */ 191417baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes if (get_state(index) != DISCOV_INQ) 191517baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return; 191617baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes 19175288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19185288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info *info = ptr; 191942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg uint32_t class = info->dev_class[0] | 192042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg (info->dev_class[1] << 8) | 192142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg (info->dev_class[2] << 16); 19225288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1923b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, class, 192442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg 0, NULL); 19255288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_SIZE; 19265288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19275288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19285288199788ecb17183d6517da3062cd94692a900Johan Hedberg 192942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void inquiry_result_with_rssi(int index, int plen, void *ptr) 19305288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1931fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19325288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 19335288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 19345288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19355288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!num) 19365288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 19375288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19385288199788ecb17183d6517da3062cd94692a900Johan Hedberg if ((plen - 1) / num == INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE) { 19395288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19405288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info_with_rssi_and_pscan_mode *info = ptr; 19415288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 194242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[1] << 8) 194342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[2] << 16); 19445288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1945b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, 19465288199788ecb17183d6517da3062cd94692a900Johan Hedberg class, info->rssi, NULL); 19475288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE; 19485288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19495288199788ecb17183d6517da3062cd94692a900Johan Hedberg } else { 19505288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19515288199788ecb17183d6517da3062cd94692a900Johan Hedberg inquiry_info_with_rssi *info = ptr; 19525288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 195342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[1] << 8) 195442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[2] << 16); 19555288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1956b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, 19575288199788ecb17183d6517da3062cd94692a900Johan Hedberg class, info->rssi, NULL); 19585288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += INQUIRY_INFO_WITH_RSSI_SIZE; 19595288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19605288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19615288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19625288199788ecb17183d6517da3062cd94692a900Johan Hedberg 196342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void extended_inquiry_result(int index, int plen, void *ptr) 19645288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1965fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19665288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint8_t num = *(uint8_t *) ptr++; 19675288199788ecb17183d6517da3062cd94692a900Johan Hedberg int i; 19685288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19695288199788ecb17183d6517da3062cd94692a900Johan Hedberg for (i = 0; i < num; i++) { 19705288199788ecb17183d6517da3062cd94692a900Johan Hedberg extended_inquiry_info *info = ptr; 19715288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = info->dev_class[0] 197242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[1] << 8) 197342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg | (info->dev_class[2] << 16); 19745288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1975b98312395e628aa8e7c25b963dad7d21c714fcc7Johan Hedberg btd_event_device_found(&dev->bdaddr, &info->bdaddr, class, 19765288199788ecb17183d6517da3062cd94692a900Johan Hedberg info->rssi, info->data); 19775288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += EXTENDED_INQUIRY_INFO_SIZE; 19785288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 19795288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19805288199788ecb17183d6517da3062cd94692a900Johan Hedberg 198142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void remote_features_information(int index, void *ptr) 19825288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 1983fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 19845288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_read_remote_features_complete *evt = ptr; 1985b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 19865288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19870e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 19880e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 19895288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->status) 19905288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 19915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1992b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 1993b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 19945288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 19955288199788ecb17183d6517da3062cd94692a900Johan Hedberg 1996b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg write_features_info(&dev->bdaddr, &conn->bdaddr, evt->features, NULL); 19975288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 19985288199788ecb17183d6517da3062cd94692a900Johan Hedberg 19998e17ca3a784294aec947866071c38d934e21940dJohan Hedbergstruct remote_version_req { 20008e17ca3a784294aec947866071c38d934e21940dJohan Hedberg int index; 20018e17ca3a784294aec947866071c38d934e21940dJohan Hedberg uint16_t handle; 20028e17ca3a784294aec947866071c38d934e21940dJohan Hedberg}; 20038e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20048e17ca3a784294aec947866071c38d934e21940dJohan Hedbergstatic gboolean __get_remote_version(gpointer user_data) 20058e17ca3a784294aec947866071c38d934e21940dJohan Hedberg{ 20068e17ca3a784294aec947866071c38d934e21940dJohan Hedberg struct remote_version_req *req = user_data; 20078e17ca3a784294aec947866071c38d934e21940dJohan Hedberg struct dev_info *dev = &devs[req->index]; 20088e17ca3a784294aec947866071c38d934e21940dJohan Hedberg read_remote_version_cp cp; 20098e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20108e17ca3a784294aec947866071c38d934e21940dJohan Hedberg DBG("hci%d handle %u", req->index, req->handle); 20118e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20128e17ca3a784294aec947866071c38d934e21940dJohan Hedberg memset(&cp, 0, sizeof(cp)); 20138e17ca3a784294aec947866071c38d934e21940dJohan Hedberg cp.handle = htobs(req->handle); 20148e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20158e17ca3a784294aec947866071c38d934e21940dJohan Hedberg hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_READ_REMOTE_VERSION, 20168e17ca3a784294aec947866071c38d934e21940dJohan Hedberg READ_REMOTE_VERSION_CP_SIZE, &cp); 20178e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20188e17ca3a784294aec947866071c38d934e21940dJohan Hedberg return FALSE; 20198e17ca3a784294aec947866071c38d934e21940dJohan Hedberg} 20208e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20218e17ca3a784294aec947866071c38d934e21940dJohan Hedbergstatic void get_remote_version(int index, uint16_t handle) 20228e17ca3a784294aec947866071c38d934e21940dJohan Hedberg{ 20238e17ca3a784294aec947866071c38d934e21940dJohan Hedberg struct remote_version_req *req; 20248e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20258e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req = g_new0(struct remote_version_req, 1); 20268e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req->handle = handle; 20278e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req->index = index; 20288e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 20298e17ca3a784294aec947866071c38d934e21940dJohan Hedberg g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 1, __get_remote_version, 20308e17ca3a784294aec947866071c38d934e21940dJohan Hedberg req, g_free); 20318e17ca3a784294aec947866071c38d934e21940dJohan Hedberg} 20328e17ca3a784294aec947866071c38d934e21940dJohan Hedberg 2033b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic void conn_free(struct bt_conn *conn) 2034b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 2035b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io != NULL) { 2036b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_shutdown(conn->io, TRUE, NULL); 2037b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_unref(conn->io); 2038b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 2039b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 2040b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_free(conn); 2041b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 2042b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 204332c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedbergstatic inline void conn_failed(int index, bdaddr_t *bdaddr, uint8_t status) 204432c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg{ 204532c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg struct dev_info *dev = &devs[index]; 204632c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg struct bt_conn *conn; 204732c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 204832c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 204932c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn = find_connection(dev, bdaddr); 205032c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg if (conn == NULL) 205132c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg return; 205232c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 2053d4a25e44a88e15da6f523183b30997e6669c481dJohan Hedberg bonding_complete(dev, conn, status); 205432c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 205532c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg dev->connections = g_slist_remove(dev->connections, conn); 205632c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn_free(conn); 20572645460e07951a5c66c24b057c0dafce3f399c63Jaikumar Ganesh 20582645460e07951a5c66c24b057c0dafce3f399c63Jaikumar Ganesh btd_event_conn_failed(&dev->bdaddr, bdaddr, status); 205932c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg} 206032c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg 206142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void conn_complete(int index, void *ptr) 20625288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2063fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 20645288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_conn_complete *evt = ptr; 20655288199788ecb17183d6517da3062cd94692a900Johan Hedberg char filename[PATH_MAX]; 20665288199788ecb17183d6517da3062cd94692a900Johan Hedberg char local_addr[18], peer_addr[18], *str; 2067b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 20685288199788ecb17183d6517da3062cd94692a900Johan Hedberg 20695288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (evt->link_type != ACL_LINK) 20705288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 20715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2072b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("status 0x%02x", evt->status); 2073bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 207432c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg if (evt->status != 0) { 207532c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn_failed(index, &evt->bdaddr, evt->status); 207632c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg return; 2077bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg } 2078bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 207932c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn = get_connection(dev, &evt->bdaddr); 208032c3d13c1f736c2a500df0b1f497ebcdb9fb27fdJohan Hedberg conn->handle = btohs(evt->handle); 20815288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2082b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg btd_event_conn_complete(&dev->bdaddr, &evt->bdaddr); 20835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2084b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->secmode3) 2085b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, 0); 2086b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 20875288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* check if the remote version needs be requested */ 2088fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg ba2str(&dev->bdaddr, local_addr); 20895288199788ecb17183d6517da3062cd94692a900Johan Hedberg ba2str(&evt->bdaddr, peer_addr); 20905288199788ecb17183d6517da3062cd94692a900Johan Hedberg 20915288199788ecb17183d6517da3062cd94692a900Johan Hedberg create_name(filename, sizeof(filename), STORAGEDIR, local_addr, 20925288199788ecb17183d6517da3062cd94692a900Johan Hedberg "manufacturers"); 20935288199788ecb17183d6517da3062cd94692a900Johan Hedberg 20945288199788ecb17183d6517da3062cd94692a900Johan Hedberg str = textfile_get(filename, peer_addr); 20955288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (!str) 20968e17ca3a784294aec947866071c38d934e21940dJohan Hedberg get_remote_version(index, btohs(evt->handle)); 20975288199788ecb17183d6517da3062cd94692a900Johan Hedberg else 20985288199788ecb17183d6517da3062cd94692a900Johan Hedberg free(str); 20995288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21005288199788ecb17183d6517da3062cd94692a900Johan Hedberg 21015f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demariostatic inline void le_conn_complete(int index, void *ptr) 21025f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario{ 2103fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21045f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario evt_le_connection_complete *evt = ptr; 21055f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario char filename[PATH_MAX]; 21065f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario char local_addr[18], peer_addr[18], *str; 2107b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg struct bt_conn *conn; 21085f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 2109b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg if (evt->status) { 2110b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg btd_event_conn_failed(&dev->bdaddr, &evt->peer_bdaddr, 2111b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg evt->status); 2112b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg return; 2113bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg } 2114bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2115b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg conn = get_connection(dev, &evt->peer_bdaddr); 2116b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg conn->handle = btohs(evt->handle); 21175f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 2118b18b51e97bddc67c8b4ff10a3f97241ac480596aJohan Hedberg btd_event_conn_complete(&dev->bdaddr, &evt->peer_bdaddr); 21195f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 21205f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario /* check if the remote version needs be requested */ 2121fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg ba2str(&dev->bdaddr, local_addr); 21225f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario ba2str(&evt->peer_bdaddr, peer_addr); 21235f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 21245f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario create_name(filename, sizeof(filename), STORAGEDIR, local_addr, 21255f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario "manufacturers"); 21265f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 21275f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario str = textfile_get(filename, peer_addr); 21285f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario if (!str) 21298e17ca3a784294aec947866071c38d934e21940dJohan Hedberg get_remote_version(index, btohs(evt->handle)); 21305f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario else 21315f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario free(str); 21325f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario} 21335f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 213442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void disconn_complete(int index, void *ptr) 21355288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2136fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21375288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_disconn_complete *evt = ptr; 2138b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 2139b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 2140b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg DBG("handle %u status 0x%02x", btohs(evt->handle), evt->status); 2141bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2142bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg if (evt->status != 0) 2143bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return; 21445288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2145b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 2146b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 2147bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return; 2148bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2149b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->connections = g_slist_remove(dev->connections, conn); 2150bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2151bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg btd_event_disconn_complete(&dev->bdaddr, &conn->bdaddr); 2152bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2153b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn_free(conn); 21545288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21555288199788ecb17183d6517da3062cd94692a900Johan Hedberg 215642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void auth_complete(int index, void *ptr) 21575288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2158fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21595288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_auth_complete *evt = ptr; 2160b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 21615288199788ecb17183d6517da3062cd94692a900Johan Hedberg 21620e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 21630e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2164b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_conn_by_handle(dev, btohs(evt->handle)); 2165b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL) 21665288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 21675288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2168b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, evt->status); 21695288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21705288199788ecb17183d6517da3062cd94692a900Johan Hedberg 217142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void simple_pairing_complete(int index, void *ptr) 21725288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2173fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21745288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_simple_pairing_complete *evt = ptr; 21755288199788ecb17183d6517da3062cd94692a900Johan Hedberg 21760e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d status %u", index, evt->status); 21770e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2178fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_simple_pairing_complete(&dev->bdaddr, &evt->bdaddr, 217942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg evt->status); 21805288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21815288199788ecb17183d6517da3062cd94692a900Johan Hedberg 218242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedbergstatic inline void conn_request(int index, void *ptr) 21835288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2184fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21855288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_conn_request *evt = ptr; 21865288199788ecb17183d6517da3062cd94692a900Johan Hedberg uint32_t class = evt->dev_class[0] | (evt->dev_class[1] << 8) 21875288199788ecb17183d6517da3062cd94692a900Johan Hedberg | (evt->dev_class[2] << 16); 21885288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2189fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg btd_event_remote_class(&dev->bdaddr, &evt->bdaddr, class); 21905288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 21915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 21925f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demariostatic inline void le_advertising_report(int index, evt_le_meta_event *meta) 21935288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2194fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 21955288199788ecb17183d6517da3062cd94692a900Johan Hedberg le_advertising_info *info; 2196f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira uint8_t num_reports, rssi, eir[HCI_MAX_EIR_LENGTH]; 2197e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes const uint8_t RSSI_SIZE = 1; 21985288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2199e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes num_reports = meta->data[0]; 22005288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2201e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes info = (le_advertising_info *) &meta->data[1]; 22025b1f949a427b39091959537f196c5d322997453fBruna Moreira rssi = *(info->data + info->length); 22035b1f949a427b39091959537f196c5d322997453fBruna Moreira 2204f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memset(eir, 0, sizeof(eir)); 2205f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memcpy(eir, info->data, info->length); 2206f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira 2207f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira btd_event_device_found(&dev->bdaddr, &info->bdaddr, 0, rssi, eir); 22085b1f949a427b39091959537f196c5d322997453fBruna Moreira 2209e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes num_reports--; 2210e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes 2211e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes while (num_reports--) { 2212e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes info = (le_advertising_info *) (info->data + info->length + 2213e27614655c3c37d1ed82a944e9f34e129a7c1f6cAndre Guedes RSSI_SIZE); 22145b1f949a427b39091959537f196c5d322997453fBruna Moreira rssi = *(info->data + info->length); 22155b1f949a427b39091959537f196c5d322997453fBruna Moreira 2216f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memset(eir, 0, sizeof(eir)); 2217f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira memcpy(eir, info->data, info->length); 2218f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira 22195b1f949a427b39091959537f196c5d322997453fBruna Moreira btd_event_device_found(&dev->bdaddr, &info->bdaddr, 0, rssi, 2220f169bea7d5b30d84ccea7f687a2698b7a8894054Bruna Moreira eir); 22215288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 22225288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 22235288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22245f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demariostatic inline void le_metaevent(int index, void *ptr) 22255f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario{ 22265f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario evt_le_meta_event *meta = ptr; 22275f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 22285f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario DBG("hci%d LE Meta Event %u", index, meta->subevent); 22295f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 22305f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario switch (meta->subevent) { 22315f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario case EVT_LE_ADVERTISING_REPORT: 22325f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario le_advertising_report(index, meta); 22335f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario break; 22345f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 22355f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario case EVT_LE_CONN_COMPLETE: 22365f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario le_conn_complete(index, meta->data); 22375f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario break; 22385f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario } 22395f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario} 22405f9ebfaa84eacb59a47bcdd6c9479d8b94552414Sheldon Demario 224155694454017b04a416931a81964bb695f48b3d93Johan Hedbergstatic void stop_hci_dev(int index) 22425288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2243fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 22445288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2245b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->sk < 0) 22465288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 22475288199788ecb17183d6517da3062cd94692a900Johan Hedberg 224855694454017b04a416931a81964bb695f48b3d93Johan Hedberg info("Stopping hci%d event socket", index); 22495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2250b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->watch_id > 0) 2251b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_source_remove(dev->watch_id); 2252b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 22539235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (dev->stop_scan_id > 0) 22549235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes g_source_remove(dev->stop_scan_id); 22559235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 2256b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->io != NULL) 2257b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_io_channel_unref(dev->io); 2258b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 2259fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_close_dev(dev->sk); 2260b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 2261b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_slist_foreach(dev->keys, (GFunc) g_free, NULL); 2262b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_slist_free(dev->keys); 2263b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 22643e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg g_slist_foreach(dev->uuids, (GFunc) g_free, NULL); 22653e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg g_slist_free(dev->uuids); 22663e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 2267b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_slist_foreach(dev->connections, (GFunc) conn_free, NULL); 2268bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg g_slist_free(dev->connections); 2269bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg 2270149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz init_dev_info(index, -1, dev->registered, dev->already_up); 22715288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 22725288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22735288199788ecb17183d6517da3062cd94692a900Johan Hedbergstatic gboolean io_security_event(GIOChannel *chan, GIOCondition cond, 22745288199788ecb17183d6517da3062cd94692a900Johan Hedberg gpointer data) 22755288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 22765288199788ecb17183d6517da3062cd94692a900Johan Hedberg unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf; 227742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg int type, index = GPOINTER_TO_INT(data); 2278fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 227942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg struct hci_dev_info di; 228090e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz ssize_t len; 22815288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_event_hdr *eh; 22825288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt_cmd_status *evt; 228390e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz int fd; 22845288199788ecb17183d6517da3062cd94692a900Johan Hedberg 22855288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { 228655694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 22875288199788ecb17183d6517da3062cd94692a900Johan Hedberg return FALSE; 22885288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 22895288199788ecb17183d6517da3062cd94692a900Johan Hedberg 229090e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz fd = g_io_channel_unix_get_fd(chan); 229190e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz 229290e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz len = read(fd, buf, sizeof(buf)); 229390e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (len < 0) { 229490e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (errno == EAGAIN) 22955288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 229655694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 22975288199788ecb17183d6517da3062cd94692a900Johan Hedberg return FALSE; 22985288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 22995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23005288199788ecb17183d6517da3062cd94692a900Johan Hedberg type = *ptr++; 23015288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23025288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (type != HCI_EVENT_PKT) 23035288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 23045288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23055288199788ecb17183d6517da3062cd94692a900Johan Hedberg eh = (hci_event_hdr *) ptr; 23065288199788ecb17183d6517da3062cd94692a900Johan Hedberg ptr += HCI_EVENT_HDR_SIZE; 23075288199788ecb17183d6517da3062cd94692a900Johan Hedberg 230842bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg memset(&di, 0, sizeof(di)); 230942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg if (hci_devinfo(index, &di) == 0) { 2310fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(&dev->bdaddr, &di.bdaddr); 23115288199788ecb17183d6517da3062cd94692a900Johan Hedberg 231242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg if (ignore_device(&di)) 231342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg return TRUE; 231442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg } 231555694454017b04a416931a81964bb695f48b3d93Johan Hedberg 23165288199788ecb17183d6517da3062cd94692a900Johan Hedberg switch (eh->evt) { 23175288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CMD_STATUS: 231842bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg cmd_status(index, ptr); 23195288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23215288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CMD_COMPLETE: 232242bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg cmd_complete(index, ptr); 23235288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23245288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23255288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_NAME_REQ_COMPLETE: 232642bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_name_information(index, ptr); 23275288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23285288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23295288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_READ_REMOTE_VERSION_COMPLETE: 233042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_version_information(index, ptr); 23315288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23325288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23335288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_READ_REMOTE_FEATURES_COMPLETE: 233442bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_features_information(index, ptr); 23355288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23365288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23375288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_HOST_FEATURES_NOTIFY: 233842bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg remote_features_notify(index, ptr); 23395288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23405288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23415288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_COMPLETE: 23425288199788ecb17183d6517da3062cd94692a900Johan Hedberg evt = (evt_cmd_status *) ptr; 23432a807a5036c78957f4c91c3379c6075d895aadf5Andre Guedes inquiry_complete_evt(index, evt->status); 23445288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23455288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23465288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_RESULT: 234742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg inquiry_result(index, eh->plen, ptr); 23485288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23495288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23505288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_INQUIRY_RESULT_WITH_RSSI: 235142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg inquiry_result_with_rssi(index, eh->plen, ptr); 23525288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23535288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23545288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_EXTENDED_INQUIRY_RESULT: 235542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg extended_inquiry_result(index, eh->plen, ptr); 23565288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23575288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23585288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CONN_COMPLETE: 235942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg conn_complete(index, ptr); 23605288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23615288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23625288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_DISCONN_COMPLETE: 236342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg disconn_complete(index, ptr); 23645288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23655288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23665288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_AUTH_COMPLETE: 236742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg auth_complete(index, ptr); 23685288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23695288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23705288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_SIMPLE_PAIRING_COMPLETE: 237142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg simple_pairing_complete(index, ptr); 23725288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23735288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23745288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_CONN_REQUEST: 237542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg conn_request(index, ptr); 23765288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23775288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LE_META_EVENT: 237842bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg le_metaevent(index, ptr); 23795288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23805288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_PIN_CODE_REQ: 238142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg pin_code_request(index, (bdaddr_t *) ptr); 23825288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23845288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LINK_KEY_REQ: 238542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg link_key_request(index, (bdaddr_t *) ptr); 23865288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23875288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23885288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_LINK_KEY_NOTIFY: 238942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg link_key_notify(index, ptr); 23905288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23915288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23925288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_RETURN_LINK_KEYS: 239342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg return_link_keys(index, ptr); 23945288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23955288199788ecb17183d6517da3062cd94692a900Johan Hedberg 23965288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_IO_CAPABILITY_REQUEST: 239742bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg io_capa_request(index, ptr); 23985288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 23995288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24005288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_IO_CAPABILITY_RESPONSE: 240142bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg io_capa_response(index, ptr); 24025288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24035288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24045288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_CONFIRM_REQUEST: 240542bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg user_confirm_request(index, ptr); 24065288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24075288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24085288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_PASSKEY_REQUEST: 240942bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg user_passkey_request(index, ptr); 24105288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24115288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24125288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_USER_PASSKEY_NOTIFY: 241342bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg user_passkey_notify(index, ptr); 24145288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24155288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24165288199788ecb17183d6517da3062cd94692a900Johan Hedberg case EVT_REMOTE_OOB_DATA_REQUEST: 241723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc remote_oob_data_request(index, (bdaddr_t *) ptr); 24185288199788ecb17183d6517da3062cd94692a900Johan Hedberg break; 24195288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 24205288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24215288199788ecb17183d6517da3062cd94692a900Johan Hedberg return TRUE; 24225288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 24235288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24245a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedbergstatic void start_hci_dev(int index) 24255288199788ecb17183d6517da3062cd94692a900Johan Hedberg{ 2426fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2427fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg GIOChannel *chan = dev->io; 2428e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg GIOCondition cond; 24295288199788ecb17183d6517da3062cd94692a900Johan Hedberg struct hci_filter flt; 24305288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24315288199788ecb17183d6517da3062cd94692a900Johan Hedberg if (chan) 24325288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 24335288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24345a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg info("Listening for HCI events on hci%d", index); 24355288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24365288199788ecb17183d6517da3062cd94692a900Johan Hedberg /* Set filter */ 24375288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_clear(&flt); 24385288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 24395288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CMD_STATUS, &flt); 24405288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CMD_COMPLETE, &flt); 24415288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_PIN_CODE_REQ, &flt); 24425288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LINK_KEY_REQ, &flt); 24435288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LINK_KEY_NOTIFY, &flt); 24445288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_RETURN_LINK_KEYS, &flt); 24455288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_IO_CAPABILITY_REQUEST, &flt); 24465288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_IO_CAPABILITY_RESPONSE, &flt); 24475288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_CONFIRM_REQUEST, &flt); 24485288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_PASSKEY_REQUEST, &flt); 24495288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_OOB_DATA_REQUEST, &flt); 24505288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_USER_PASSKEY_NOTIFY, &flt); 24515288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_KEYPRESS_NOTIFY, &flt); 24525288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_SIMPLE_PAIRING_COMPLETE, &flt); 24535288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_AUTH_COMPLETE, &flt); 24545288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt); 24555288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_READ_REMOTE_VERSION_COMPLETE, &flt); 24565288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_READ_REMOTE_FEATURES_COMPLETE, &flt); 24575288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_REMOTE_HOST_FEATURES_NOTIFY, &flt); 24585288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt); 24595288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); 24605288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt); 24615288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_EXTENDED_INQUIRY_RESULT, &flt); 24625288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CONN_REQUEST, &flt); 24635288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_CONN_COMPLETE, &flt); 24645288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_DISCONN_COMPLETE, &flt); 24655288199788ecb17183d6517da3062cd94692a900Johan Hedberg hci_filter_set_event(EVT_LE_META_EVENT, &flt); 2466fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (setsockopt(dev->sk, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 24675288199788ecb17183d6517da3062cd94692a900Johan Hedberg error("Can't set filter on hci%d: %s (%d)", 24685a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg index, strerror(errno), errno); 24695288199788ecb17183d6517da3062cd94692a900Johan Hedberg return; 24705288199788ecb17183d6517da3062cd94692a900Johan Hedberg } 24715288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2472fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg chan = g_io_channel_unix_new(dev->sk); 2473e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg cond = G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR; 2474fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->watch_id = g_io_add_watch_full(chan, G_PRIORITY_LOW, cond, 2475e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg io_security_event, 2476e5828c7e30453232e930dbead0e359175dc1decfJohan Hedberg GINT_TO_POINTER(index), NULL); 2477fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->io = chan; 24781522d6568002afa27ee7a3280b3166f7ecb02f06Johan Hedberg dev->pin_length = 0; 24795288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24805288199788ecb17183d6517da3062cd94692a900Johan Hedberg} 24815288199788ecb17183d6517da3062cd94692a900Johan Hedberg 24825288199788ecb17183d6517da3062cd94692a900Johan Hedberg/* End of HCI event callbacks */ 24835288199788ecb17183d6517da3062cd94692a900Johan Hedberg 2484a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) 2485a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2486a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode int status, fd = g_io_channel_unix_get_fd(io); 2487a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t child_pid; 2488a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2489a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) { 2490a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("child_exit: unable to read child pid from pipe"); 2491a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 2492a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2493a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2494a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (waitpid(child_pid, &status, 0) != child_pid) 2495a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("waitpid(%d) failed", child_pid); 2496a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode else 24978e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d exited", child_pid); 2498a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2499a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return TRUE; 2500a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2501a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2502a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodestatic void at_child_exit(void) 2503a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2504a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid_t pid = getpid(); 2505a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2506a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid)) 2507a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("unable to write to child pipe"); 2508a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2509a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2510fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedbergstatic void device_devup_setup(int index) 2511a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2512fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2513a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_info di; 25145a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg read_stored_link_key_cp cp; 2515a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 25160e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 25170e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2518ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (hci_devinfo(index, &di) < 0) 2519a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 2520a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 252165bf1321203b55b11167ac8b869da28a86ce49d2David Scherba if (ignore_device(&di)) 2522a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode return; 2523a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2524fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(&dev->bdaddr, &di.bdaddr); 2525fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->features, di.features, 8); 2526a352058752e541539b09e55124d411a534cc14afJohan Hedberg 2527a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set page timeout */ 2528a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if ((main_opts.flags & (1 << HCID_SET_PAGETO))) { 2529a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode write_page_timeout_cp cp; 2530a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2531a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode cp.timeout = htobs(main_opts.pageto); 2532fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, 2533a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode WRITE_PAGE_TIMEOUT_CP_SIZE, &cp); 2534a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2535a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 25365a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg bacpy(&cp.bdaddr, BDADDR_ANY); 25375a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg cp.read_all = 1; 2538fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY, 25396d2ce6e859049d6cf56e5db2197e02b0359ac442Johan Hedberg READ_STORED_LINK_KEY_CP_SIZE, &cp); 2540fccdf4a50765ef5a2dbde00d95f65e94ce0a543bJohan Hedberg 2541fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->pending) 25425c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg init_adapter(index); 2543a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2544a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2545be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedbergstatic void init_pending(int index) 2546be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg{ 2547fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2548fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 2549fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_BDADDR, &dev->pending); 2550fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_VERSION, &dev->pending); 2551fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_FEATURES, &dev->pending); 2552fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_NAME, &dev->pending); 2553be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg} 2554be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 255571ba00415bd2941db24958d1e6e265611945194eJohan Hedbergstatic struct dev_info *init_device(int index, gboolean already_up) 2556a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 255771ba00415bd2941db24958d1e6e265611945194eJohan Hedberg struct dev_info *dev; 2558a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode struct hci_dev_req dr; 2559c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg int dd; 25606844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg pid_t pid; 25616844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 25620e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 25630e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 25646844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg dd = hci_open_dev(index); 25656844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (dd < 0) { 25666844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Unable to open hci%d: %s (%d)", index, 25676844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg strerror(errno), errno); 256871ba00415bd2941db24958d1e6e265611945194eJohan Hedberg return NULL; 25696844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg } 25706844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 25716844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (index > max_dev) { 25726844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg max_dev = index; 2573ef071f94a765fa0b0e96935abef7508c76cace00Johan Hedberg devs = g_realloc(devs, sizeof(devs[0]) * (max_dev + 1)); 25746844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg } 25756844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 257671ba00415bd2941db24958d1e6e265611945194eJohan Hedberg dev = init_dev_info(index, dd, FALSE, already_up); 2577be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg init_pending(index); 25785a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg start_hci_dev(index); 2579a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2580149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz /* Avoid forking if nothing else has to be done */ 2581149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz if (already_up) 258271ba00415bd2941db24958d1e6e265611945194eJohan Hedberg return dev; 2583149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz 2584a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Do initialization in the separate process */ 2585a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode pid = fork(); 2586a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (pid) { 2587a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case 0: 2588a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode atexit(at_child_exit); 2589a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2590a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case -1: 2591a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Fork failed. Can't init device hci%d: %s (%d)", 2592c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg index, strerror(errno), errno); 2593a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode default: 25948e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan DBG("child %d forked", pid); 259571ba00415bd2941db24958d1e6e265611945194eJohan Hedberg return dev; 2596a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2597a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2598a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode memset(&dr, 0, sizeof(dr)); 2599ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode dr.dev_id = index; 2600a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2601a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Set link mode */ 2602a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode dr.dev_opt = main_opts.link_mode; 2603c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0) 2604a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't set link mode on hci%d: %s (%d)", 2605ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg index, strerror(errno), errno); 2606a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2607a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode /* Start HCI device */ 2608ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode if (ioctl(dd, HCIDEVUP, index) < 0 && errno != EALREADY) { 2609a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode error("Can't init device hci%d: %s (%d)", 2610ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode index, strerror(errno), errno); 2611a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode goto fail; 2612a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2613a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2614a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 2615a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(0); 2616a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2617a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsodefail: 2618a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode hci_close_dev(dd); 2619a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode exit(1); 2620a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2621a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2622cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedbergstatic void init_conn_list(int index) 2623cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg{ 2624cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg struct dev_info *dev = &devs[index]; 2625cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg struct hci_conn_list_req *cl; 2626cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg struct hci_conn_info *ci; 2627b671636c82f5c2eff114d3eb98cae8ff599f3fdcSzymon Janc int i; 2628cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2629cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg DBG("hci%d", index); 2630cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2631cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); 2632cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2633cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg cl->dev_id = index; 2634cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg cl->conn_num = 10; 2635cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg ci = cl->conn_info; 2636cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2637cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg if (ioctl(dev->sk, HCIGETCONNLIST, cl) < 0) { 2638cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg error("Unable to get connection list: %s (%d)", 2639cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg strerror(errno), errno); 2640cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg goto failed; 2641cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg } 2642cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2643cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg for (i = 0; i < cl->conn_num; i++, ci++) { 2644b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 2645cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2646cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg if (ci->type != ACL_LINK) 2647cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg continue; 2648cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2649b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, &ci->bdaddr); 2650cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg conn->handle = ci->handle; 2651cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg } 2652cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2653cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedbergfailed: 2654cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg g_free(cl); 2655cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg} 2656cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 2657ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsodestatic void device_event(int event, int index) 2658a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode{ 2659a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode switch (event) { 2660a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_REG: 2661ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d registered", index); 2662149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz init_device(index, FALSE); 2663a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2664a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2665a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UNREG: 2666ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d unregistered", index); 266755694454017b04a416931a81964bb695f48b3d93Johan Hedberg stop_hci_dev(index); 2668fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (devs[index].registered) 26695c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg btd_manager_unregister_adapter(index); 2670a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2671a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2672a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_UP: 2673ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d up", index); 2674fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].up = TRUE; 2675ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode device_devup_setup(index); 2676a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2677a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2678a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode case HCI_DEV_DOWN: 2679ffff055ee50ab909b61e2b904bfa71dde42ee5c7Alok Barsode info("HCI dev %d down", index); 2680fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].up = FALSE; 2681fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].pending_cod = 0; 2682fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg devs[index].cache_enable = TRUE; 2683fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!devs[index].pending) { 268465edd4d5397d00d204123432fd83326486860783Johan Hedberg struct btd_adapter *adapter; 268565edd4d5397d00d204123432fd83326486860783Johan Hedberg 2686f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg adapter = manager_find_adapter_by_id(index); 268765edd4d5397d00d204123432fd83326486860783Johan Hedberg if (adapter) 2688f674830abac4c9e7ee4d96a354e0f7850942d548Johan Hedberg btd_adapter_stop(adapter); 268965edd4d5397d00d204123432fd83326486860783Johan Hedberg 2690be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg init_pending(index); 26915a58cd8ac9a93cfde63371872cd89ff8b190c52cJohan Hedberg } 2692a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode break; 2693a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2694a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode} 2695cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2696f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedbergstatic gboolean init_known_adapters(gpointer user_data) 269794e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 2698cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_list_req *dl; 2699cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_dev_req *dr; 2700f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg int i, err, ctl = GPOINTER_TO_INT(user_data); 2701ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg size_t req_size; 2702cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 27030e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 27040e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2705ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg req_size = HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t); 2706ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg 2707ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg dl = g_try_malloc0(req_size); 2708cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (!dl) { 2709ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg error("Can't allocate devlist buffer"); 2710f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 2711cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2712cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2713cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dl->dev_num = HCI_MAX_DEV; 2714cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode dr = dl->dev_req; 2715cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2716ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg if (ioctl(ctl, HCIGETDEVLIST, dl) < 0) { 2717c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2718ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg error("Can't get device list: %s (%d)", strerror(-err), -err); 271983003660808c30390f21c569a5ba7dbdd8344a41Claudio Takahasi g_free(dl); 2720f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 2721cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2722cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2723cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode for (i = 0; i < dl->dev_num; i++, dr++) { 2724fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev; 2725149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz gboolean already_up; 2726fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 2727149f5d0b49d7c52e64e3c63505f689a9f872af8bLuiz Augusto von Dentz already_up = hci_test_bit(HCI_UP, &dr->dev_opt); 2728cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 272971ba00415bd2941db24958d1e6e265611945194eJohan Hedberg dev = init_device(dr->dev_id, already_up); 273071ba00415bd2941db24958d1e6e265611945194eJohan Hedberg if (dev == NULL) 273171ba00415bd2941db24958d1e6e265611945194eJohan Hedberg continue; 27325c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 2733fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->already_up) 2734be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg continue; 2735be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg 27369ac53f53be09b96ebd6379b3c7113a05324b47dfLuiz Augusto von Dentz init_conn_list(dr->dev_id); 27375c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 2738fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->pending = 0; 2739fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_set_bit(PENDING_VERSION, &dev->pending); 2740fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg hci_send_cmd(dev->sk, OGF_INFO_PARAM, 2741be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg OCF_READ_LOCAL_VERSION, 0, NULL); 2742be3d4f5e4c621718de0dc0fb4f947635682f1a95Johan Hedberg device_event(HCI_DEV_UP, dr->dev_id); 2743cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2744cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2745cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_free(dl); 2746f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg 2747f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return FALSE; 274894e91856179a268805256055ffd5155d1468b99cAlok Barsode} 274994e91856179a268805256055ffd5155d1468b99cAlok Barsode 2750cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsodestatic gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, 2751cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode gpointer data) 2752cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 2753cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; 2754cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_stack_internal *si; 2755cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode evt_si_device *sd; 2756cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_event_hdr *eh; 275790e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz int type, fd; 275890e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz ssize_t len; 2759cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2760cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr = buf; 2761cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 276290e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz fd = g_io_channel_unix_get_fd(chan); 276390e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz 276490e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz len = read(fd, buf, sizeof(buf)); 276590e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (len < 0) { 276690e78131e3e347eeee25e5cd831b374907359e3fLuiz Augusto von Dentz if (errno == EAGAIN) 2767cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2768cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2769cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode error("Read from control socket failed: %s (%d)", 2770ad737e6427a5bfb09bc26c4af071a7aa7045f0acJohan Hedberg strerror(errno), errno); 2771cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return FALSE; 2772cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2773cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2774cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode type = *ptr++; 2775cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2776cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (type != HCI_EVENT_PKT) 2777cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2778cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2779cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode eh = (hci_event_hdr *) ptr; 2780cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (eh->evt != EVT_STACK_INTERNAL) 2781cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2782cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2783cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ptr += HCI_EVENT_HDR_SIZE; 2784cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2785cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode si = (evt_stack_internal *) ptr; 2786cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode switch (si->type) { 2787cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode case EVT_SI_DEVICE: 2788cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sd = (void *) &si->data; 2789cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode device_event(sd->event, sd->dev_id); 2790cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode break; 2791cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2792cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2793cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode return TRUE; 2794cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 2795cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 279634c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_setup(void) 2797cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode{ 2798cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct sockaddr_hci addr; 2799cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode struct hci_filter flt; 2800a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode GIOChannel *ctl_io, *child_io; 280118e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg int sock, err; 280218e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg 28030e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 28040e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 280518e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg if (child_pipe[0] != -1) 280618e8b33f0d60b9e1f4a6521720e14e9db1cda01dJohan Hedberg return -EALREADY; 2807cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2808a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode if (pipe(child_pipe) < 0) { 2809c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2810c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("pipe(): %s (%d)", strerror(-err), -err); 2811c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2812a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode } 2813a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2814a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode child_io = g_io_channel_unix_new(child_pipe[0]); 2815a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_set_close_on_unref(child_io, TRUE); 28168b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = g_io_add_watch(child_io, 28178b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 28188b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_exit, NULL); 2819a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode g_io_channel_unref(child_io); 2820a557e08d8c3e39439e922b1267d13c8cf34e37eaAlok Barsode 2821cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Create and bind HCI socket */ 2822cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 2823cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode if (sock < 0) { 2824c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2825c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("Can't open HCI socket: %s (%d)", strerror(-err), 2826c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg -err); 2827c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2828cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2829cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2830cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode /* Set filter */ 2831cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_clear(&flt); 2832cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 2833cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode hci_filter_set_event(EVT_STACK_INTERNAL, &flt); 28346844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 2835c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 2836c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg error("Can't set filter: %s (%d)", strerror(-err), -err); 2837c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2838cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2839cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2840cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode memset(&addr, 0, sizeof(addr)); 2841cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_family = AF_BLUETOOTH; 2842cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode addr.hci_dev = HCI_DEV_NONE; 28436844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2844c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg err = -errno; 28456844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Can't bind HCI socket: %s (%d)", strerror(-err), -err); 2846c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2847cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode } 2848cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2849cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode ctl_io = g_io_channel_unix_new(sock); 2850cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_set_close_on_unref(ctl_io, TRUE); 2851cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 28528b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); 2853cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2854cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode g_io_channel_unref(ctl_io); 2855cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 2856f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg g_idle_add(init_known_adapters, GINT_TO_POINTER(sock)); 2857f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg 2858f92841301d17330745d286ed35249a3a51c1e4e4Johan Hedberg return 0; 2859cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode} 2860cce9e28ea1ea1cbf5f9e9027c949632ce67cd27fAlok Barsode 286134c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic void hciops_cleanup(void) 286234c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 28636844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int i; 28646844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 28650e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 28660e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2867b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg for (i = 0; i <= max_dev; i++) 2868b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg stop_hci_dev(i); 28696844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 28706844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg g_free(devs); 28716844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg devs = NULL; 28726844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg max_dev = -1; 28736844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg 28748b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_io_id) { 28758b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(child_io_id); 28768b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_io_id = 0; 28778b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 28788b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 28798b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (ctl_io_id) { 28808b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg g_source_remove(ctl_io_id); 28818b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg ctl_io_id = 0; 28828b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 28838b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 28848b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[0] >= 0) { 28858b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[0]); 28868b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[0] = -1; 28878b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 28888b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg 28898b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg if (child_pipe[1] >= 0) { 28908b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg close(child_pipe[1]); 28918b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg child_pipe[1] = -1; 28928b9bab24d5e35777c6838a48d487355ad790a5f4Johan Hedberg } 289334c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 289434c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 289527c58425af807521e618f29b08e7a99496aeda3bJohan Hedbergstatic int hciops_set_powered(int index, gboolean powered) 2896076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode{ 2897fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 28986844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 2899076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 290027c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg DBG("hci%d powered %d", index, powered); 290127c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg 290227c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg if (powered == FALSE) 290327c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg return hciops_power_off(index); 29040e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2905fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (ioctl(dev->sk, HCIDEVUP, index) == 0) 29066844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2907076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 29086844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (errno == EALREADY) 29096844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 2910076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 29116844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 29126844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg error("Can't init device hci%d: %s (%d)", 29136844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg index, strerror(-err), -err); 2914076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 2915c67ba167cc642c34b4b85abbe3a9866cb00c0e57Johan Hedberg return err; 2916076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode} 2917076540a14a41acf8eba0bdb65e2dd5d4d42c7946Alok Barsode 291800c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_set_dev_class(int index, uint8_t major, uint8_t minor) 2919d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode{ 2920fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 292100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg int err; 2922d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 29235c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d major %u minor %u", index, major, minor); 29245c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 292500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Update only the major and minor class bits keeping remaining bits 292600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * intact*/ 2927fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod &= 0xffe000; 2928fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod |= ((major & 0x1f) << 8) | minor; 2929d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 2930fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->wanted_cod == dev->current_cod || 2931fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->cache_enable || dev->pending_cod) 293200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 29330e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 2934fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg DBG("Changing Major/Minor class to 0x%06x", dev->wanted_cod); 2935eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 2936fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = write_class(index, dev->wanted_cod); 293700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (err < 0) 293800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg error("Adapter class update failed: %s (%d)", 293900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg strerror(-err), -err); 2940d2a6bf00afbaeef82f9210639150e1f93cb44589Alok Barsode 294100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return err; 2942eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode} 2943eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode 2944e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedesstatic int hciops_start_inquiry(int index, uint8_t length) 2945a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode{ 2946fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 2947a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; 294817baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes inquiry_cp inq_cp; 2949a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 2950e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedes DBG("hci%d length %u", index, length); 29510e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 295217baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes memset(&inq_cp, 0, sizeof(inq_cp)); 295317baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes memcpy(&inq_cp.lap, lap, 3); 295417baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes inq_cp.length = length; 295517baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes inq_cp.num_rsp = 0x00; 2956a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 295717baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes if (hci_send_cmd(dev->sk, OGF_LINK_CTL, 295817baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes OCF_INQUIRY, INQUIRY_CP_SIZE, &inq_cp) < 0) 295917baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return -errno; 2960a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 296117baf8a0d52b72518cfeab3737d551fe9e2f7488Andre Guedes return 0; 2962a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode} 2963a67cf482f872ae7c87de9478a471cd1e478d688fAlok Barsode 29643ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasistatic int le_set_scan_enable(int index, uint8_t enable) 296570cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi{ 2966fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 29673ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi le_set_scan_enable_cp cp; 29683ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 29690e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d enable %u", index, enable); 29700e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 29713ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi memset(&cp, 0, sizeof(cp)); 29723ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.enable = enable; 29733ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.filter_dup = 0; 297470cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 2975fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, 29763ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi LE_SET_SCAN_ENABLE_CP_SIZE, &cp) < 0) 29776844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 297870cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 29796844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 298070cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi} 298170cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 29829235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedesstatic gboolean stop_le_scan_cb(gpointer user_data) 29839235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes{ 29849235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes struct dev_info *dev = user_data; 29859235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes int err; 29869235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29879235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes err = le_set_scan_enable(dev->id, 0); 29889235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (err < 0) 29899235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return TRUE; 29909235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29919235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes dev->stop_scan_id = 0; 29929235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29939235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return FALSE; 29949235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes} 29959235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 29969235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedesstatic int hciops_start_scanning(int index, int timeout) 299770cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi{ 2998fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 29993ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi le_set_scan_parameters_cp cp; 30009235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes int err; 30013ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 30020e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 30030e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 30043ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi memset(&cp, 0, sizeof(cp)); 30053ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.type = 0x01; /* Active scanning */ 3006051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira /* The recommended value for scan interval and window is 11.25 msec. 3007051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira * It is calculated by: time = n * 0.625 msec */ 3008051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira cp.interval = htobs(0x0012); 3009051ad18433a74feb39f8f3296ea1ddf2ae009aecBruna Moreira cp.window = htobs(0x0012); 30103ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.own_bdaddr_type = 0; /* Public address */ 30113ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi cp.filter = 0; /* Accept all adv packets */ 30123ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 3013fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, 30143ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi LE_SET_SCAN_PARAMETERS_CP_SIZE, &cp) < 0) 301570cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi return -errno; 301670cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 30179235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes err = le_set_scan_enable(index, 1); 30189235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (err < 0) 30199235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return err; 30209235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30219235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes /* Schedule a le scan disable in 'timeout' milliseconds */ 30229235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes dev->stop_scan_id = g_timeout_add(timeout, stop_le_scan_cb, dev); 30239235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30249235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes return 0; 30253ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi} 30263ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi 30273ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasistatic int hciops_stop_scanning(int index) 30283ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi{ 30299235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes struct dev_info *dev = &devs[index]; 30309235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30310e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 30320e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 30339235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes if (dev->stop_scan_id > 0) { 30349235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes g_source_remove(dev->stop_scan_id); 30359235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes dev->stop_scan_id = 0; 30369235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes } 30379235d4b5aea5f420c5330c22a411ab780b272aa6Andre Guedes 30383ef2b1cae64036f074908a927803a45a86e65f04Claudio Takahasi return le_set_scan_enable(index, 0); 303970cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi} 304070cd37db7cdadd72b0cd4c7e3e1b329b79e0d868Claudio Takahasi 3041ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsodestatic int hciops_resolve_name(int index, bdaddr_t *bdaddr) 3042ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode{ 3043fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3044ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode remote_name_req_cp cp; 30450e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 30460e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 30470e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 30480e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 3049ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 3050ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode memset(&cp, 0, sizeof(cp)); 3051ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode bacpy(&cp.bdaddr, bdaddr); 3052ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode cp.pscan_rep_mode = 0x02; 3053ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 3054fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, 30556844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg REMOTE_NAME_REQ_CP_SIZE, &cp) < 0) 30566844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3057ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 30586844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3059ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode} 3060ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode 3061164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsodestatic int hciops_set_name(int index, const char *name) 3062164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode{ 3063fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3064164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode change_local_name_cp cp; 3065164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 30660e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d, name %s", index, name); 30670e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3068164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode memset(&cp, 0, sizeof(cp)); 3069164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode strncpy((char *) cp.name, name, sizeof(cp.name)); 3070164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 3071fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, 30726844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg CHANGE_LOCAL_NAME_CP_SIZE, &cp) < 0) 30736844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3074164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 3075fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(dev->name, cp.name, 248); 307600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 307700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 30786844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3079164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode} 3080164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode 3081b96f44db8e91325968a0149595b2522d4a22481aAlok Barsodestatic int hciops_cancel_resolve_name(int index, bdaddr_t *bdaddr) 3082b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode{ 3083fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3084b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode remote_name_req_cancel_cp cp; 30850e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 30860e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 30870e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 30880e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 3089b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 3090b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode memset(&cp, 0, sizeof(cp)); 3091b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode bacpy(&cp.bdaddr, bdaddr); 3092b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 3093fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL, 30946844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg REMOTE_NAME_REQ_CANCEL_CP_SIZE, &cp) < 0) 30956844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3096b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 30976844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3098b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode} 3099b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode 31004cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedesstatic int hciops_start_discovery(int index) 31014cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes{ 31028be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes int adapter_type = get_adapter_type(index); 31038be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes 31048be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes switch (adapter_type) { 31058be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes case BR_EDR_LE: 3106e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedes return hciops_start_inquiry(index, LENGTH_BR_LE_INQ); 31078be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes case BR_EDR: 3108e6c2d1c3fc81864e38316ed24ade5994b78cc751Andre Guedes return hciops_start_inquiry(index, LENGTH_BR_INQ); 31098be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes case LE_ONLY: 31108be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return hciops_start_scanning(index, TIMEOUT_LE_SCAN); 31118be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes default: 31128be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes return -EINVAL; 31138be3b42e34b9897a2ad3513267b8dcaef17e6157Andre Guedes } 31144cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes} 31154cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes 31164cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedesstatic int hciops_stop_discovery(int index) 31174cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes{ 311857bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes struct dev_info *dev = &devs[index]; 311957bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes 31204cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes DBG("index %d", index); 312157bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes 312257bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes switch (dev->discov_state) { 312357bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes case DISCOV_INQ: 312457bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes return hciops_stop_inquiry(index); 312557bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes case DISCOV_SCAN: 312657bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes return hciops_stop_scanning(index); 312757bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes default: 312857bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes return -EINVAL; 312957bd6dd224eb7eb5683321685b5ea8b093843bfaAndre Guedes } 31304cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes} 31314cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes 313261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliystatic int hciops_fast_connectable(int index, gboolean enable) 313361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy{ 3134fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 313561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy write_page_activity_cp cp; 313661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy uint8_t type; 313761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 31380e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d enable %d", index, enable); 31390e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 314061f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy if (enable) { 314161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_INTERLACED; 314261f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0024; /* 22.5 msec page scan interval */ 314361f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } else { 314461f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy type = PAGE_SCAN_TYPE_STANDARD; /* default */ 314561f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.interval = 0x0800; /* default 1.28 sec page scan */ 314661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy } 314761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 314861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy cp.window = 0x0012; /* default 11.25 msec page scan window */ 314961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 3150fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY, 315161f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy WRITE_PAGE_ACTIVITY_CP_SIZE, &cp) < 0) 31526844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 3153fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg else if (hci_send_cmd(dev->sk, OGF_HOST_CTL, 31546844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_PAGE_SCAN_TYPE, 1, &type) < 0) 31556844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 315661f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 31576844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 315861f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy} 315961f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy 31606b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedbergstatic int hciops_read_clock(int index, bdaddr_t *bdaddr, int which, 316158b68d33c5fad024f2b235555be0234e97721920Johan Hedberg int timeout, uint32_t *clock, 316258b68d33c5fad024f2b235555be0234e97721920Johan Hedberg uint16_t *accuracy) 31635bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter{ 3164fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 31656b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg uint16_t handle = 0; 31666b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg char addr[18]; 31676b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg int ret; 3168fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 31696b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg ba2str(bdaddr, addr); 31706b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg DBG("hci%d addr %s which %d timeout %d", index, addr, which, timeout); 31716b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg 31726b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg ret = get_handle(index, bdaddr, &handle); 31736b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg if (ret < 0) 31746b9921107e0346f0fc6f5475b0dea17f65dc94ceJohan Hedberg return ret; 31750e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 317658b68d33c5fad024f2b235555be0234e97721920Johan Hedberg if (hci_read_clock(dev->sk, htobs(handle), which, clock, accuracy, 31776844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg timeout) < 0) 31786844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 31795bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 31806844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 31815bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter} 31825bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter 3183b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedbergstatic int hciops_read_bdaddr(int index, bdaddr_t *bdaddr) 3184b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg{ 3185fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3186fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 31870e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 3188fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3189fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg bacpy(bdaddr, &dev->bdaddr); 3190fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 31916844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3192b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg} 3193b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg 3194885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedbergstatic int hciops_block_device(int index, bdaddr_t *bdaddr) 3195885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg{ 3196fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 31970e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 31980e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 31990e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 32000e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 32010e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3202fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (ioctl(dev->sk, HCIBLOCKADDR, bdaddr) < 0) 3203885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg return -errno; 3204885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 32056844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3206885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg} 3207885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 3208885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedbergstatic int hciops_unblock_device(int index, bdaddr_t *bdaddr) 3209885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg{ 3210fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 32110e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 32120e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 32130e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 32140e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 32150e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3216fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (ioctl(dev->sk, HCIUNBLOCKADDR, bdaddr) < 0) 3217885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg return -errno; 3218885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 32196844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 3220885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg} 3221885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg 3222f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedbergstatic int hciops_get_conn_list(int index, GSList **conns) 3223f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg{ 3224fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3225cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg GSList *l; 3226f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 32270e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 32280e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3229f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg *conns = NULL; 3230f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 3231cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg for (l = dev->connections; l != NULL; l = g_slist_next(l)) { 3232b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn = l->data; 3233cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg 323476522723bdf7cb46a692f88a6ad616045bfa46e8Johan Hedberg *conns = g_slist_append(*conns, 3235cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg g_memdup(&conn->bdaddr, sizeof(bdaddr_t))); 3236cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg } 3237f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 3238cc0e50e3ab1a612ffb72b9021229f660d54f9388Johan Hedberg return 0; 3239f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg} 3240f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg 324148e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedbergstatic int hciops_read_local_features(int index, uint8_t *features) 324248e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg{ 3243fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3244fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 32450e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d", index); 3246fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3247fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg memcpy(features, dev->features, 8); 3248fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 32496844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 325048e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg} 325148e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg 3252bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedbergstatic int hciops_disconnect(int index, bdaddr_t *bdaddr) 325306dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg{ 3254bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg DBG("hci%d", index); 325506dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 3256bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg return disconnect_addr(index, bdaddr, HCI_OE_USER_ENDED_CONNECTION); 325706dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg} 325806dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg 32591bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedbergstatic int hciops_remove_bonding(int index, bdaddr_t *bdaddr) 32601bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg{ 3261fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 326273c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg delete_stored_link_key_cp cp; 3263b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg GSList *match; 32640e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 32650e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 32660e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 32670e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 32681bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 3269b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg match = g_slist_find_custom(dev->keys, bdaddr, (GCompareFunc) bacmp); 3270b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (match) { 3271b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg g_free(match->data); 3272b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg dev->keys = g_slist_delete_link(dev->keys, match); 3273b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg } 3274b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 327573c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg memset(&cp, 0, sizeof(cp)); 327673c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg bacpy(&cp.bdaddr, bdaddr); 327773c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg 32781bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg /* Delete the link key from the Bluetooth chip */ 3279fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_DELETE_STORED_LINK_KEY, 328073c8e7ac377f0f6ea0df6396b96cb9e8a11eb070Johan Hedberg DELETE_STORED_LINK_KEY_CP_SIZE, &cp) < 0) 32816844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 32821bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 32836844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 32841bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg} 32851bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg 32862d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmannstatic int hciops_pincode_reply(int index, bdaddr_t *bdaddr, const char *pin, 32872d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann size_t pin_len) 3288e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg{ 3289fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 32900e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 32916844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 3292e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 32930e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 32940e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 32950e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3296e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg if (pin) { 3297e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg pin_code_reply_cp pr; 3298e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 32992d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann dev->pin_length = pin_len; 330042bb162ca16e92eac264127a88063cadf7d48af7Johan Hedberg 3301e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg memset(&pr, 0, sizeof(pr)); 3302e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg bacpy(&pr.bdaddr, bdaddr); 33032d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann memcpy(pr.pin_code, pin, pin_len); 33042d59b9b4a353fe2c57db084895e8958dddade63dDavid Herrmann pr.pin_len = pin_len; 3305fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 33066844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_PIN_CODE_REPLY, 3307e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg PIN_CODE_REPLY_CP_SIZE, &pr); 3308e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg } else 3309fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 3310e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg OCF_PIN_CODE_NEG_REPLY, 6, bdaddr); 3311e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 33126844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (err < 0) 33136844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 3314e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 3315e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg return err; 3316e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg} 3317e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg 3318889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedbergstatic int hciops_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey) 3319889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg{ 3320fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 33210e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg char addr[18]; 33226844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg int err; 3323889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 33240e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg ba2str(bdaddr, addr); 33250e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG("hci%d dba %s", index, addr); 33260e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 3327889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg if (passkey != INVALID_PASSKEY) { 3328889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg user_passkey_reply_cp cp; 3329889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 3330889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg memset(&cp, 0, sizeof(cp)); 3331889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg bacpy(&cp.bdaddr, bdaddr); 3332889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg cp.passkey = passkey; 3333889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 3334fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 33356844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_USER_PASSKEY_REPLY, 3336889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg USER_PASSKEY_REPLY_CP_SIZE, &cp); 3337889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg } else 3338fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = hci_send_cmd(dev->sk, OGF_LINK_CTL, 3339889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg OCF_USER_PASSKEY_NEG_REPLY, 6, bdaddr); 3340889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 33416844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg if (err < 0) 33426844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg err = -errno; 3343889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 3344889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg return err; 3345889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg} 3346889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg 33475c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergstatic int hciops_enable_le(int index) 33487ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi{ 3349fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 33507ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi write_le_host_supported_cp cp; 33517ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 33525c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d", index); 33535c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 3354fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!(dev->features[4] & LMP_LE)) 33555c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return -ENOTSUP; 33560e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg 33575c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg cp.le = 0x01; 3358fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg cp.simul = (dev->features[6] & LMP_LE_BREDR) ? 0x01 : 0x00; 33597ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 3360fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (hci_send_cmd(dev->sk, OGF_HOST_CTL, 33616844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg OCF_WRITE_LE_HOST_SUPPORTED, 33626844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg WRITE_LE_HOST_SUPPORTED_CP_SIZE, &cp) < 0) 33636844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return -errno; 33647ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 33656844ac4ce59e05b8857f18fa620adf42479d6aa5Johan Hedberg return 0; 33667ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi} 33677ff8fd32ebaec606c8ee9d063a277eeba7352f5fClaudio Takahasi 33683e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedbergstatic uint8_t generate_service_class(int index) 336900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 3370fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 33713e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg GSList *l; 33723e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg uint8_t val = 0; 33733e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33743e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg for (l = dev->uuids; l != NULL; l = g_slist_next(l)) { 3375006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg struct uuid_info *uuid = l->data; 33763e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 3377006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg val |= uuid->svc_hint; 33783e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg } 33793e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33803e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg return val; 33813e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg} 33823e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33833e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedbergstatic int update_service_classes(int index) 33843e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg{ 33853e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg struct dev_info *dev = &devs[index]; 33863e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg uint8_t value; 338700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg int err; 338800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 33893e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg value = generate_service_class(index); 33903e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 33915c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg DBG("hci%d value %u", index, value); 33925c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 339300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Update only the service class, keep the limited bit, 339400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * major/minor class bits intact */ 3395fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod &= 0x00ffff; 3396fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->wanted_cod |= (value << 16); 339700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 339800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* If the cache is enabled or an existing CoD write is in progress 339900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * just bail out */ 3400fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->cache_enable || dev->pending_cod) 340100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 340200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 340300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* If we already have the CoD we want, update EIR and return */ 3404fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->current_cod == dev->wanted_cod) { 340500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 340600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 340700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg } 340800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3409fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg DBG("Changing service classes to 0x%06x", dev->wanted_cod); 341000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3411fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg err = write_class(index, dev->wanted_cod); 341200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg if (err < 0) 341300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg error("Adapter class update failed: %s (%d)", 341400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg strerror(-err), -err); 341500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 341600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return err; 341700c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 341800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3419006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedbergstatic int hciops_add_uuid(int index, uuid_t *uuid, uint8_t svc_hint) 342000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 34213e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg struct dev_info *dev = &devs[index]; 3422006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg struct uuid_info *info; 342300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 342400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d", index); 342500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3426006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg info = g_new0(struct uuid_info, 1); 3427006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg memcpy(&info->uuid, uuid, sizeof(*uuid)); 3428006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg info->svc_hint = svc_hint; 3429006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg 3430006301ab40fc71da92f593ddfb2dba70202bd061Johan Hedberg dev->uuids = g_slist_append(dev->uuids, info); 343100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34323e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg return update_service_classes(index); 34333e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg} 343400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34353e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedbergstatic int hciops_remove_uuid(int index, uuid_t *uuid) 34363e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg{ 34373e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg struct dev_info *dev = &devs[index]; 34383e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg GSList *match; 343900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34403e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg match = g_slist_find_custom(dev->uuids, uuid, sdp_uuid_cmp); 34413e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg if (match) { 34423e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg g_free(match->data); 34433e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg dev->uuids = g_slist_delete_link(dev->uuids, match); 344400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg } 344500c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34463e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg DBG("hci%d", index); 34473e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg 34483e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg return update_service_classes(index); 344900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 345000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 345100c2267405ff3416672401cf394f06017a6814c1Johan Hedbergstatic int hciops_disable_cod_cache(int index) 345200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg{ 3453fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 345400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3455fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg DBG("hci%d cache_enable %d", index, dev->cache_enable); 3456fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3457fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->cache_enable) 345800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 345900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 346000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg DBG("hci%d current_cod 0x%06x wanted_cod 0x%06x", index, 3461fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->current_cod, dev->wanted_cod); 346200c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 346300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg /* Disable and flush svc cache. All successive service class 346400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg * updates * will be written to the device */ 3465fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg dev->cache_enable = FALSE; 346600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3467fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (dev->current_cod == dev->wanted_cod) { 346800c2267405ff3416672401cf394f06017a6814c1Johan Hedberg update_ext_inquiry_response(index); 346900c2267405ff3416672401cf394f06017a6814c1Johan Hedberg return 0; 347000c2267405ff3416672401cf394f06017a6814c1Johan Hedberg } 347100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 3472fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg return write_class(index, dev->wanted_cod); 347300c2267405ff3416672401cf394f06017a6814c1Johan Hedberg} 347400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg 34755c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedbergstatic int hciops_restore_powered(int index) 34765c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg{ 3477fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg struct dev_info *dev = &devs[index]; 3478fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg 3479fdb266b6797638b89b9ba9fe0d89670bf71d47c5Johan Hedberg if (!dev->already_up && dev->up) 348063ff6738abc6bf21becbbfde583062502e7728a6Johan Hedberg return hciops_power_off(index); 34815c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 34825c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg return 0; 34835c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg} 34845c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg 3485dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedbergstatic int hciops_load_keys(int index, GSList *keys, gboolean debug_keys) 3486b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg{ 3487b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg struct dev_info *dev = &devs[index]; 3488b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3489dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg DBG("hci%d keys %d debug_keys %d", index, g_slist_length(keys), 3490dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg debug_keys); 3491b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3492b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg if (dev->keys != NULL) 3493b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg return -EEXIST; 3494b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3495b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg dev->keys = keys; 3496dccef4954d8dcaa4559be66263ea0945cd9be528Johan Hedberg dev->debug_keys = debug_keys; 3497b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 3498b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg return 0; 3499b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg} 3500b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg 35019634f5c410e761219037129f71c591459a854391Johan Hedbergstatic int hciops_set_io_capability(int index, uint8_t io_capability) 35029634f5c410e761219037129f71c591459a854391Johan Hedberg{ 3503b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 3504b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3505b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg dev->io_capability = io_capability; 3506b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3507b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 3508b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 3509b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3510596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedbergstatic int request_authentication(int index, bdaddr_t *bdaddr) 3511596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg{ 3512596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg struct dev_info *dev = &devs[index]; 3513596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg auth_requested_cp cp; 3514596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg uint16_t handle; 3515596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg int err; 3516596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3517596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg DBG("hci%d", index); 3518596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3519596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg err = get_handle(index, bdaddr, &handle); 3520596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg if (err < 0) 3521596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg return err; 3522596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3523596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg memset(&cp, 0, sizeof(cp)); 3524596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg cp.handle = htobs(handle); 3525596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3526596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_AUTH_REQUESTED, 3527596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg AUTH_REQUESTED_CP_SIZE, &cp) < 0) 3528596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg return -errno; 3529596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3530596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg return 0; 3531596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg} 3532596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg 3533b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic void bonding_connect_cb(GIOChannel *io, GError *err, gpointer user_data) 3534b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 3535b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn = user_data; 3536b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = conn->dev; 3537b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3538b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!conn->io) { 3539b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (!err) 3540b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_shutdown(io, TRUE, NULL); 3541b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 3542b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 3543b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3544b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (err) 3545b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* Wait proper error to be propagated by bonding complete */ 3546b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 3547b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3548596e8ddd21ff0074f79acc9b0577a7050ade5bf6Johan Hedberg if (request_authentication(dev->id, &conn->bdaddr) < 0) 3549b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg goto failed; 3550b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3551b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return; 3552b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3553b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergfailed: 3554b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg bonding_complete(dev, conn, HCI_UNSPECIFIED_ERROR); 3555b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 3556b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3557b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int hciops_create_bonding(int index, bdaddr_t *bdaddr, uint8_t io_cap) 3558b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 3559b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 3560b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BtIOSecLevel sec_level; 3561b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 3562b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg GError *err = NULL; 3563b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3564b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = get_connection(dev, bdaddr); 3565b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3566b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io != NULL) 3567b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -EBUSY; 3568b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3569b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->loc_cap = io_cap; 3570b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3571b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg /* If our IO capability is NoInputNoOutput use medium security 3572b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * level (i.e. don't require MITM protection) else use high 3573b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg * security level */ 3574b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (io_cap == 0x03) 3575b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg sec_level = BT_IO_SEC_MEDIUM; 3576b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg else 3577b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg sec_level = BT_IO_SEC_HIGH; 3578b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3579b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->io = bt_io_connect(BT_IO_L2RAW, bonding_connect_cb, conn, 3580b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg NULL, &err, 3581b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_SOURCE_BDADDR, &dev->bdaddr, 3582b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_DEST_BDADDR, bdaddr, 3583b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_SEC_LEVEL, sec_level, 3584b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg BT_IO_OPT_INVALID); 3585b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn->io == NULL) { 3586b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg error("bt_io_connect: %s", err->message); 3587b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_error_free(err); 3588b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -EIO; 3589b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg } 3590b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3591b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->bonding_initiator = TRUE; 3592b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3593b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return 0; 3594b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg} 3595b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3596b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedbergstatic int hciops_cancel_bonding(int index, bdaddr_t *bdaddr) 3597b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg{ 3598b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct dev_info *dev = &devs[index]; 3599b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg struct bt_conn *conn; 3600b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3601629c9dbe7f161c0c285749bb014f55a2b30fd65cJohan Hedberg DBG("hci%d", index); 3602629c9dbe7f161c0c285749bb014f55a2b30fd65cJohan Hedberg 3603b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn = find_connection(dev, bdaddr); 3604b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg if (conn == NULL || conn->io == NULL) 3605b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg return -ENOTCONN; 3606b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 3607b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_shutdown(conn->io, TRUE, NULL); 3608b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg g_io_channel_unref(conn->io); 3609b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg conn->io = NULL; 3610b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg 36119634f5c410e761219037129f71c591459a854391Johan Hedberg return 0; 36129634f5c410e761219037129f71c591459a854391Johan Hedberg} 36139634f5c410e761219037129f71c591459a854391Johan Hedberg 361475397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Jancstatic int hciops_read_local_oob_data(int index) 361575397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc{ 361623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct dev_info *dev = &devs[index]; 361723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 361875397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc DBG("hci%d", index); 361975397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 362023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA, 0, 0) 362123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc < 0) 362223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return -errno; 362323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 362423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return 0; 362575397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc} 362675397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 362775397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Jancstatic int hciops_add_remote_oob_data(int index, bdaddr_t *bdaddr, 362875397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc uint8_t *hash, uint8_t *randomizer) 362975397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc{ 363075397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc char addr[18]; 363123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct dev_info *dev = &devs[index]; 363223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 363323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct oob_data *data; 363475397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 363575397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc ba2str(bdaddr, addr); 363675397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc DBG("hci%d bdaddr %s", index, addr); 363775397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 363823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, &bdaddr, oob_bdaddr_cmp); 363923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 364023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (match) { 364123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc data = match->data; 364223586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } else { 364323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc data = g_new(struct oob_data, 1); 364423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc bacpy(&data->bdaddr, bdaddr); 364523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc dev->oob_data = g_slist_prepend(dev->oob_data, data); 364623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc } 364723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 364823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(data->hash, hash, sizeof(data->hash)); 364923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); 365023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 365123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return 0; 365275397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc} 365375397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 365475397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Jancstatic int hciops_remove_remote_oob_data(int index, bdaddr_t *bdaddr) 365575397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc{ 365675397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc char addr[18]; 365723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc struct dev_info *dev = &devs[index]; 365823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc GSList *match; 365975397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 366075397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc ba2str(bdaddr, addr); 366175397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc DBG("hci%d bdaddr %s", index, addr); 366275397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 366323586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc match = g_slist_find_custom(dev->oob_data, &bdaddr, oob_bdaddr_cmp); 366423586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 366523586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc if (!match) 366623586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return -ENOENT; 366723586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 366823586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc g_free(match->data); 366923586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc dev->oob_data = g_slist_delete_link(dev->oob_data, match); 367023586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc 367123586efc94e7b04f002c103b2f6bd8068fff6ca9Szymon Janc return 0; 367275397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc} 367375397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc 3674a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganeshstatic int hciops_set_link_timeout(int index, bdaddr_t *bdaddr, uint32_t num_slots) 3675a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh{ 3676a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh int dd, err; 3677a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh uint16_t handle; 3678a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh char addr[18]; 3679a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3680a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh ba2str(bdaddr, addr); 3681a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh DBG("hci%d, addr %s, num_slots %d", index, bdaddr, num_slots); 3682a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3683a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh dd = hci_open_dev(index); 3684a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3685a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh if (dd < 0) 3686a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh return EIO; 3687a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3688a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh handle = get_handle(index, bdaddr, &handle); 3689a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh err = hci_write_link_supervision_timeout(dd, htobs(handle), 3690a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh htobs(num_slots), 1000); 3691a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh if (err < 0) 3692a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh err = -errno; 3693a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3694a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh hci_close_dev(dd); 3695a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3696a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh return err; 3697a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh} 3698a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 3699f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganeshstatic int hciops_retry_authentication(int index, bdaddr_t *bdaddr) 3700f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh{ 3701f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh return request_authentication(index, bdaddr); 3702f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh} 3703a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh 370434c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic struct btd_adapter_ops hci_ops = { 370534c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .setup = hciops_setup, 370634c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode .cleanup = hciops_cleanup, 370727c58425af807521e618f29b08e7a99496aeda3bJohan Hedberg .set_powered = hciops_set_powered, 37085c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .set_discoverable = hciops_set_discoverable, 37095c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .set_pairable = hciops_set_pairable, 3710eeba5fdb9c807191893b9e82cb4952e23df3ca56Alok Barsode .set_limited_discoverable = hciops_set_limited_discoverable, 37114cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes .start_discovery = hciops_start_discovery, 37124cb11a06dcebf4a3d91049a65d6c7a174eea922aAndre Guedes .stop_discovery = hciops_stop_discovery, 3713ef876daebf32cbe65fb4d9ec6fb1ffead60086eaAlok Barsode .resolve_name = hciops_resolve_name, 3714b96f44db8e91325968a0149595b2522d4a22481aAlok Barsode .cancel_resolve_name = hciops_cancel_resolve_name, 3715164ccf9a6641fe646d8476f6b860d5ff4905632bAlok Barsode .set_name = hciops_set_name, 371600c2267405ff3416672401cf394f06017a6814c1Johan Hedberg .set_dev_class = hciops_set_dev_class, 371761f0df8f18c417df50a296e10893c82b5eb83879Dmitriy Paliy .set_fast_connectable = hciops_fast_connectable, 37185bca34b67c59a01d72adcf6601ce2c8553464142Elvis Pfützenreuter .read_clock = hciops_read_clock, 3719b5c556ef59a9a8318b239453c3d4a8aad951689fJohan Hedberg .read_bdaddr = hciops_read_bdaddr, 3720885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg .block_device = hciops_block_device, 3721885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg .unblock_device = hciops_unblock_device, 3722f7b4b3fcd1190d231b864730c821b98fb945e439Johan Hedberg .get_conn_list = hciops_get_conn_list, 372348e6007a98222853a0e1bcbbd6ac17a37098bb49Johan Hedberg .read_local_features = hciops_read_local_features, 372406dcf6ada5042f6f8a52ae64cfca8327399c09b1Johan Hedberg .disconnect = hciops_disconnect, 37251bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg .remove_bonding = hciops_remove_bonding, 3726e7daece858070d71cecf6ade4f0e3c93272c53acJohan Hedberg .pincode_reply = hciops_pincode_reply, 3727df6c074158bc0f2caf76178dc00d50c7bf1b444aJohan Hedberg .confirm_reply = hciops_confirm_reply, 3728889c7513b312854e7f5c274696ad92a233c1ce78Johan Hedberg .passkey_reply = hciops_passkey_reply, 37295c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .enable_le = hciops_enable_le, 3730abe7cd44124a6955c1a3fd5c828ec2934f38a528Johan Hedberg .encrypt_link = hciops_encrypt_link, 373100c2267405ff3416672401cf394f06017a6814c1Johan Hedberg .set_did = hciops_set_did, 37323e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg .add_uuid = hciops_add_uuid, 37333e1b64c81d0ef4ae92b601114aa06d85c735d646Johan Hedberg .remove_uuid = hciops_remove_uuid, 373400c2267405ff3416672401cf394f06017a6814c1Johan Hedberg .disable_cod_cache = hciops_disable_cod_cache, 37355c1c35eb38790bd068bfd37e0355aafb194f7812Johan Hedberg .restore_powered = hciops_restore_powered, 3736b95ef500f79d9c2fb81be4866037bc1c7780e6f6Johan Hedberg .load_keys = hciops_load_keys, 37379634f5c410e761219037129f71c591459a854391Johan Hedberg .set_io_capability = hciops_set_io_capability, 3738b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg .create_bonding = hciops_create_bonding, 3739b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg .cancel_bonding = hciops_cancel_bonding, 374075397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc .read_local_oob_data = hciops_read_local_oob_data, 374175397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc .add_remote_oob_data = hciops_add_remote_oob_data, 374275397433e8024fb07d5801778cc572ac1d5ea5bfSzymon Janc .remove_remote_oob_data = hciops_remove_remote_oob_data, 3743a04c1f0249e1899e4b3d237931f9b5d97f30cebeJaikumar Ganesh .set_link_timeout = hciops_set_link_timeout, 3744f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh .retry_authentication = hciops_retry_authentication, 374534c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode}; 374634c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode 374734c4239984722c169e3e821ec5ca7c88528827bdAlok Barsodestatic int hciops_init(void) 374834c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode{ 37490e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 3750d30044157466e7f34e7f2d5d7ce70215ea013338Johan Hedberg return btd_register_adapter_ops(&hci_ops, FALSE); 375134c4239984722c169e3e821ec5ca7c88528827bdAlok Barsode} 3752d57934d1d09c34d1b136c572cad1dff6306c8c48Johan Hedberg 375394e91856179a268805256055ffd5155d1468b99cAlok Barsodestatic void hciops_exit(void) 375494e91856179a268805256055ffd5155d1468b99cAlok Barsode{ 37550e9aac1c77cac6e125ea0dbf68769e12e0928964Johan Hedberg DBG(""); 3756929393b82db06368ff5fa4074bc209d1d4d03a48Marcel Holtmann btd_adapter_cleanup_ops(&hci_ops); 375794e91856179a268805256055ffd5155d1468b99cAlok Barsode} 375894e91856179a268805256055ffd5155d1468b99cAlok Barsode 375994e91856179a268805256055ffd5155d1468b99cAlok BarsodeBLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, 37601ab388feb37980f1afc940c7cf530b9baadeabb1Marcel Holtmann BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit) 3761