blob: c7e5d46510215207e6f1bef5024d25d54c07352b [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020094};
95
96static const u16 mgmt_events[] = {
97 MGMT_EV_CONTROLLER_ERROR,
98 MGMT_EV_INDEX_ADDED,
99 MGMT_EV_INDEX_REMOVED,
100 MGMT_EV_NEW_SETTINGS,
101 MGMT_EV_CLASS_OF_DEV_CHANGED,
102 MGMT_EV_LOCAL_NAME_CHANGED,
103 MGMT_EV_NEW_LINK_KEY,
104 MGMT_EV_NEW_LONG_TERM_KEY,
105 MGMT_EV_DEVICE_CONNECTED,
106 MGMT_EV_DEVICE_DISCONNECTED,
107 MGMT_EV_CONNECT_FAILED,
108 MGMT_EV_PIN_CODE_REQUEST,
109 MGMT_EV_USER_CONFIRM_REQUEST,
110 MGMT_EV_USER_PASSKEY_REQUEST,
111 MGMT_EV_AUTH_FAILED,
112 MGMT_EV_DEVICE_FOUND,
113 MGMT_EV_DISCOVERING,
114 MGMT_EV_DEVICE_BLOCKED,
115 MGMT_EV_DEVICE_UNBLOCKED,
116 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300117 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800118 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700119 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200120 MGMT_EV_DEVICE_ADDED,
121 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300122 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200123 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200124 MGMT_EV_UNCONF_INDEX_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200125};
126
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800127#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200128
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200129#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
130 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
131
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200132struct pending_cmd {
133 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200134 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100136 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300138 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139};
140
Johan Hedbergca69b792011-11-11 18:10:00 +0200141/* HCI to MGMT error code conversion table */
142static u8 mgmt_status_table[] = {
143 MGMT_STATUS_SUCCESS,
144 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
145 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
146 MGMT_STATUS_FAILED, /* Hardware Failure */
147 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
148 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200149 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200150 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
151 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
152 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
153 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
154 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
155 MGMT_STATUS_BUSY, /* Command Disallowed */
156 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
157 MGMT_STATUS_REJECTED, /* Rejected Security */
158 MGMT_STATUS_REJECTED, /* Rejected Personal */
159 MGMT_STATUS_TIMEOUT, /* Host Timeout */
160 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
161 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
162 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
163 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
164 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
165 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
166 MGMT_STATUS_BUSY, /* Repeated Attempts */
167 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
168 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
169 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
170 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
171 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
172 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
173 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
174 MGMT_STATUS_FAILED, /* Unspecified Error */
175 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
176 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
177 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
178 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
179 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
180 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
181 MGMT_STATUS_FAILED, /* Unit Link Key Used */
182 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
183 MGMT_STATUS_TIMEOUT, /* Instant Passed */
184 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
185 MGMT_STATUS_FAILED, /* Transaction Collision */
186 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
187 MGMT_STATUS_REJECTED, /* QoS Rejected */
188 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
189 MGMT_STATUS_REJECTED, /* Insufficient Security */
190 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
191 MGMT_STATUS_BUSY, /* Role Switch Pending */
192 MGMT_STATUS_FAILED, /* Slot Violation */
193 MGMT_STATUS_FAILED, /* Role Switch Failed */
194 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
195 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
196 MGMT_STATUS_BUSY, /* Host Busy Pairing */
197 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
198 MGMT_STATUS_BUSY, /* Controller Busy */
199 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
200 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
201 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
202 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
203 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
204};
205
206static u8 mgmt_status(u8 hci_status)
207{
208 if (hci_status < ARRAY_SIZE(mgmt_status_table))
209 return mgmt_status_table[hci_status];
210
211 return MGMT_STATUS_FAILED;
212}
213
Szymon Janc4e51eae2011-02-25 19:05:48 +0100214static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200215{
216 struct sk_buff *skb;
217 struct mgmt_hdr *hdr;
218 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300219 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200220
Szymon Janc34eb5252011-02-28 14:10:08 +0100221 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200222
Andre Guedes790eff42012-06-07 19:05:46 -0300223 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700229 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100230 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200231 hdr->len = cpu_to_le16(sizeof(*ev));
232
233 ev = (void *) skb_put(skb, sizeof(*ev));
234 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200235 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200236
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300237 err = sock_queue_rcv_skb(sk, skb);
238 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200239 kfree_skb(skb);
240
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300241 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200242}
243
Johan Hedbergaee9b212012-02-18 15:07:59 +0200244static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300245 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200246{
247 struct sk_buff *skb;
248 struct mgmt_hdr *hdr;
249 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300250 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200251
252 BT_DBG("sock %p", sk);
253
Andre Guedes790eff42012-06-07 19:05:46 -0300254 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200255 if (!skb)
256 return -ENOMEM;
257
258 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200259
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700260 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100261 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200262 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200263
Johan Hedberga38528f2011-01-22 06:46:43 +0200264 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200265 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200266 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100267
268 if (rp)
269 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200270
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300271 err = sock_queue_rcv_skb(sk, skb);
272 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200273 kfree_skb(skb);
274
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100275 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200276}
277
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
279 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200280{
281 struct mgmt_rp_read_version rp;
282
283 BT_DBG("sock %p", sk);
284
285 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700286 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200287
Johan Hedbergaee9b212012-02-18 15:07:59 +0200288 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300289 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200290}
291
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300292static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
293 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200294{
295 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200296 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
297 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200298 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200299 size_t rp_size;
300 int i, err;
301
302 BT_DBG("sock %p", sk);
303
304 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
305
306 rp = kmalloc(rp_size, GFP_KERNEL);
307 if (!rp)
308 return -ENOMEM;
309
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700310 rp->num_commands = cpu_to_le16(num_commands);
311 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200312
313 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
314 put_unaligned_le16(mgmt_commands[i], opcode);
315
316 for (i = 0; i < num_events; i++, opcode++)
317 put_unaligned_le16(mgmt_events[i], opcode);
318
Johan Hedbergaee9b212012-02-18 15:07:59 +0200319 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300320 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200321 kfree(rp);
322
323 return err;
324}
325
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300326static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
327 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200328{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200329 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200330 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200331 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200332 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300333 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200334
335 BT_DBG("sock %p", sk);
336
337 read_lock(&hci_dev_list_lock);
338
339 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300340 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200341 if (d->dev_type == HCI_BREDR &&
342 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700343 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200344 }
345
Johan Hedberga38528f2011-01-22 06:46:43 +0200346 rp_len = sizeof(*rp) + (2 * count);
347 rp = kmalloc(rp_len, GFP_ATOMIC);
348 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100349 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200350 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100351 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200352
Johan Hedberg476e44c2012-10-19 20:10:46 +0300353 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200354 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200355 if (test_bit(HCI_SETUP, &d->dev_flags) ||
356 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200357 continue;
358
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200359 /* Devices marked as raw-only are neither configured
360 * nor unconfigured controllers.
361 */
362 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700363 continue;
364
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200365 if (d->dev_type == HCI_BREDR &&
366 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700367 rp->index[count++] = cpu_to_le16(d->id);
368 BT_DBG("Added hci%u", d->id);
369 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370 }
371
Johan Hedberg476e44c2012-10-19 20:10:46 +0300372 rp->num_controllers = cpu_to_le16(count);
373 rp_len = sizeof(*rp) + (2 * count);
374
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375 read_unlock(&hci_dev_list_lock);
376
Johan Hedbergaee9b212012-02-18 15:07:59 +0200377 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300378 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200379
Johan Hedberga38528f2011-01-22 06:46:43 +0200380 kfree(rp);
381
382 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383}
384
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200385static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
386 void *data, u16 data_len)
387{
388 struct mgmt_rp_read_unconf_index_list *rp;
389 struct hci_dev *d;
390 size_t rp_len;
391 u16 count;
392 int err;
393
394 BT_DBG("sock %p", sk);
395
396 read_lock(&hci_dev_list_lock);
397
398 count = 0;
399 list_for_each_entry(d, &hci_dev_list, list) {
400 if (d->dev_type == HCI_BREDR &&
401 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
402 count++;
403 }
404
405 rp_len = sizeof(*rp) + (2 * count);
406 rp = kmalloc(rp_len, GFP_ATOMIC);
407 if (!rp) {
408 read_unlock(&hci_dev_list_lock);
409 return -ENOMEM;
410 }
411
412 count = 0;
413 list_for_each_entry(d, &hci_dev_list, list) {
414 if (test_bit(HCI_SETUP, &d->dev_flags) ||
415 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
416 continue;
417
418 /* Devices marked as raw-only are neither configured
419 * nor unconfigured controllers.
420 */
421 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
422 continue;
423
424 if (d->dev_type == HCI_BREDR &&
425 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
426 rp->index[count++] = cpu_to_le16(d->id);
427 BT_DBG("Added hci%u", d->id);
428 }
429 }
430
431 rp->num_controllers = cpu_to_le16(count);
432 rp_len = sizeof(*rp) + (2 * count);
433
434 read_unlock(&hci_dev_list_lock);
435
436 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
437 0, rp, rp_len);
438
439 kfree(rp);
440
441 return err;
442}
443
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200444static __le32 get_missing_options(struct hci_dev *hdev)
445{
446 u32 options = 0;
447
448 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
449 !bacmp(&hdev->public_addr, BDADDR_ANY))
450 options |= MGMT_OPTION_PUBLIC_ADDRESS;
451
452 return cpu_to_le32(options);
453}
454
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200455static int read_config_info(struct sock *sk, struct hci_dev *hdev,
456 void *data, u16 data_len)
457{
458 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200459 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200460
461 BT_DBG("sock %p %s", sk, hdev->name);
462
463 hci_dev_lock(hdev);
464
465 memset(&rp, 0, sizeof(rp));
466 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200467
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200468 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200469 options |= MGMT_OPTION_PUBLIC_ADDRESS;
470
471 rp.supported_options = cpu_to_le32(options);
472 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200473
474 hci_dev_unlock(hdev);
475
476 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
477 sizeof(rp));
478}
479
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200480static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200481{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200482 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200483
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200484 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200485 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800486 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200487
Andre Guedesed3fa312012-07-24 15:03:46 -0300488 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300489 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500490 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
491 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300492 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200493 settings |= MGMT_SETTING_BREDR;
494 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700495
496 if (lmp_ssp_capable(hdev)) {
497 settings |= MGMT_SETTING_SSP;
498 settings |= MGMT_SETTING_HS;
499 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800500
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800501 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200502 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800503 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700504 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100505
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300506 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200507 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300508 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200509 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300510 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200511
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200512 if (hdev->set_bdaddr)
513 settings |= MGMT_SETTING_CONFIGURATION;
514
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200515 return settings;
516}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200517
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200518static u32 get_current_settings(struct hci_dev *hdev)
519{
520 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200521
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200522 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100523 settings |= MGMT_SETTING_POWERED;
524
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200525 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200526 settings |= MGMT_SETTING_CONNECTABLE;
527
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500528 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
529 settings |= MGMT_SETTING_FAST_CONNECTABLE;
530
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200531 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200532 settings |= MGMT_SETTING_DISCOVERABLE;
533
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200534 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200535 settings |= MGMT_SETTING_PAIRABLE;
536
Johan Hedberg56f87902013-10-02 13:43:13 +0300537 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200538 settings |= MGMT_SETTING_BREDR;
539
Johan Hedberg06199cf2012-02-22 16:37:11 +0200540 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200541 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200542
Johan Hedberg47990ea2012-02-22 11:58:37 +0200543 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200544 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200545
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200546 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200547 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200548
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200549 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
550 settings |= MGMT_SETTING_HS;
551
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200552 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300553 settings |= MGMT_SETTING_ADVERTISING;
554
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800555 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
556 settings |= MGMT_SETTING_SECURE_CONN;
557
Johan Hedberg0663b292014-06-24 13:15:50 +0300558 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800559 settings |= MGMT_SETTING_DEBUG_KEYS;
560
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200561 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
562 settings |= MGMT_SETTING_PRIVACY;
563
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200565}
566
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300567#define PNP_INFO_SVCLASS_ID 0x1200
568
Johan Hedberg213202e2013-01-27 00:31:33 +0200569static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
570{
571 u8 *ptr = data, *uuids_start = NULL;
572 struct bt_uuid *uuid;
573
574 if (len < 4)
575 return ptr;
576
577 list_for_each_entry(uuid, &hdev->uuids, list) {
578 u16 uuid16;
579
580 if (uuid->size != 16)
581 continue;
582
583 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
584 if (uuid16 < 0x1100)
585 continue;
586
587 if (uuid16 == PNP_INFO_SVCLASS_ID)
588 continue;
589
590 if (!uuids_start) {
591 uuids_start = ptr;
592 uuids_start[0] = 1;
593 uuids_start[1] = EIR_UUID16_ALL;
594 ptr += 2;
595 }
596
597 /* Stop if not enough space to put next UUID */
598 if ((ptr - data) + sizeof(u16) > len) {
599 uuids_start[1] = EIR_UUID16_SOME;
600 break;
601 }
602
603 *ptr++ = (uuid16 & 0x00ff);
604 *ptr++ = (uuid16 & 0xff00) >> 8;
605 uuids_start[0] += sizeof(uuid16);
606 }
607
608 return ptr;
609}
610
Johan Hedbergcdf19632013-01-27 00:31:34 +0200611static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
612{
613 u8 *ptr = data, *uuids_start = NULL;
614 struct bt_uuid *uuid;
615
616 if (len < 6)
617 return ptr;
618
619 list_for_each_entry(uuid, &hdev->uuids, list) {
620 if (uuid->size != 32)
621 continue;
622
623 if (!uuids_start) {
624 uuids_start = ptr;
625 uuids_start[0] = 1;
626 uuids_start[1] = EIR_UUID32_ALL;
627 ptr += 2;
628 }
629
630 /* Stop if not enough space to put next UUID */
631 if ((ptr - data) + sizeof(u32) > len) {
632 uuids_start[1] = EIR_UUID32_SOME;
633 break;
634 }
635
636 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
637 ptr += sizeof(u32);
638 uuids_start[0] += sizeof(u32);
639 }
640
641 return ptr;
642}
643
Johan Hedbergc00d5752013-01-27 00:31:35 +0200644static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
645{
646 u8 *ptr = data, *uuids_start = NULL;
647 struct bt_uuid *uuid;
648
649 if (len < 18)
650 return ptr;
651
652 list_for_each_entry(uuid, &hdev->uuids, list) {
653 if (uuid->size != 128)
654 continue;
655
656 if (!uuids_start) {
657 uuids_start = ptr;
658 uuids_start[0] = 1;
659 uuids_start[1] = EIR_UUID128_ALL;
660 ptr += 2;
661 }
662
663 /* Stop if not enough space to put next UUID */
664 if ((ptr - data) + 16 > len) {
665 uuids_start[1] = EIR_UUID128_SOME;
666 break;
667 }
668
669 memcpy(ptr, uuid->uuid, 16);
670 ptr += 16;
671 uuids_start[0] += 16;
672 }
673
674 return ptr;
675}
676
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300677static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
678{
679 struct pending_cmd *cmd;
680
681 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
682 if (cmd->opcode == opcode)
683 return cmd;
684 }
685
686 return NULL;
687}
688
Johan Hedberg95868422014-06-28 17:54:07 +0300689static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
690 struct hci_dev *hdev,
691 const void *data)
692{
693 struct pending_cmd *cmd;
694
695 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
696 if (cmd->user_data != data)
697 continue;
698 if (cmd->opcode == opcode)
699 return cmd;
700 }
701
702 return NULL;
703}
704
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700705static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
706{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700707 u8 ad_len = 0;
708 size_t name_len;
709
710 name_len = strlen(hdev->dev_name);
711 if (name_len > 0) {
712 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
713
714 if (name_len > max_len) {
715 name_len = max_len;
716 ptr[1] = EIR_NAME_SHORT;
717 } else
718 ptr[1] = EIR_NAME_COMPLETE;
719
720 ptr[0] = name_len + 1;
721
722 memcpy(ptr + 2, hdev->dev_name, name_len);
723
724 ad_len += (name_len + 2);
725 ptr += (name_len + 2);
726 }
727
728 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700729}
730
731static void update_scan_rsp_data(struct hci_request *req)
732{
733 struct hci_dev *hdev = req->hdev;
734 struct hci_cp_le_set_scan_rsp_data cp;
735 u8 len;
736
Johan Hedberg7751ef12013-10-19 23:38:15 +0300737 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700738 return;
739
740 memset(&cp, 0, sizeof(cp));
741
742 len = create_scan_rsp_data(hdev, cp.data);
743
Johan Hedbergeb438b52013-10-16 15:31:07 +0300744 if (hdev->scan_rsp_data_len == len &&
745 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700746 return;
747
Johan Hedbergeb438b52013-10-16 15:31:07 +0300748 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
749 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700750
751 cp.length = len;
752
753 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
754}
755
Johan Hedberg9a43e252013-10-20 19:00:07 +0300756static u8 get_adv_discov_flags(struct hci_dev *hdev)
757{
758 struct pending_cmd *cmd;
759
760 /* If there's a pending mgmt command the flags will not yet have
761 * their final values, so check for this first.
762 */
763 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
764 if (cmd) {
765 struct mgmt_mode *cp = cmd->param;
766 if (cp->val == 0x01)
767 return LE_AD_GENERAL;
768 else if (cp->val == 0x02)
769 return LE_AD_LIMITED;
770 } else {
771 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
772 return LE_AD_LIMITED;
773 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
774 return LE_AD_GENERAL;
775 }
776
777 return 0;
778}
779
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700780static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700781{
782 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700783
Johan Hedberg9a43e252013-10-20 19:00:07 +0300784 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700785
Johan Hedberge8340042014-01-30 11:16:50 -0800786 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700787 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700788
789 if (flags) {
790 BT_DBG("adv flags 0x%02x", flags);
791
792 ptr[0] = 2;
793 ptr[1] = EIR_FLAGS;
794 ptr[2] = flags;
795
796 ad_len += 3;
797 ptr += 3;
798 }
799
800 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
801 ptr[0] = 2;
802 ptr[1] = EIR_TX_POWER;
803 ptr[2] = (u8) hdev->adv_tx_power;
804
805 ad_len += 3;
806 ptr += 3;
807 }
808
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700809 return ad_len;
810}
811
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700812static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700813{
814 struct hci_dev *hdev = req->hdev;
815 struct hci_cp_le_set_adv_data cp;
816 u8 len;
817
Johan Hedberg10994ce2013-10-19 23:38:16 +0300818 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700819 return;
820
821 memset(&cp, 0, sizeof(cp));
822
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700823 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700824
825 if (hdev->adv_data_len == len &&
826 memcmp(cp.data, hdev->adv_data, len) == 0)
827 return;
828
829 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
830 hdev->adv_data_len = len;
831
832 cp.length = len;
833
834 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
835}
836
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300837static void create_eir(struct hci_dev *hdev, u8 *data)
838{
839 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300840 size_t name_len;
841
842 name_len = strlen(hdev->dev_name);
843
844 if (name_len > 0) {
845 /* EIR Data type */
846 if (name_len > 48) {
847 name_len = 48;
848 ptr[1] = EIR_NAME_SHORT;
849 } else
850 ptr[1] = EIR_NAME_COMPLETE;
851
852 /* EIR Data length */
853 ptr[0] = name_len + 1;
854
855 memcpy(ptr + 2, hdev->dev_name, name_len);
856
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300857 ptr += (name_len + 2);
858 }
859
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100860 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700861 ptr[0] = 2;
862 ptr[1] = EIR_TX_POWER;
863 ptr[2] = (u8) hdev->inq_tx_power;
864
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700865 ptr += 3;
866 }
867
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700868 if (hdev->devid_source > 0) {
869 ptr[0] = 9;
870 ptr[1] = EIR_DEVICE_ID;
871
872 put_unaligned_le16(hdev->devid_source, ptr + 2);
873 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
874 put_unaligned_le16(hdev->devid_product, ptr + 6);
875 put_unaligned_le16(hdev->devid_version, ptr + 8);
876
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700877 ptr += 10;
878 }
879
Johan Hedberg213202e2013-01-27 00:31:33 +0200880 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200881 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200882 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300883}
884
Johan Hedberg890ea892013-03-15 17:06:52 -0500885static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300886{
Johan Hedberg890ea892013-03-15 17:06:52 -0500887 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300888 struct hci_cp_write_eir cp;
889
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200890 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500891 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200892
Johan Hedberg976eb202012-10-24 21:12:01 +0300893 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500894 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300895
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200896 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500897 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300898
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200899 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500900 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300901
902 memset(&cp, 0, sizeof(cp));
903
904 create_eir(hdev, cp.data);
905
906 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500907 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300908
909 memcpy(hdev->eir, cp.data, sizeof(cp.data));
910
Johan Hedberg890ea892013-03-15 17:06:52 -0500911 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300912}
913
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200914static u8 get_service_classes(struct hci_dev *hdev)
915{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300916 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200917 u8 val = 0;
918
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300919 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200920 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200921
922 return val;
923}
924
Johan Hedberg890ea892013-03-15 17:06:52 -0500925static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200926{
Johan Hedberg890ea892013-03-15 17:06:52 -0500927 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200928 u8 cod[3];
929
930 BT_DBG("%s", hdev->name);
931
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200932 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500933 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200934
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300935 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
936 return;
937
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200938 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500939 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200940
941 cod[0] = hdev->minor_class;
942 cod[1] = hdev->major_class;
943 cod[2] = get_service_classes(hdev);
944
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700945 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
946 cod[1] |= 0x20;
947
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200948 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500949 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200950
Johan Hedberg890ea892013-03-15 17:06:52 -0500951 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200952}
953
Johan Hedberga4858cb2014-02-25 19:56:31 +0200954static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200955{
956 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200957
958 /* If there's a pending mgmt command the flag will not yet have
959 * it's final value, so check for this first.
960 */
961 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
962 if (cmd) {
963 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200964 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200965 }
966
Johan Hedberga4858cb2014-02-25 19:56:31 +0200967 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200968}
969
970static void enable_advertising(struct hci_request *req)
971{
972 struct hci_dev *hdev = req->hdev;
973 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200974 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200975 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200976
Johan Hedberg8d972502014-02-28 12:54:14 +0200977 /* Clear the HCI_ADVERTISING bit temporarily so that the
978 * hci_update_random_address knows that it's safe to go ahead
979 * and write a new random address. The flag will be set back on
980 * as soon as the SET_ADV_ENABLE HCI command completes.
981 */
982 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
983
Johan Hedberga4858cb2014-02-25 19:56:31 +0200984 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200985
Johan Hedberga4858cb2014-02-25 19:56:31 +0200986 /* Set require_privacy to true only when non-connectable
987 * advertising is used. In that case it is fine to use a
988 * non-resolvable private address.
989 */
990 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200991 return;
992
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800993 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700994 cp.min_interval = cpu_to_le16(0x0800);
995 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200996 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200997 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200998 cp.channel_map = hdev->le_adv_channel_map;
999
1000 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1001
1002 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1003}
1004
1005static void disable_advertising(struct hci_request *req)
1006{
1007 u8 enable = 0x00;
1008
1009 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1010}
1011
Johan Hedberg7d785252011-12-15 00:47:39 +02001012static void service_cache_off(struct work_struct *work)
1013{
1014 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001015 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001017
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001018 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001019 return;
1020
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 hci_req_init(&req, hdev);
1022
Johan Hedberg7d785252011-12-15 00:47:39 +02001023 hci_dev_lock(hdev);
1024
Johan Hedberg890ea892013-03-15 17:06:52 -05001025 update_eir(&req);
1026 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001027
1028 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001029
1030 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001031}
1032
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001033static void rpa_expired(struct work_struct *work)
1034{
1035 struct hci_dev *hdev = container_of(work, struct hci_dev,
1036 rpa_expired.work);
1037 struct hci_request req;
1038
1039 BT_DBG("");
1040
1041 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1042
1043 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
1044 hci_conn_num(hdev, LE_LINK) > 0)
1045 return;
1046
1047 /* The generation of a new RPA and programming it into the
1048 * controller happens in the enable_advertising() function.
1049 */
1050
1051 hci_req_init(&req, hdev);
1052
1053 disable_advertising(&req);
1054 enable_advertising(&req);
1055
1056 hci_req_run(&req, NULL);
1057}
1058
Johan Hedberg6a919082012-02-28 06:17:26 +02001059static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001060{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001061 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001062 return;
1063
Johan Hedberg4f87da82012-03-02 19:55:56 +02001064 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001065 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001066
Johan Hedberg4f87da82012-03-02 19:55:56 +02001067 /* Non-mgmt controlled devices get this bit set
1068 * implicitly so that pairing works for them, however
1069 * for mgmt we require user-space to explicitly enable
1070 * it
1071 */
1072 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001073}
1074
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001075static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001076 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001077{
1078 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001079
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001080 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001081
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001082 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001083
Johan Hedberg03811012010-12-08 00:21:06 +02001084 memset(&rp, 0, sizeof(rp));
1085
Johan Hedberg03811012010-12-08 00:21:06 +02001086 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001087
1088 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001089 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001090
1091 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1092 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1093
1094 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001095
1096 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001097 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001098
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001099 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001100
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001101 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001102 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001103}
1104
1105static void mgmt_pending_free(struct pending_cmd *cmd)
1106{
1107 sock_put(cmd->sk);
1108 kfree(cmd->param);
1109 kfree(cmd);
1110}
1111
1112static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001113 struct hci_dev *hdev, void *data,
1114 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001115{
1116 struct pending_cmd *cmd;
1117
Johan Hedbergfca20012014-06-28 17:54:05 +03001118 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001119 if (!cmd)
1120 return NULL;
1121
1122 cmd->opcode = opcode;
1123 cmd->index = hdev->id;
1124
Andre Guedes12b94562012-06-07 19:05:45 -03001125 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001126 if (!cmd->param) {
1127 kfree(cmd);
1128 return NULL;
1129 }
1130
1131 if (data)
1132 memcpy(cmd->param, data, len);
1133
1134 cmd->sk = sk;
1135 sock_hold(sk);
1136
1137 list_add(&cmd->list, &hdev->mgmt_pending);
1138
1139 return cmd;
1140}
1141
1142static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001143 void (*cb)(struct pending_cmd *cmd,
1144 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001145 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001146{
Andre Guedesa3d09352013-02-01 11:21:30 -03001147 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001148
Andre Guedesa3d09352013-02-01 11:21:30 -03001149 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001150 if (opcode > 0 && cmd->opcode != opcode)
1151 continue;
1152
1153 cb(cmd, data);
1154 }
1155}
1156
Johan Hedberg03811012010-12-08 00:21:06 +02001157static void mgmt_pending_remove(struct pending_cmd *cmd)
1158{
1159 list_del(&cmd->list);
1160 mgmt_pending_free(cmd);
1161}
1162
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001163static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001164{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001165 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001166
Johan Hedbergaee9b212012-02-18 15:07:59 +02001167 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001168 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001169}
1170
Johan Hedberg8b064a32014-02-24 14:52:22 +02001171static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1172{
1173 BT_DBG("%s status 0x%02x", hdev->name, status);
1174
Johan Hedberga3172b72014-02-28 09:33:44 +02001175 if (hci_conn_count(hdev) == 0) {
1176 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001177 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001178 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001179}
1180
Johan Hedberg21a60d32014-06-10 14:05:58 +03001181static void hci_stop_discovery(struct hci_request *req)
1182{
1183 struct hci_dev *hdev = req->hdev;
1184 struct hci_cp_remote_name_req_cancel cp;
1185 struct inquiry_entry *e;
1186
1187 switch (hdev->discovery.state) {
1188 case DISCOVERY_FINDING:
1189 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1190 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1191 } else {
1192 cancel_delayed_work(&hdev->le_scan_disable);
1193 hci_req_add_le_scan_disable(req);
1194 }
1195
1196 break;
1197
1198 case DISCOVERY_RESOLVING:
1199 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1200 NAME_PENDING);
1201 if (!e)
1202 return;
1203
1204 bacpy(&cp.bdaddr, &e->data.bdaddr);
1205 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1206 &cp);
1207
1208 break;
1209
1210 default:
1211 /* Passive scanning */
1212 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1213 hci_req_add_le_scan_disable(req);
1214 break;
1215 }
1216}
1217
Johan Hedberg8b064a32014-02-24 14:52:22 +02001218static int clean_up_hci_state(struct hci_dev *hdev)
1219{
1220 struct hci_request req;
1221 struct hci_conn *conn;
1222
1223 hci_req_init(&req, hdev);
1224
1225 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1226 test_bit(HCI_PSCAN, &hdev->flags)) {
1227 u8 scan = 0x00;
1228 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1229 }
1230
1231 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1232 disable_advertising(&req);
1233
Johan Hedbergf8680f12014-06-10 14:05:59 +03001234 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001235
1236 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1237 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001238 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001239
Johan Hedbergc9910d02014-02-27 14:35:12 +02001240 switch (conn->state) {
1241 case BT_CONNECTED:
1242 case BT_CONFIG:
1243 dc.handle = cpu_to_le16(conn->handle);
1244 dc.reason = 0x15; /* Terminated due to Power Off */
1245 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1246 break;
1247 case BT_CONNECT:
1248 if (conn->type == LE_LINK)
1249 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1250 0, NULL);
1251 else if (conn->type == ACL_LINK)
1252 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1253 6, &conn->dst);
1254 break;
1255 case BT_CONNECT2:
1256 bacpy(&rej.bdaddr, &conn->dst);
1257 rej.reason = 0x15; /* Terminated due to Power Off */
1258 if (conn->type == ACL_LINK)
1259 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1260 sizeof(rej), &rej);
1261 else if (conn->type == SCO_LINK)
1262 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1263 sizeof(rej), &rej);
1264 break;
1265 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001266 }
1267
1268 return hci_req_run(&req, clean_up_hci_complete);
1269}
1270
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001271static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001272 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001273{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001274 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001275 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001276 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001277
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001278 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001279
Johan Hedberga7e80f22013-01-09 16:05:19 +02001280 if (cp->val != 0x00 && cp->val != 0x01)
1281 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1282 MGMT_STATUS_INVALID_PARAMS);
1283
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001284 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001285
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001286 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1287 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1288 MGMT_STATUS_BUSY);
1289 goto failed;
1290 }
1291
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001292 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1293 cancel_delayed_work(&hdev->power_off);
1294
1295 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001296 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1297 data, len);
1298 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001299 goto failed;
1300 }
1301 }
1302
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001303 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001304 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001305 goto failed;
1306 }
1307
Johan Hedberg03811012010-12-08 00:21:06 +02001308 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1309 if (!cmd) {
1310 err = -ENOMEM;
1311 goto failed;
1312 }
1313
Johan Hedberg8b064a32014-02-24 14:52:22 +02001314 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001315 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001316 err = 0;
1317 } else {
1318 /* Disconnect connections, stop scans, etc */
1319 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001320 if (!err)
1321 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1322 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001323
Johan Hedberg8b064a32014-02-24 14:52:22 +02001324 /* ENODATA means there were no HCI commands queued */
1325 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001326 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001327 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1328 err = 0;
1329 }
1330 }
Johan Hedberg03811012010-12-08 00:21:06 +02001331
1332failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001333 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001334 return err;
1335}
1336
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001337static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1338 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001339{
1340 struct sk_buff *skb;
1341 struct mgmt_hdr *hdr;
1342
Andre Guedes790eff42012-06-07 19:05:46 -03001343 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001344 if (!skb)
1345 return -ENOMEM;
1346
1347 hdr = (void *) skb_put(skb, sizeof(*hdr));
1348 hdr->opcode = cpu_to_le16(event);
1349 if (hdev)
1350 hdr->index = cpu_to_le16(hdev->id);
1351 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001352 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001353 hdr->len = cpu_to_le16(data_len);
1354
1355 if (data)
1356 memcpy(skb_put(skb, data_len), data, data_len);
1357
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001358 /* Time stamp */
1359 __net_timestamp(skb);
1360
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001361 hci_send_to_control(skb, skip_sk);
1362 kfree_skb(skb);
1363
1364 return 0;
1365}
1366
1367static int new_settings(struct hci_dev *hdev, struct sock *skip)
1368{
1369 __le32 ev;
1370
1371 ev = cpu_to_le32(get_current_settings(hdev));
1372
1373 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1374}
1375
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001376struct cmd_lookup {
1377 struct sock *sk;
1378 struct hci_dev *hdev;
1379 u8 mgmt_status;
1380};
1381
1382static void settings_rsp(struct pending_cmd *cmd, void *data)
1383{
1384 struct cmd_lookup *match = data;
1385
1386 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1387
1388 list_del(&cmd->list);
1389
1390 if (match->sk == NULL) {
1391 match->sk = cmd->sk;
1392 sock_hold(match->sk);
1393 }
1394
1395 mgmt_pending_free(cmd);
1396}
1397
1398static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1399{
1400 u8 *status = data;
1401
1402 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1403 mgmt_pending_remove(cmd);
1404}
1405
Johan Hedberge6fe7982013-10-02 15:45:22 +03001406static u8 mgmt_bredr_support(struct hci_dev *hdev)
1407{
1408 if (!lmp_bredr_capable(hdev))
1409 return MGMT_STATUS_NOT_SUPPORTED;
1410 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1411 return MGMT_STATUS_REJECTED;
1412 else
1413 return MGMT_STATUS_SUCCESS;
1414}
1415
1416static u8 mgmt_le_support(struct hci_dev *hdev)
1417{
1418 if (!lmp_le_capable(hdev))
1419 return MGMT_STATUS_NOT_SUPPORTED;
1420 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1421 return MGMT_STATUS_REJECTED;
1422 else
1423 return MGMT_STATUS_SUCCESS;
1424}
1425
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001426static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1427{
1428 struct pending_cmd *cmd;
1429 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001430 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001431 bool changed;
1432
1433 BT_DBG("status 0x%02x", status);
1434
1435 hci_dev_lock(hdev);
1436
1437 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1438 if (!cmd)
1439 goto unlock;
1440
1441 if (status) {
1442 u8 mgmt_err = mgmt_status(status);
1443 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001444 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001445 goto remove_cmd;
1446 }
1447
1448 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001449 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001450 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1451 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001452
1453 if (hdev->discov_timeout > 0) {
1454 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1455 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1456 to);
1457 }
1458 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001459 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1460 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001461 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001462
1463 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1464
1465 if (changed)
1466 new_settings(hdev, cmd->sk);
1467
Marcel Holtmann970ba522013-10-15 06:33:57 -07001468 /* When the discoverable mode gets changed, make sure
1469 * that class of device has the limited discoverable
1470 * bit correctly set.
1471 */
1472 hci_req_init(&req, hdev);
1473 update_class(&req);
1474 hci_req_run(&req, NULL);
1475
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001476remove_cmd:
1477 mgmt_pending_remove(cmd);
1478
1479unlock:
1480 hci_dev_unlock(hdev);
1481}
1482
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001483static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001484 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001485{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001486 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001487 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001488 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001489 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001490 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001491 int err;
1492
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001493 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001494
Johan Hedberg9a43e252013-10-20 19:00:07 +03001495 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1496 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001497 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001498 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001499
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001500 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001501 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1502 MGMT_STATUS_INVALID_PARAMS);
1503
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001504 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001505
1506 /* Disabling discoverable requires that no timeout is set,
1507 * and enabling limited discoverable requires a timeout.
1508 */
1509 if ((cp->val == 0x00 && timeout > 0) ||
1510 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001511 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001512 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001513
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001514 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001515
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001516 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001517 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001518 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001519 goto failed;
1520 }
1521
1522 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001523 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001524 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001525 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001526 goto failed;
1527 }
1528
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001529 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001530 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001531 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001532 goto failed;
1533 }
1534
1535 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001536 bool changed = false;
1537
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001538 /* Setting limited discoverable when powered off is
1539 * not a valid operation since it requires a timeout
1540 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1541 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001542 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1543 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1544 changed = true;
1545 }
1546
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001547 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001548 if (err < 0)
1549 goto failed;
1550
1551 if (changed)
1552 err = new_settings(hdev, sk);
1553
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001554 goto failed;
1555 }
1556
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001557 /* If the current mode is the same, then just update the timeout
1558 * value with the new value. And if only the timeout gets updated,
1559 * then no need for any HCI transactions.
1560 */
1561 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1562 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1563 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001564 cancel_delayed_work(&hdev->discov_off);
1565 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001566
Marcel Holtmann36261542013-10-15 08:28:51 -07001567 if (cp->val && hdev->discov_timeout > 0) {
1568 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001569 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001570 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001571 }
1572
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001573 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001574 goto failed;
1575 }
1576
1577 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1578 if (!cmd) {
1579 err = -ENOMEM;
1580 goto failed;
1581 }
1582
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001583 /* Cancel any potential discoverable timeout that might be
1584 * still active and store new timeout value. The arming of
1585 * the timeout happens in the complete handler.
1586 */
1587 cancel_delayed_work(&hdev->discov_off);
1588 hdev->discov_timeout = timeout;
1589
Johan Hedbergb456f872013-10-19 23:38:22 +03001590 /* Limited discoverable mode */
1591 if (cp->val == 0x02)
1592 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1593 else
1594 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1595
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001596 hci_req_init(&req, hdev);
1597
Johan Hedberg9a43e252013-10-20 19:00:07 +03001598 /* The procedure for LE-only controllers is much simpler - just
1599 * update the advertising data.
1600 */
1601 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1602 goto update_ad;
1603
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001604 scan = SCAN_PAGE;
1605
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001606 if (cp->val) {
1607 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001608
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001609 if (cp->val == 0x02) {
1610 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001611 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001612 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1613 hci_cp.iac_lap[1] = 0x8b;
1614 hci_cp.iac_lap[2] = 0x9e;
1615 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1616 hci_cp.iac_lap[4] = 0x8b;
1617 hci_cp.iac_lap[5] = 0x9e;
1618 } else {
1619 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001620 hci_cp.num_iac = 1;
1621 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1622 hci_cp.iac_lap[1] = 0x8b;
1623 hci_cp.iac_lap[2] = 0x9e;
1624 }
1625
1626 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1627 (hci_cp.num_iac * 3) + 1, &hci_cp);
1628
1629 scan |= SCAN_INQUIRY;
1630 } else {
1631 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1632 }
1633
1634 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001635
Johan Hedberg9a43e252013-10-20 19:00:07 +03001636update_ad:
1637 update_adv_data(&req);
1638
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001639 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001640 if (err < 0)
1641 mgmt_pending_remove(cmd);
1642
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001643failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001644 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001645 return err;
1646}
1647
Johan Hedberg406d7802013-03-15 17:07:09 -05001648static void write_fast_connectable(struct hci_request *req, bool enable)
1649{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001650 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001651 struct hci_cp_write_page_scan_activity acp;
1652 u8 type;
1653
Johan Hedberg547003b2013-10-21 16:51:53 +03001654 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1655 return;
1656
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001657 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1658 return;
1659
Johan Hedberg406d7802013-03-15 17:07:09 -05001660 if (enable) {
1661 type = PAGE_SCAN_TYPE_INTERLACED;
1662
1663 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001664 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001665 } else {
1666 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1667
1668 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001669 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001670 }
1671
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001672 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001673
Johan Hedbergbd98b992013-03-15 17:07:13 -05001674 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1675 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1676 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1677 sizeof(acp), &acp);
1678
1679 if (hdev->page_scan_type != type)
1680 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001681}
1682
Johan Hedberg2b76f452013-03-15 17:07:04 -05001683static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1684{
1685 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001686 struct mgmt_mode *cp;
1687 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001688
1689 BT_DBG("status 0x%02x", status);
1690
1691 hci_dev_lock(hdev);
1692
1693 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1694 if (!cmd)
1695 goto unlock;
1696
Johan Hedberg37438c12013-10-14 16:20:05 +03001697 if (status) {
1698 u8 mgmt_err = mgmt_status(status);
1699 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1700 goto remove_cmd;
1701 }
1702
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001703 cp = cmd->param;
1704 if (cp->val)
1705 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1706 else
1707 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1708
Johan Hedberg2b76f452013-03-15 17:07:04 -05001709 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1710
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001711 if (changed)
1712 new_settings(hdev, cmd->sk);
1713
Johan Hedberg37438c12013-10-14 16:20:05 +03001714remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001715 mgmt_pending_remove(cmd);
1716
1717unlock:
1718 hci_dev_unlock(hdev);
1719}
1720
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001721static int set_connectable_update_settings(struct hci_dev *hdev,
1722 struct sock *sk, u8 val)
1723{
1724 bool changed = false;
1725 int err;
1726
1727 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1728 changed = true;
1729
1730 if (val) {
1731 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1732 } else {
1733 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1734 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1735 }
1736
1737 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1738 if (err < 0)
1739 return err;
1740
1741 if (changed)
1742 return new_settings(hdev, sk);
1743
1744 return 0;
1745}
1746
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001747static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001748 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001749{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001750 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001751 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001752 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001753 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001754 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001755
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001756 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001757
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001758 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1759 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001760 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001761 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001762
Johan Hedberga7e80f22013-01-09 16:05:19 +02001763 if (cp->val != 0x00 && cp->val != 0x01)
1764 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1765 MGMT_STATUS_INVALID_PARAMS);
1766
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001767 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001768
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001769 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001770 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001771 goto failed;
1772 }
1773
1774 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001775 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001776 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001777 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001778 goto failed;
1779 }
1780
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001781 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1782 if (!cmd) {
1783 err = -ENOMEM;
1784 goto failed;
1785 }
1786
Johan Hedberg2b76f452013-03-15 17:07:04 -05001787 hci_req_init(&req, hdev);
1788
Johan Hedberg9a43e252013-10-20 19:00:07 +03001789 /* If BR/EDR is not enabled and we disable advertising as a
1790 * by-product of disabling connectable, we need to update the
1791 * advertising flags.
1792 */
1793 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1794 if (!cp->val) {
1795 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1796 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1797 }
1798 update_adv_data(&req);
1799 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001800 if (cp->val) {
1801 scan = SCAN_PAGE;
1802 } else {
1803 scan = 0;
1804
1805 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001806 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001807 cancel_delayed_work(&hdev->discov_off);
1808 }
1809
1810 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1811 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001812
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001813 /* If we're going from non-connectable to connectable or
1814 * vice-versa when fast connectable is enabled ensure that fast
1815 * connectable gets disabled. write_fast_connectable won't do
1816 * anything if the page scan parameters are already what they
1817 * should be.
1818 */
1819 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001820 write_fast_connectable(&req, false);
1821
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001822 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1823 hci_conn_num(hdev, LE_LINK) == 0) {
1824 disable_advertising(&req);
1825 enable_advertising(&req);
1826 }
1827
Johan Hedberg2b76f452013-03-15 17:07:04 -05001828 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001829 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001830 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001831 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001832 err = set_connectable_update_settings(hdev, sk,
1833 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001834 goto failed;
1835 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001836
1837failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001838 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001839 return err;
1840}
1841
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001842static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001843 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001844{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001845 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001846 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001847 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001848
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001849 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001850
Johan Hedberga7e80f22013-01-09 16:05:19 +02001851 if (cp->val != 0x00 && cp->val != 0x01)
1852 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1853 MGMT_STATUS_INVALID_PARAMS);
1854
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001855 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001856
1857 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001858 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001859 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001860 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001861
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001862 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001863 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001864 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001865
Marcel Holtmann55594352013-10-06 16:11:57 -07001866 if (changed)
1867 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001868
Marcel Holtmann55594352013-10-06 16:11:57 -07001869unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001870 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001871 return err;
1872}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001873
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001874static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1875 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001876{
1877 struct mgmt_mode *cp = data;
1878 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001879 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001880 int err;
1881
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001882 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001883
Johan Hedberge6fe7982013-10-02 15:45:22 +03001884 status = mgmt_bredr_support(hdev);
1885 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001886 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001887 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001888
Johan Hedberga7e80f22013-01-09 16:05:19 +02001889 if (cp->val != 0x00 && cp->val != 0x01)
1890 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1891 MGMT_STATUS_INVALID_PARAMS);
1892
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001893 hci_dev_lock(hdev);
1894
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001895 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001896 bool changed = false;
1897
1898 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001899 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001900 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1901 changed = true;
1902 }
1903
1904 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1905 if (err < 0)
1906 goto failed;
1907
1908 if (changed)
1909 err = new_settings(hdev, sk);
1910
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001911 goto failed;
1912 }
1913
1914 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001915 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001916 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001917 goto failed;
1918 }
1919
1920 val = !!cp->val;
1921
1922 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1923 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1924 goto failed;
1925 }
1926
1927 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1928 if (!cmd) {
1929 err = -ENOMEM;
1930 goto failed;
1931 }
1932
1933 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1934 if (err < 0) {
1935 mgmt_pending_remove(cmd);
1936 goto failed;
1937 }
1938
1939failed:
1940 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001941 return err;
1942}
1943
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001944static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001945{
1946 struct mgmt_mode *cp = data;
1947 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001948 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001949 int err;
1950
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001951 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001952
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001953 status = mgmt_bredr_support(hdev);
1954 if (status)
1955 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1956
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001957 if (!lmp_ssp_capable(hdev))
1958 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1959 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001960
Johan Hedberga7e80f22013-01-09 16:05:19 +02001961 if (cp->val != 0x00 && cp->val != 0x01)
1962 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1963 MGMT_STATUS_INVALID_PARAMS);
1964
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001965 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001966
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001967 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001968 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001969
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001970 if (cp->val) {
1971 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1972 &hdev->dev_flags);
1973 } else {
1974 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1975 &hdev->dev_flags);
1976 if (!changed)
1977 changed = test_and_clear_bit(HCI_HS_ENABLED,
1978 &hdev->dev_flags);
1979 else
1980 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001981 }
1982
1983 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1984 if (err < 0)
1985 goto failed;
1986
1987 if (changed)
1988 err = new_settings(hdev, sk);
1989
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001990 goto failed;
1991 }
1992
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001993 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1994 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001995 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1996 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001997 goto failed;
1998 }
1999
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002000 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002001 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2002 goto failed;
2003 }
2004
2005 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2006 if (!cmd) {
2007 err = -ENOMEM;
2008 goto failed;
2009 }
2010
Johan Hedberg37699722014-06-24 14:00:27 +03002011 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2012 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2013 sizeof(cp->val), &cp->val);
2014
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002015 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002016 if (err < 0) {
2017 mgmt_pending_remove(cmd);
2018 goto failed;
2019 }
2020
2021failed:
2022 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002023 return err;
2024}
2025
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002026static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002027{
2028 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002029 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002030 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002031 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002032
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002033 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002034
Johan Hedberge6fe7982013-10-02 15:45:22 +03002035 status = mgmt_bredr_support(hdev);
2036 if (status)
2037 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002038
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002039 if (!lmp_ssp_capable(hdev))
2040 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2041 MGMT_STATUS_NOT_SUPPORTED);
2042
2043 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2044 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2045 MGMT_STATUS_REJECTED);
2046
Johan Hedberga7e80f22013-01-09 16:05:19 +02002047 if (cp->val != 0x00 && cp->val != 0x01)
2048 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2049 MGMT_STATUS_INVALID_PARAMS);
2050
Marcel Holtmannee392692013-10-01 22:59:23 -07002051 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002052
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002053 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002054 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002055 } else {
2056 if (hdev_is_powered(hdev)) {
2057 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2058 MGMT_STATUS_REJECTED);
2059 goto unlock;
2060 }
2061
Marcel Holtmannee392692013-10-01 22:59:23 -07002062 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002063 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002064
2065 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2066 if (err < 0)
2067 goto unlock;
2068
2069 if (changed)
2070 err = new_settings(hdev, sk);
2071
2072unlock:
2073 hci_dev_unlock(hdev);
2074 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002075}
2076
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002077static void le_enable_complete(struct hci_dev *hdev, u8 status)
2078{
2079 struct cmd_lookup match = { NULL, hdev };
2080
2081 if (status) {
2082 u8 mgmt_err = mgmt_status(status);
2083
2084 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2085 &mgmt_err);
2086 return;
2087 }
2088
2089 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2090
2091 new_settings(hdev, match.sk);
2092
2093 if (match.sk)
2094 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002095
2096 /* Make sure the controller has a good default for
2097 * advertising data. Restrict the update to when LE
2098 * has actually been enabled. During power on, the
2099 * update in powered_update_hci will take care of it.
2100 */
2101 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2102 struct hci_request req;
2103
2104 hci_dev_lock(hdev);
2105
2106 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002107 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002108 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002109 hci_req_run(&req, NULL);
2110
2111 hci_dev_unlock(hdev);
2112 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002113}
2114
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002115static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002116{
2117 struct mgmt_mode *cp = data;
2118 struct hci_cp_write_le_host_supported hci_cp;
2119 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002120 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002121 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002122 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002123
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002124 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002125
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002126 if (!lmp_le_capable(hdev))
2127 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2128 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002129
Johan Hedberga7e80f22013-01-09 16:05:19 +02002130 if (cp->val != 0x00 && cp->val != 0x01)
2131 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2132 MGMT_STATUS_INVALID_PARAMS);
2133
Johan Hedbergc73eee92013-04-19 18:35:21 +03002134 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002135 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002136 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2137 MGMT_STATUS_REJECTED);
2138
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002139 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002140
2141 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002142 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002143
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002144 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002145 bool changed = false;
2146
2147 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2148 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2149 changed = true;
2150 }
2151
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002152 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2153 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002154 changed = true;
2155 }
2156
Johan Hedberg06199cf2012-02-22 16:37:11 +02002157 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2158 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002159 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002160
2161 if (changed)
2162 err = new_settings(hdev, sk);
2163
Johan Hedberg1de028c2012-02-29 19:55:35 -08002164 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002165 }
2166
Johan Hedberg4375f102013-09-25 13:26:10 +03002167 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2168 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002169 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002170 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002171 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002172 }
2173
2174 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2175 if (!cmd) {
2176 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002177 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002178 }
2179
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002180 hci_req_init(&req, hdev);
2181
Johan Hedberg06199cf2012-02-22 16:37:11 +02002182 memset(&hci_cp, 0, sizeof(hci_cp));
2183
2184 if (val) {
2185 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002186 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002187 } else {
2188 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2189 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002190 }
2191
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002192 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2193 &hci_cp);
2194
2195 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302196 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002197 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002198
Johan Hedberg1de028c2012-02-29 19:55:35 -08002199unlock:
2200 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002201 return err;
2202}
2203
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002204/* This is a helper function to test for pending mgmt commands that can
2205 * cause CoD or EIR HCI commands. We can only allow one such pending
2206 * mgmt command at a time since otherwise we cannot easily track what
2207 * the current values are, will be, and based on that calculate if a new
2208 * HCI command needs to be sent and if yes with what value.
2209 */
2210static bool pending_eir_or_class(struct hci_dev *hdev)
2211{
2212 struct pending_cmd *cmd;
2213
2214 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2215 switch (cmd->opcode) {
2216 case MGMT_OP_ADD_UUID:
2217 case MGMT_OP_REMOVE_UUID:
2218 case MGMT_OP_SET_DEV_CLASS:
2219 case MGMT_OP_SET_POWERED:
2220 return true;
2221 }
2222 }
2223
2224 return false;
2225}
2226
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002227static const u8 bluetooth_base_uuid[] = {
2228 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2229 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2230};
2231
2232static u8 get_uuid_size(const u8 *uuid)
2233{
2234 u32 val;
2235
2236 if (memcmp(uuid, bluetooth_base_uuid, 12))
2237 return 128;
2238
2239 val = get_unaligned_le32(&uuid[12]);
2240 if (val > 0xffff)
2241 return 32;
2242
2243 return 16;
2244}
2245
Johan Hedberg92da6092013-03-15 17:06:55 -05002246static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2247{
2248 struct pending_cmd *cmd;
2249
2250 hci_dev_lock(hdev);
2251
2252 cmd = mgmt_pending_find(mgmt_op, hdev);
2253 if (!cmd)
2254 goto unlock;
2255
2256 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2257 hdev->dev_class, 3);
2258
2259 mgmt_pending_remove(cmd);
2260
2261unlock:
2262 hci_dev_unlock(hdev);
2263}
2264
2265static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2266{
2267 BT_DBG("status 0x%02x", status);
2268
2269 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2270}
2271
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002272static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002273{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002274 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002275 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002276 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002277 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002278 int err;
2279
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002280 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002281
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002282 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002283
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002284 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002285 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002286 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002287 goto failed;
2288 }
2289
Andre Guedes92c4c202012-06-07 19:05:44 -03002290 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002291 if (!uuid) {
2292 err = -ENOMEM;
2293 goto failed;
2294 }
2295
2296 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002297 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002298 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002299
Johan Hedbergde66aa62013-01-27 00:31:27 +02002300 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002301
Johan Hedberg890ea892013-03-15 17:06:52 -05002302 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002303
Johan Hedberg890ea892013-03-15 17:06:52 -05002304 update_class(&req);
2305 update_eir(&req);
2306
Johan Hedberg92da6092013-03-15 17:06:55 -05002307 err = hci_req_run(&req, add_uuid_complete);
2308 if (err < 0) {
2309 if (err != -ENODATA)
2310 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002311
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002312 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002313 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002314 goto failed;
2315 }
2316
2317 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002318 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002319 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002320 goto failed;
2321 }
2322
2323 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002324
2325failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002326 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002327 return err;
2328}
2329
Johan Hedberg24b78d02012-02-23 23:24:30 +02002330static bool enable_service_cache(struct hci_dev *hdev)
2331{
2332 if (!hdev_is_powered(hdev))
2333 return false;
2334
2335 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002336 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2337 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002338 return true;
2339 }
2340
2341 return false;
2342}
2343
Johan Hedberg92da6092013-03-15 17:06:55 -05002344static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2345{
2346 BT_DBG("status 0x%02x", status);
2347
2348 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2349}
2350
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002351static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002352 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002353{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002354 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002355 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002356 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002357 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg890ea892013-03-15 17:06:52 -05002358 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002359 int err, found;
2360
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002361 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002362
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002363 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002364
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002365 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002366 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002367 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002368 goto unlock;
2369 }
2370
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002371 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002372 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002373
Johan Hedberg24b78d02012-02-23 23:24:30 +02002374 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002375 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002376 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002377 goto unlock;
2378 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002379
Johan Hedberg9246a862012-02-23 21:33:16 +02002380 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002381 }
2382
2383 found = 0;
2384
Johan Hedberg056341c2013-01-27 00:31:30 +02002385 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002386 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2387 continue;
2388
2389 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002390 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002391 found++;
2392 }
2393
2394 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002396 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002397 goto unlock;
2398 }
2399
Johan Hedberg9246a862012-02-23 21:33:16 +02002400update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002401 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002402
Johan Hedberg890ea892013-03-15 17:06:52 -05002403 update_class(&req);
2404 update_eir(&req);
2405
Johan Hedberg92da6092013-03-15 17:06:55 -05002406 err = hci_req_run(&req, remove_uuid_complete);
2407 if (err < 0) {
2408 if (err != -ENODATA)
2409 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002410
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002411 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002412 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002413 goto unlock;
2414 }
2415
2416 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002417 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002418 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002419 goto unlock;
2420 }
2421
2422 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002423
2424unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002425 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002426 return err;
2427}
2428
Johan Hedberg92da6092013-03-15 17:06:55 -05002429static void set_class_complete(struct hci_dev *hdev, u8 status)
2430{
2431 BT_DBG("status 0x%02x", status);
2432
2433 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2434}
2435
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002436static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002437 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002438{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002439 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002440 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002441 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002442 int err;
2443
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002444 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002445
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002446 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002447 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2448 MGMT_STATUS_NOT_SUPPORTED);
2449
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002450 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002451
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002452 if (pending_eir_or_class(hdev)) {
2453 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2454 MGMT_STATUS_BUSY);
2455 goto unlock;
2456 }
2457
2458 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2459 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2460 MGMT_STATUS_INVALID_PARAMS);
2461 goto unlock;
2462 }
2463
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002464 hdev->major_class = cp->major;
2465 hdev->minor_class = cp->minor;
2466
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002467 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002468 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002469 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002470 goto unlock;
2471 }
2472
Johan Hedberg890ea892013-03-15 17:06:52 -05002473 hci_req_init(&req, hdev);
2474
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002475 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002476 hci_dev_unlock(hdev);
2477 cancel_delayed_work_sync(&hdev->service_cache);
2478 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002479 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002480 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002481
Johan Hedberg890ea892013-03-15 17:06:52 -05002482 update_class(&req);
2483
Johan Hedberg92da6092013-03-15 17:06:55 -05002484 err = hci_req_run(&req, set_class_complete);
2485 if (err < 0) {
2486 if (err != -ENODATA)
2487 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002488
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002491 goto unlock;
2492 }
2493
2494 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002495 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002496 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002497 goto unlock;
2498 }
2499
2500 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002501
Johan Hedbergb5235a62012-02-21 14:32:24 +02002502unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002503 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002504 return err;
2505}
2506
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002507static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002508 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002509{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002510 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002511 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2512 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002513 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002514 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002515 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002516
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002517 BT_DBG("request for %s", hdev->name);
2518
2519 if (!lmp_bredr_capable(hdev))
2520 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2521 MGMT_STATUS_NOT_SUPPORTED);
2522
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002523 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002524 if (key_count > max_key_count) {
2525 BT_ERR("load_link_keys: too big key_count value %u",
2526 key_count);
2527 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2528 MGMT_STATUS_INVALID_PARAMS);
2529 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002530
Johan Hedberg86742e12011-11-07 23:13:38 +02002531 expected_len = sizeof(*cp) + key_count *
2532 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002533 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002534 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002535 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002536 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002537 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002538 }
2539
Johan Hedberg4ae14302013-01-20 14:27:13 +02002540 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2541 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2542 MGMT_STATUS_INVALID_PARAMS);
2543
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002544 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002545 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002546
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002547 for (i = 0; i < key_count; i++) {
2548 struct mgmt_link_key_info *key = &cp->keys[i];
2549
Marcel Holtmann8e991132014-01-10 02:07:25 -08002550 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002551 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2552 MGMT_STATUS_INVALID_PARAMS);
2553 }
2554
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002555 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002556
2557 hci_link_keys_clear(hdev);
2558
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002559 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002560 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2561 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002562 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002563 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2564 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002565
2566 if (changed)
2567 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002568
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002569 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002570 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002571
Johan Hedberg58e92932014-06-24 14:00:26 +03002572 /* Always ignore debug keys and require a new pairing if
2573 * the user wants to use them.
2574 */
2575 if (key->type == HCI_LK_DEBUG_COMBINATION)
2576 continue;
2577
Johan Hedberg7652ff62014-06-24 13:15:49 +03002578 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2579 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002580 }
2581
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002582 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002583
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002584 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002585
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002586 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002587}
2588
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002589static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002590 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002591{
2592 struct mgmt_ev_device_unpaired ev;
2593
2594 bacpy(&ev.addr.bdaddr, bdaddr);
2595 ev.addr.type = addr_type;
2596
2597 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002598 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002599}
2600
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002601static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002602 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002603{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002604 struct mgmt_cp_unpair_device *cp = data;
2605 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002606 struct hci_cp_disconnect dc;
2607 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002608 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002609 int err;
2610
Johan Hedberga8a1d192011-11-10 15:54:38 +02002611 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002612 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2613 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002614
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002615 if (!bdaddr_type_is_valid(cp->addr.type))
2616 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2617 MGMT_STATUS_INVALID_PARAMS,
2618 &rp, sizeof(rp));
2619
Johan Hedberg118da702013-01-20 14:27:20 +02002620 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2621 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2622 MGMT_STATUS_INVALID_PARAMS,
2623 &rp, sizeof(rp));
2624
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002625 hci_dev_lock(hdev);
2626
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002627 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002628 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002629 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002630 goto unlock;
2631 }
2632
Johan Hedberge0b2b272014-02-18 17:14:31 +02002633 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002634 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002635 } else {
2636 u8 addr_type;
2637
2638 if (cp->addr.type == BDADDR_LE_PUBLIC)
2639 addr_type = ADDR_LE_DEV_PUBLIC;
2640 else
2641 addr_type = ADDR_LE_DEV_RANDOM;
2642
Johan Hedberga7ec7332014-02-18 17:14:35 +02002643 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2644
Andre Guedesa9b0a042014-02-26 20:21:52 -03002645 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2646
Johan Hedberge0b2b272014-02-18 17:14:31 +02002647 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2648 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002649
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002650 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002651 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002652 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653 goto unlock;
2654 }
2655
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002656 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002657 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002658 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002659 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002660 else
2661 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002662 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002663 } else {
2664 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002665 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002666
Johan Hedberga8a1d192011-11-10 15:54:38 +02002667 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002668 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002669 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002670 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002671 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002672 }
2673
Johan Hedberg124f6e32012-02-09 13:50:12 +02002674 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002675 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002676 if (!cmd) {
2677 err = -ENOMEM;
2678 goto unlock;
2679 }
2680
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002681 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002682 dc.reason = 0x13; /* Remote User Terminated Connection */
2683 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2684 if (err < 0)
2685 mgmt_pending_remove(cmd);
2686
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002687unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002688 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002689 return err;
2690}
2691
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002692static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002693 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002694{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002695 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002696 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002697 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002698 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002699 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002700 int err;
2701
2702 BT_DBG("");
2703
Johan Hedberg06a63b12013-01-20 14:27:21 +02002704 memset(&rp, 0, sizeof(rp));
2705 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2706 rp.addr.type = cp->addr.type;
2707
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002708 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002709 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2710 MGMT_STATUS_INVALID_PARAMS,
2711 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002712
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002713 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002714
2715 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002716 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2717 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002718 goto failed;
2719 }
2720
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002721 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002722 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2723 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002724 goto failed;
2725 }
2726
Andre Guedes591f47f2012-04-24 21:02:49 -03002727 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002728 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2729 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002730 else
2731 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002732
Vishal Agarwalf9607272012-06-13 05:32:43 +05302733 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002734 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2735 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002736 goto failed;
2737 }
2738
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002739 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002740 if (!cmd) {
2741 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002742 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002743 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002744
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002745 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002746 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002747
2748 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2749 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002750 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002751
2752failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002753 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002754 return err;
2755}
2756
Andre Guedes57c14772012-04-24 21:02:50 -03002757static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002758{
2759 switch (link_type) {
2760 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002761 switch (addr_type) {
2762 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002763 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002764
Johan Hedberg48264f02011-11-09 13:58:58 +02002765 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002766 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002767 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002768 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002769
Johan Hedberg4c659c32011-11-07 23:13:39 +02002770 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002771 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002772 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002773 }
2774}
2775
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002776static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2777 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002778{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002779 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002780 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002781 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002782 int err;
2783 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002784
2785 BT_DBG("");
2786
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002787 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002788
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002789 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002790 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002791 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002792 goto unlock;
2793 }
2794
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002795 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002796 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2797 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002798 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002799 }
2800
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002801 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002802 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002803 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002804 err = -ENOMEM;
2805 goto unlock;
2806 }
2807
Johan Hedberg2784eb42011-01-21 13:56:35 +02002808 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002809 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002810 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2811 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002812 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002813 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002814 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002815 continue;
2816 i++;
2817 }
2818
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002819 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002820
Johan Hedberg4c659c32011-11-07 23:13:39 +02002821 /* Recalculate length in case of filtered SCO connections, etc */
2822 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002823
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002824 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002825 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002826
Johan Hedberga38528f2011-01-22 06:46:43 +02002827 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002828
2829unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002830 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002831 return err;
2832}
2833
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002834static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002835 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002836{
2837 struct pending_cmd *cmd;
2838 int err;
2839
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002840 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002841 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002842 if (!cmd)
2843 return -ENOMEM;
2844
Johan Hedbergd8457692012-02-17 14:24:57 +02002845 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002846 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002847 if (err < 0)
2848 mgmt_pending_remove(cmd);
2849
2850 return err;
2851}
2852
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002853static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002854 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002855{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002856 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002857 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002858 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002859 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002860 int err;
2861
2862 BT_DBG("");
2863
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002864 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002865
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002866 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002867 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002868 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002869 goto failed;
2870 }
2871
Johan Hedbergd8457692012-02-17 14:24:57 +02002872 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002873 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002874 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002875 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002876 goto failed;
2877 }
2878
2879 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002880 struct mgmt_cp_pin_code_neg_reply ncp;
2881
2882 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002883
2884 BT_ERR("PIN code is not 16 bytes long");
2885
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002886 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002887 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002888 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002889 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002890
2891 goto failed;
2892 }
2893
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002894 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002895 if (!cmd) {
2896 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002897 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002898 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002899
Johan Hedbergd8457692012-02-17 14:24:57 +02002900 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002901 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002902 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002903
2904 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2905 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002906 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002907
2908failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002909 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002910 return err;
2911}
2912
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002913static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2914 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002915{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002916 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002917
2918 BT_DBG("");
2919
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002920 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2921 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2922 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2923
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002924 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002925
2926 hdev->io_capability = cp->io_capability;
2927
2928 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002929 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002930
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002931 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002932
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002933 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2934 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002935}
2936
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002937static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002938{
2939 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002940 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002941
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002942 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002943 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2944 continue;
2945
Johan Hedberge9a416b2011-02-19 12:05:56 -03002946 if (cmd->user_data != conn)
2947 continue;
2948
2949 return cmd;
2950 }
2951
2952 return NULL;
2953}
2954
2955static void pairing_complete(struct pending_cmd *cmd, u8 status)
2956{
2957 struct mgmt_rp_pair_device rp;
2958 struct hci_conn *conn = cmd->user_data;
2959
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002960 bacpy(&rp.addr.bdaddr, &conn->dst);
2961 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002962
Johan Hedbergaee9b212012-02-18 15:07:59 +02002963 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002964 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002965
2966 /* So we don't get further callbacks for this connection */
2967 conn->connect_cfm_cb = NULL;
2968 conn->security_cfm_cb = NULL;
2969 conn->disconn_cfm_cb = NULL;
2970
David Herrmann76a68ba2013-04-06 20:28:37 +02002971 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002972
Johan Hedberga664b5b2011-02-19 12:06:02 -03002973 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002974}
2975
Johan Hedbergf4a407be2014-02-18 21:41:34 +02002976void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2977{
2978 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2979 struct pending_cmd *cmd;
2980
2981 cmd = find_pairing(conn);
2982 if (cmd)
2983 pairing_complete(cmd, status);
2984}
2985
Johan Hedberge9a416b2011-02-19 12:05:56 -03002986static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2987{
2988 struct pending_cmd *cmd;
2989
2990 BT_DBG("status %u", status);
2991
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002992 cmd = find_pairing(conn);
2993 if (!cmd)
2994 BT_DBG("Unable to find a pending command");
2995 else
Johan Hedberge2113262012-02-18 15:20:03 +02002996 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002997}
2998
Johan Hedbergf4a407be2014-02-18 21:41:34 +02002999static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303000{
3001 struct pending_cmd *cmd;
3002
3003 BT_DBG("status %u", status);
3004
3005 if (!status)
3006 return;
3007
3008 cmd = find_pairing(conn);
3009 if (!cmd)
3010 BT_DBG("Unable to find a pending command");
3011 else
3012 pairing_complete(cmd, mgmt_status(status));
3013}
3014
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003015static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003016 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003017{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003018 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003019 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003020 struct pending_cmd *cmd;
3021 u8 sec_level, auth_type;
3022 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003023 int err;
3024
3025 BT_DBG("");
3026
Szymon Jancf950a30e2013-01-18 12:48:07 +01003027 memset(&rp, 0, sizeof(rp));
3028 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3029 rp.addr.type = cp->addr.type;
3030
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003031 if (!bdaddr_type_is_valid(cp->addr.type))
3032 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3033 MGMT_STATUS_INVALID_PARAMS,
3034 &rp, sizeof(rp));
3035
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003036 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3037 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3038 MGMT_STATUS_INVALID_PARAMS,
3039 &rp, sizeof(rp));
3040
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003041 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003042
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003043 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003044 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3045 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003046 goto unlock;
3047 }
3048
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003049 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003050 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003051
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003052 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003053 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3054 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003055 } else {
3056 u8 addr_type;
3057
3058 /* Convert from L2CAP channel address type to HCI address type
3059 */
3060 if (cp->addr.type == BDADDR_LE_PUBLIC)
3061 addr_type = ADDR_LE_DEV_PUBLIC;
3062 else
3063 addr_type = ADDR_LE_DEV_RANDOM;
3064
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003065 /* When pairing a new device, it is expected to remember
3066 * this device for future connections. Adding the connection
3067 * parameter information ahead of time allows tracking
3068 * of the slave preferred values and will speed up any
3069 * further connection establishment.
3070 *
3071 * If connection parameters already exist, then they
3072 * will be kept and this function does nothing.
3073 */
3074 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3075
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003076 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03003077 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003078 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003079
Ville Tervo30e76272011-02-22 16:10:53 -03003080 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003081 int status;
3082
3083 if (PTR_ERR(conn) == -EBUSY)
3084 status = MGMT_STATUS_BUSY;
3085 else
3086 status = MGMT_STATUS_CONNECT_FAILED;
3087
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003088 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003089 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003090 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003091 goto unlock;
3092 }
3093
3094 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003095 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003096 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003097 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003098 goto unlock;
3099 }
3100
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003101 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003102 if (!cmd) {
3103 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003104 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003105 goto unlock;
3106 }
3107
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003108 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003109 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003110 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003111 conn->security_cfm_cb = pairing_complete_cb;
3112 conn->disconn_cfm_cb = pairing_complete_cb;
3113 } else {
3114 conn->connect_cfm_cb = le_pairing_complete_cb;
3115 conn->security_cfm_cb = le_pairing_complete_cb;
3116 conn->disconn_cfm_cb = le_pairing_complete_cb;
3117 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003118
Johan Hedberge9a416b2011-02-19 12:05:56 -03003119 conn->io_capability = cp->io_cap;
3120 cmd->user_data = conn;
3121
3122 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003123 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003124 pairing_complete(cmd, 0);
3125
3126 err = 0;
3127
3128unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003129 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003130 return err;
3131}
3132
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003133static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3134 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003135{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003136 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003137 struct pending_cmd *cmd;
3138 struct hci_conn *conn;
3139 int err;
3140
3141 BT_DBG("");
3142
Johan Hedberg28424702012-02-02 04:02:29 +02003143 hci_dev_lock(hdev);
3144
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003145 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003146 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003147 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003148 goto unlock;
3149 }
3150
Johan Hedberg28424702012-02-02 04:02:29 +02003151 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3152 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003153 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003154 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003155 goto unlock;
3156 }
3157
3158 conn = cmd->user_data;
3159
3160 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003161 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003162 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003163 goto unlock;
3164 }
3165
3166 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3167
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003168 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003169 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003170unlock:
3171 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003172 return err;
3173}
3174
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003175static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003176 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003177 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003178{
Johan Hedberga5c29682011-02-19 12:05:57 -03003179 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003180 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003181 int err;
3182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003183 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003184
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003185 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003186 err = cmd_complete(sk, hdev->id, mgmt_op,
3187 MGMT_STATUS_NOT_POWERED, addr,
3188 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003189 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003190 }
3191
Johan Hedberg1707c602013-03-15 17:07:15 -05003192 if (addr->type == BDADDR_BREDR)
3193 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003194 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003195 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003196
Johan Hedberg272d90d2012-02-09 15:26:12 +02003197 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003198 err = cmd_complete(sk, hdev->id, mgmt_op,
3199 MGMT_STATUS_NOT_CONNECTED, addr,
3200 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003201 goto done;
3202 }
3203
Johan Hedberg1707c602013-03-15 17:07:15 -05003204 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003205 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003206 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003207 err = cmd_complete(sk, hdev->id, mgmt_op,
3208 MGMT_STATUS_SUCCESS, addr,
3209 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003210 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003211 err = cmd_complete(sk, hdev->id, mgmt_op,
3212 MGMT_STATUS_FAILED, addr,
3213 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003214
Brian Gix47c15e22011-11-16 13:53:14 -08003215 goto done;
3216 }
3217
Johan Hedberg1707c602013-03-15 17:07:15 -05003218 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003219 if (!cmd) {
3220 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003221 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003222 }
3223
Brian Gix0df4c182011-11-16 13:53:13 -08003224 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003225 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3226 struct hci_cp_user_passkey_reply cp;
3227
Johan Hedberg1707c602013-03-15 17:07:15 -05003228 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003229 cp.passkey = passkey;
3230 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3231 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003232 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3233 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003234
Johan Hedberga664b5b2011-02-19 12:06:02 -03003235 if (err < 0)
3236 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003237
Brian Gix0df4c182011-11-16 13:53:13 -08003238done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003239 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003240 return err;
3241}
3242
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303243static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3244 void *data, u16 len)
3245{
3246 struct mgmt_cp_pin_code_neg_reply *cp = data;
3247
3248 BT_DBG("");
3249
Johan Hedberg1707c602013-03-15 17:07:15 -05003250 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303251 MGMT_OP_PIN_CODE_NEG_REPLY,
3252 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3253}
3254
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003255static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3256 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003257{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003258 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003259
3260 BT_DBG("");
3261
3262 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003263 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003264 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003265
Johan Hedberg1707c602013-03-15 17:07:15 -05003266 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003267 MGMT_OP_USER_CONFIRM_REPLY,
3268 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003269}
3270
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003271static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003272 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003273{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003274 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003275
3276 BT_DBG("");
3277
Johan Hedberg1707c602013-03-15 17:07:15 -05003278 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003279 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3280 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003281}
3282
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003283static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3284 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003285{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003286 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003287
3288 BT_DBG("");
3289
Johan Hedberg1707c602013-03-15 17:07:15 -05003290 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003291 MGMT_OP_USER_PASSKEY_REPLY,
3292 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003293}
3294
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003295static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003296 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003297{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003298 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003299
3300 BT_DBG("");
3301
Johan Hedberg1707c602013-03-15 17:07:15 -05003302 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003303 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3304 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003305}
3306
Johan Hedberg13928972013-03-15 17:07:00 -05003307static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003308{
Johan Hedberg13928972013-03-15 17:07:00 -05003309 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003310 struct hci_cp_write_local_name cp;
3311
Johan Hedberg13928972013-03-15 17:07:00 -05003312 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003313
Johan Hedberg890ea892013-03-15 17:06:52 -05003314 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003315}
3316
Johan Hedberg13928972013-03-15 17:07:00 -05003317static void set_name_complete(struct hci_dev *hdev, u8 status)
3318{
3319 struct mgmt_cp_set_local_name *cp;
3320 struct pending_cmd *cmd;
3321
3322 BT_DBG("status 0x%02x", status);
3323
3324 hci_dev_lock(hdev);
3325
3326 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3327 if (!cmd)
3328 goto unlock;
3329
3330 cp = cmd->param;
3331
3332 if (status)
3333 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3334 mgmt_status(status));
3335 else
3336 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3337 cp, sizeof(*cp));
3338
3339 mgmt_pending_remove(cmd);
3340
3341unlock:
3342 hci_dev_unlock(hdev);
3343}
3344
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003345static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003346 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003347{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003348 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003349 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003350 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003351 int err;
3352
3353 BT_DBG("");
3354
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003355 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003356
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003357 /* If the old values are the same as the new ones just return a
3358 * direct command complete event.
3359 */
3360 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3361 !memcmp(hdev->short_name, cp->short_name,
3362 sizeof(hdev->short_name))) {
3363 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3364 data, len);
3365 goto failed;
3366 }
3367
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003368 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003369
Johan Hedbergb5235a62012-02-21 14:32:24 +02003370 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003371 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003372
3373 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003374 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003375 if (err < 0)
3376 goto failed;
3377
3378 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003379 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003380
Johan Hedbergb5235a62012-02-21 14:32:24 +02003381 goto failed;
3382 }
3383
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003384 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003385 if (!cmd) {
3386 err = -ENOMEM;
3387 goto failed;
3388 }
3389
Johan Hedberg13928972013-03-15 17:07:00 -05003390 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3391
Johan Hedberg890ea892013-03-15 17:06:52 -05003392 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003393
3394 if (lmp_bredr_capable(hdev)) {
3395 update_name(&req);
3396 update_eir(&req);
3397 }
3398
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003399 /* The name is stored in the scan response data and so
3400 * no need to udpate the advertising data here.
3401 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003402 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003403 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003404
Johan Hedberg13928972013-03-15 17:07:00 -05003405 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003406 if (err < 0)
3407 mgmt_pending_remove(cmd);
3408
3409failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003410 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003411 return err;
3412}
3413
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003414static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003415 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003416{
Szymon Jancc35938b2011-03-22 13:12:21 +01003417 struct pending_cmd *cmd;
3418 int err;
3419
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003420 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003421
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003422 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003423
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003424 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003425 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003426 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003427 goto unlock;
3428 }
3429
Andre Guedes9a1a1992012-07-24 15:03:48 -03003430 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003431 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003432 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003433 goto unlock;
3434 }
3435
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003436 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003437 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003438 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003439 goto unlock;
3440 }
3441
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003442 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003443 if (!cmd) {
3444 err = -ENOMEM;
3445 goto unlock;
3446 }
3447
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003448 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3449 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3450 0, NULL);
3451 else
3452 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3453
Szymon Jancc35938b2011-03-22 13:12:21 +01003454 if (err < 0)
3455 mgmt_pending_remove(cmd);
3456
3457unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003458 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003459 return err;
3460}
3461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003462static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003463 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003464{
Szymon Janc2763eda2011-03-22 13:12:22 +01003465 int err;
3466
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003467 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003468
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003469 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003470
Marcel Holtmannec109112014-01-10 02:07:30 -08003471 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3472 struct mgmt_cp_add_remote_oob_data *cp = data;
3473 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003474
Marcel Holtmannec109112014-01-10 02:07:30 -08003475 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3476 cp->hash, cp->randomizer);
3477 if (err < 0)
3478 status = MGMT_STATUS_FAILED;
3479 else
3480 status = MGMT_STATUS_SUCCESS;
3481
3482 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3483 status, &cp->addr, sizeof(cp->addr));
3484 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3485 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3486 u8 status;
3487
3488 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3489 cp->hash192,
3490 cp->randomizer192,
3491 cp->hash256,
3492 cp->randomizer256);
3493 if (err < 0)
3494 status = MGMT_STATUS_FAILED;
3495 else
3496 status = MGMT_STATUS_SUCCESS;
3497
3498 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3499 status, &cp->addr, sizeof(cp->addr));
3500 } else {
3501 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3502 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3503 MGMT_STATUS_INVALID_PARAMS);
3504 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003505
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003506 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003507 return err;
3508}
3509
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003510static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003511 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003512{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003513 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003514 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003515 int err;
3516
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003517 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003518
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003519 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003520
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003521 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003522 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003523 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003524 else
Szymon Janca6785be2012-12-13 15:11:21 +01003525 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003526
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003527 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003528 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003529
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003530 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003531 return err;
3532}
3533
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003534static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3535{
3536 struct pending_cmd *cmd;
3537 u8 type;
3538 int err;
3539
3540 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3541
3542 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3543 if (!cmd)
3544 return -ENOENT;
3545
3546 type = hdev->discovery.type;
3547
3548 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3549 &type, sizeof(type));
3550 mgmt_pending_remove(cmd);
3551
3552 return err;
3553}
3554
Andre Guedes7c307722013-04-30 15:29:28 -03003555static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3556{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003557 unsigned long timeout = 0;
3558
Andre Guedes7c307722013-04-30 15:29:28 -03003559 BT_DBG("status %d", status);
3560
3561 if (status) {
3562 hci_dev_lock(hdev);
3563 mgmt_start_discovery_failed(hdev, status);
3564 hci_dev_unlock(hdev);
3565 return;
3566 }
3567
3568 hci_dev_lock(hdev);
3569 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3570 hci_dev_unlock(hdev);
3571
3572 switch (hdev->discovery.type) {
3573 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003574 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003575 break;
3576
3577 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003578 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003579 break;
3580
3581 case DISCOV_TYPE_BREDR:
3582 break;
3583
3584 default:
3585 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3586 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003587
3588 if (!timeout)
3589 return;
3590
3591 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003592}
3593
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003594static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003595 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003596{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003597 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003598 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003599 struct hci_cp_le_set_scan_param param_cp;
3600 struct hci_cp_le_set_scan_enable enable_cp;
3601 struct hci_cp_inquiry inq_cp;
3602 struct hci_request req;
3603 /* General inquiry access code (GIAC) */
3604 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003605 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003606 int err;
3607
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003608 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003609
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003610 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003611
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003612 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003613 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003614 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003615 goto failed;
3616 }
3617
Andre Guedes642be6c2012-03-21 00:03:37 -03003618 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3619 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3620 MGMT_STATUS_BUSY);
3621 goto failed;
3622 }
3623
Johan Hedbergff9ef572012-01-04 14:23:45 +02003624 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003625 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003626 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003627 goto failed;
3628 }
3629
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003630 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003631 if (!cmd) {
3632 err = -ENOMEM;
3633 goto failed;
3634 }
3635
Andre Guedes4aab14e2012-02-17 20:39:36 -03003636 hdev->discovery.type = cp->type;
3637
Andre Guedes7c307722013-04-30 15:29:28 -03003638 hci_req_init(&req, hdev);
3639
Andre Guedes4aab14e2012-02-17 20:39:36 -03003640 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003641 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003642 status = mgmt_bredr_support(hdev);
3643 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003644 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003645 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003646 mgmt_pending_remove(cmd);
3647 goto failed;
3648 }
3649
Andre Guedes7c307722013-04-30 15:29:28 -03003650 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3651 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3652 MGMT_STATUS_BUSY);
3653 mgmt_pending_remove(cmd);
3654 goto failed;
3655 }
3656
3657 hci_inquiry_cache_flush(hdev);
3658
3659 memset(&inq_cp, 0, sizeof(inq_cp));
3660 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003661 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003662 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003663 break;
3664
3665 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003666 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003667 status = mgmt_le_support(hdev);
3668 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003669 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003670 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003671 mgmt_pending_remove(cmd);
3672 goto failed;
3673 }
3674
Andre Guedes7c307722013-04-30 15:29:28 -03003675 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003676 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003677 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3678 MGMT_STATUS_NOT_SUPPORTED);
3679 mgmt_pending_remove(cmd);
3680 goto failed;
3681 }
3682
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003683 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003684 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3685 MGMT_STATUS_REJECTED);
3686 mgmt_pending_remove(cmd);
3687 goto failed;
3688 }
3689
Andre Guedesc54c3862014-02-26 20:21:50 -03003690 /* If controller is scanning, it means the background scanning
3691 * is running. Thus, we should temporarily stop it in order to
3692 * set the discovery scanning parameters.
3693 */
3694 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3695 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003696
3697 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003698
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003699 /* All active scans will be done with either a resolvable
3700 * private address (when privacy feature has been enabled)
3701 * or unresolvable private address.
3702 */
3703 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003704 if (err < 0) {
3705 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3706 MGMT_STATUS_FAILED);
3707 mgmt_pending_remove(cmd);
3708 goto failed;
3709 }
3710
Andre Guedes7c307722013-04-30 15:29:28 -03003711 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003712 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3713 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003714 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003715 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3716 &param_cp);
3717
3718 memset(&enable_cp, 0, sizeof(enable_cp));
3719 enable_cp.enable = LE_SCAN_ENABLE;
3720 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3721 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3722 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003723 break;
3724
Andre Guedesf39799f2012-02-17 20:39:35 -03003725 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003726 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3727 MGMT_STATUS_INVALID_PARAMS);
3728 mgmt_pending_remove(cmd);
3729 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003730 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003731
Andre Guedes7c307722013-04-30 15:29:28 -03003732 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003733 if (err < 0)
3734 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003735 else
3736 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003737
3738failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003739 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003740 return err;
3741}
3742
Andre Guedes1183fdc2013-04-30 15:29:35 -03003743static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3744{
3745 struct pending_cmd *cmd;
3746 int err;
3747
3748 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3749 if (!cmd)
3750 return -ENOENT;
3751
3752 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3753 &hdev->discovery.type, sizeof(hdev->discovery.type));
3754 mgmt_pending_remove(cmd);
3755
3756 return err;
3757}
3758
Andre Guedes0e05bba2013-04-30 15:29:33 -03003759static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3760{
3761 BT_DBG("status %d", status);
3762
3763 hci_dev_lock(hdev);
3764
3765 if (status) {
3766 mgmt_stop_discovery_failed(hdev, status);
3767 goto unlock;
3768 }
3769
3770 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3771
3772unlock:
3773 hci_dev_unlock(hdev);
3774}
3775
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003776static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003777 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003778{
Johan Hedbergd9306502012-02-20 23:25:18 +02003779 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003780 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003781 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003782 int err;
3783
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003784 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003785
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003786 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003787
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003788 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003789 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003790 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3791 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003792 goto unlock;
3793 }
3794
3795 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003796 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003797 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3798 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003799 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003800 }
3801
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003802 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003803 if (!cmd) {
3804 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003805 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003806 }
3807
Andre Guedes0e05bba2013-04-30 15:29:33 -03003808 hci_req_init(&req, hdev);
3809
Johan Hedberg21a60d32014-06-10 14:05:58 +03003810 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003811
Johan Hedberg21a60d32014-06-10 14:05:58 +03003812 err = hci_req_run(&req, stop_discovery_complete);
3813 if (!err) {
3814 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003815 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003816 }
3817
Johan Hedberg21a60d32014-06-10 14:05:58 +03003818 mgmt_pending_remove(cmd);
3819
3820 /* If no HCI commands were sent we're done */
3821 if (err == -ENODATA) {
3822 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3823 &mgmt_cp->type, sizeof(mgmt_cp->type));
3824 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3825 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003826
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003827unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003828 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003829 return err;
3830}
3831
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003832static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003833 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003834{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003835 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003836 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003837 int err;
3838
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003839 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003840
Johan Hedberg561aafb2012-01-04 13:31:59 +02003841 hci_dev_lock(hdev);
3842
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003843 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003844 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3845 MGMT_STATUS_FAILED, &cp->addr,
3846 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003847 goto failed;
3848 }
3849
Johan Hedberga198e7b2012-02-17 14:27:06 +02003850 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003851 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003852 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3853 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3854 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003855 goto failed;
3856 }
3857
3858 if (cp->name_known) {
3859 e->name_state = NAME_KNOWN;
3860 list_del(&e->list);
3861 } else {
3862 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003863 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003864 }
3865
Johan Hedberge3846622013-01-09 15:29:33 +02003866 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3867 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003868
3869failed:
3870 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003871 return err;
3872}
3873
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003874static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003875 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003876{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003877 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003878 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003879 int err;
3880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003881 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003882
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003883 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003884 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3885 MGMT_STATUS_INVALID_PARAMS,
3886 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003887
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003888 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003889
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003890 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003891 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003892 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003893 goto done;
3894 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003895
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003896 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3897 sk);
3898 status = MGMT_STATUS_SUCCESS;
3899
3900done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003901 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003902 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003903
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003904 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003905
3906 return err;
3907}
3908
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003909static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003910 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003911{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003912 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003913 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003914 int err;
3915
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003916 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003917
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003918 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003919 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3920 MGMT_STATUS_INVALID_PARAMS,
3921 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003922
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003923 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003924
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003925 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003926 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003927 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003928 goto done;
3929 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003930
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003931 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3932 sk);
3933 status = MGMT_STATUS_SUCCESS;
3934
3935done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003936 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003937 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003938
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003939 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003940
3941 return err;
3942}
3943
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003944static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3945 u16 len)
3946{
3947 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003948 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003949 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003950 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003951
3952 BT_DBG("%s", hdev->name);
3953
Szymon Jancc72d4b82012-03-16 16:02:57 +01003954 source = __le16_to_cpu(cp->source);
3955
3956 if (source > 0x0002)
3957 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3958 MGMT_STATUS_INVALID_PARAMS);
3959
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003960 hci_dev_lock(hdev);
3961
Szymon Jancc72d4b82012-03-16 16:02:57 +01003962 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003963 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3964 hdev->devid_product = __le16_to_cpu(cp->product);
3965 hdev->devid_version = __le16_to_cpu(cp->version);
3966
3967 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3968
Johan Hedberg890ea892013-03-15 17:06:52 -05003969 hci_req_init(&req, hdev);
3970 update_eir(&req);
3971 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003972
3973 hci_dev_unlock(hdev);
3974
3975 return err;
3976}
3977
Johan Hedberg4375f102013-09-25 13:26:10 +03003978static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3979{
3980 struct cmd_lookup match = { NULL, hdev };
3981
3982 if (status) {
3983 u8 mgmt_err = mgmt_status(status);
3984
3985 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3986 cmd_status_rsp, &mgmt_err);
3987 return;
3988 }
3989
3990 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3991 &match);
3992
3993 new_settings(hdev, match.sk);
3994
3995 if (match.sk)
3996 sock_put(match.sk);
3997}
3998
Marcel Holtmann21b51872013-10-10 09:47:53 -07003999static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4000 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004001{
4002 struct mgmt_mode *cp = data;
4003 struct pending_cmd *cmd;
4004 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004005 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004006 int err;
4007
4008 BT_DBG("request for %s", hdev->name);
4009
Johan Hedberge6fe7982013-10-02 15:45:22 +03004010 status = mgmt_le_support(hdev);
4011 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004012 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004013 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004014
4015 if (cp->val != 0x00 && cp->val != 0x01)
4016 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4017 MGMT_STATUS_INVALID_PARAMS);
4018
4019 hci_dev_lock(hdev);
4020
4021 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004022 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004023
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004024 /* The following conditions are ones which mean that we should
4025 * not do any HCI communication but directly send a mgmt
4026 * response to user space (after toggling the flag if
4027 * necessary).
4028 */
4029 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004030 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004031 bool changed = false;
4032
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004033 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4034 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004035 changed = true;
4036 }
4037
4038 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4039 if (err < 0)
4040 goto unlock;
4041
4042 if (changed)
4043 err = new_settings(hdev, sk);
4044
4045 goto unlock;
4046 }
4047
4048 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4049 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4050 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4051 MGMT_STATUS_BUSY);
4052 goto unlock;
4053 }
4054
4055 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4056 if (!cmd) {
4057 err = -ENOMEM;
4058 goto unlock;
4059 }
4060
4061 hci_req_init(&req, hdev);
4062
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004063 if (val)
4064 enable_advertising(&req);
4065 else
4066 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004067
4068 err = hci_req_run(&req, set_advertising_complete);
4069 if (err < 0)
4070 mgmt_pending_remove(cmd);
4071
4072unlock:
4073 hci_dev_unlock(hdev);
4074 return err;
4075}
4076
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004077static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4078 void *data, u16 len)
4079{
4080 struct mgmt_cp_set_static_address *cp = data;
4081 int err;
4082
4083 BT_DBG("%s", hdev->name);
4084
Marcel Holtmann62af4442013-10-02 22:10:32 -07004085 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004086 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004087 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004088
4089 if (hdev_is_powered(hdev))
4090 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4091 MGMT_STATUS_REJECTED);
4092
4093 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4094 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4095 return cmd_status(sk, hdev->id,
4096 MGMT_OP_SET_STATIC_ADDRESS,
4097 MGMT_STATUS_INVALID_PARAMS);
4098
4099 /* Two most significant bits shall be set */
4100 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4101 return cmd_status(sk, hdev->id,
4102 MGMT_OP_SET_STATIC_ADDRESS,
4103 MGMT_STATUS_INVALID_PARAMS);
4104 }
4105
4106 hci_dev_lock(hdev);
4107
4108 bacpy(&hdev->static_addr, &cp->bdaddr);
4109
4110 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4111
4112 hci_dev_unlock(hdev);
4113
4114 return err;
4115}
4116
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004117static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4118 void *data, u16 len)
4119{
4120 struct mgmt_cp_set_scan_params *cp = data;
4121 __u16 interval, window;
4122 int err;
4123
4124 BT_DBG("%s", hdev->name);
4125
4126 if (!lmp_le_capable(hdev))
4127 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4128 MGMT_STATUS_NOT_SUPPORTED);
4129
4130 interval = __le16_to_cpu(cp->interval);
4131
4132 if (interval < 0x0004 || interval > 0x4000)
4133 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4134 MGMT_STATUS_INVALID_PARAMS);
4135
4136 window = __le16_to_cpu(cp->window);
4137
4138 if (window < 0x0004 || window > 0x4000)
4139 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4140 MGMT_STATUS_INVALID_PARAMS);
4141
Marcel Holtmann899e1072013-10-14 09:55:32 -07004142 if (window > interval)
4143 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4144 MGMT_STATUS_INVALID_PARAMS);
4145
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004146 hci_dev_lock(hdev);
4147
4148 hdev->le_scan_interval = interval;
4149 hdev->le_scan_window = window;
4150
4151 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4152
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004153 /* If background scan is running, restart it so new parameters are
4154 * loaded.
4155 */
4156 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4157 hdev->discovery.state == DISCOVERY_STOPPED) {
4158 struct hci_request req;
4159
4160 hci_req_init(&req, hdev);
4161
4162 hci_req_add_le_scan_disable(&req);
4163 hci_req_add_le_passive_scan(&req);
4164
4165 hci_req_run(&req, NULL);
4166 }
4167
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004168 hci_dev_unlock(hdev);
4169
4170 return err;
4171}
4172
Johan Hedberg33e38b32013-03-15 17:07:05 -05004173static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4174{
4175 struct pending_cmd *cmd;
4176
4177 BT_DBG("status 0x%02x", status);
4178
4179 hci_dev_lock(hdev);
4180
4181 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4182 if (!cmd)
4183 goto unlock;
4184
4185 if (status) {
4186 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4187 mgmt_status(status));
4188 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004189 struct mgmt_mode *cp = cmd->param;
4190
4191 if (cp->val)
4192 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4193 else
4194 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4195
Johan Hedberg33e38b32013-03-15 17:07:05 -05004196 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4197 new_settings(hdev, cmd->sk);
4198 }
4199
4200 mgmt_pending_remove(cmd);
4201
4202unlock:
4203 hci_dev_unlock(hdev);
4204}
4205
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004206static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004207 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004208{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004209 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004210 struct pending_cmd *cmd;
4211 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004212 int err;
4213
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004214 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004215
Johan Hedberg56f87902013-10-02 13:43:13 +03004216 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4217 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004218 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4219 MGMT_STATUS_NOT_SUPPORTED);
4220
Johan Hedberga7e80f22013-01-09 16:05:19 +02004221 if (cp->val != 0x00 && cp->val != 0x01)
4222 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4223 MGMT_STATUS_INVALID_PARAMS);
4224
Johan Hedberg5400c042012-02-21 16:40:33 +02004225 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004226 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004227 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004228
4229 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004230 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004231 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004232
4233 hci_dev_lock(hdev);
4234
Johan Hedberg05cbf292013-03-15 17:07:07 -05004235 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4236 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4237 MGMT_STATUS_BUSY);
4238 goto unlock;
4239 }
4240
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004241 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4242 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4243 hdev);
4244 goto unlock;
4245 }
4246
Johan Hedberg33e38b32013-03-15 17:07:05 -05004247 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4248 data, len);
4249 if (!cmd) {
4250 err = -ENOMEM;
4251 goto unlock;
4252 }
4253
4254 hci_req_init(&req, hdev);
4255
Johan Hedberg406d7802013-03-15 17:07:09 -05004256 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004257
4258 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004259 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004260 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004261 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004262 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004263 }
4264
Johan Hedberg33e38b32013-03-15 17:07:05 -05004265unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004266 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004267
Antti Julkuf6422ec2011-06-22 13:11:56 +03004268 return err;
4269}
4270
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004271static void set_bredr_scan(struct hci_request *req)
4272{
4273 struct hci_dev *hdev = req->hdev;
4274 u8 scan = 0;
4275
4276 /* Ensure that fast connectable is disabled. This function will
4277 * not do anything if the page scan parameters are already what
4278 * they should be.
4279 */
4280 write_fast_connectable(req, false);
4281
4282 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4283 scan |= SCAN_PAGE;
4284 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4285 scan |= SCAN_INQUIRY;
4286
4287 if (scan)
4288 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4289}
4290
Johan Hedberg0663ca22013-10-02 13:43:14 +03004291static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4292{
4293 struct pending_cmd *cmd;
4294
4295 BT_DBG("status 0x%02x", status);
4296
4297 hci_dev_lock(hdev);
4298
4299 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4300 if (!cmd)
4301 goto unlock;
4302
4303 if (status) {
4304 u8 mgmt_err = mgmt_status(status);
4305
4306 /* We need to restore the flag if related HCI commands
4307 * failed.
4308 */
4309 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4310
4311 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4312 } else {
4313 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4314 new_settings(hdev, cmd->sk);
4315 }
4316
4317 mgmt_pending_remove(cmd);
4318
4319unlock:
4320 hci_dev_unlock(hdev);
4321}
4322
4323static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4324{
4325 struct mgmt_mode *cp = data;
4326 struct pending_cmd *cmd;
4327 struct hci_request req;
4328 int err;
4329
4330 BT_DBG("request for %s", hdev->name);
4331
4332 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4333 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4334 MGMT_STATUS_NOT_SUPPORTED);
4335
4336 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4337 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4338 MGMT_STATUS_REJECTED);
4339
4340 if (cp->val != 0x00 && cp->val != 0x01)
4341 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4342 MGMT_STATUS_INVALID_PARAMS);
4343
4344 hci_dev_lock(hdev);
4345
4346 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4347 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4348 goto unlock;
4349 }
4350
4351 if (!hdev_is_powered(hdev)) {
4352 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004353 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4354 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4355 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4356 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4357 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4358 }
4359
4360 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4361
4362 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4363 if (err < 0)
4364 goto unlock;
4365
4366 err = new_settings(hdev, sk);
4367 goto unlock;
4368 }
4369
4370 /* Reject disabling when powered on */
4371 if (!cp->val) {
4372 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4373 MGMT_STATUS_REJECTED);
4374 goto unlock;
4375 }
4376
4377 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4378 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4379 MGMT_STATUS_BUSY);
4380 goto unlock;
4381 }
4382
4383 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4384 if (!cmd) {
4385 err = -ENOMEM;
4386 goto unlock;
4387 }
4388
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004389 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004390 * generates the correct flags.
4391 */
4392 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4393
4394 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004395
4396 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4397 set_bredr_scan(&req);
4398
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004399 /* Since only the advertising data flags will change, there
4400 * is no need to update the scan response data.
4401 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004402 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004403
Johan Hedberg0663ca22013-10-02 13:43:14 +03004404 err = hci_req_run(&req, set_bredr_complete);
4405 if (err < 0)
4406 mgmt_pending_remove(cmd);
4407
4408unlock:
4409 hci_dev_unlock(hdev);
4410 return err;
4411}
4412
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004413static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4414 void *data, u16 len)
4415{
4416 struct mgmt_mode *cp = data;
4417 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004418 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004419 int err;
4420
4421 BT_DBG("request for %s", hdev->name);
4422
4423 status = mgmt_bredr_support(hdev);
4424 if (status)
4425 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4426 status);
4427
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004428 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004429 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004430 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4431 MGMT_STATUS_NOT_SUPPORTED);
4432
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004433 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004434 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4435 MGMT_STATUS_INVALID_PARAMS);
4436
4437 hci_dev_lock(hdev);
4438
4439 if (!hdev_is_powered(hdev)) {
4440 bool changed;
4441
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004442 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004443 changed = !test_and_set_bit(HCI_SC_ENABLED,
4444 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004445 if (cp->val == 0x02)
4446 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4447 else
4448 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4449 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004450 changed = test_and_clear_bit(HCI_SC_ENABLED,
4451 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004452 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4453 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004454
4455 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4456 if (err < 0)
4457 goto failed;
4458
4459 if (changed)
4460 err = new_settings(hdev, sk);
4461
4462 goto failed;
4463 }
4464
4465 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4466 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4467 MGMT_STATUS_BUSY);
4468 goto failed;
4469 }
4470
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004471 val = !!cp->val;
4472
4473 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4474 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004475 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4476 goto failed;
4477 }
4478
4479 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4480 if (!cmd) {
4481 err = -ENOMEM;
4482 goto failed;
4483 }
4484
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004485 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004486 if (err < 0) {
4487 mgmt_pending_remove(cmd);
4488 goto failed;
4489 }
4490
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004491 if (cp->val == 0x02)
4492 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4493 else
4494 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4495
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004496failed:
4497 hci_dev_unlock(hdev);
4498 return err;
4499}
4500
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004501static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4502 void *data, u16 len)
4503{
4504 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004505 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004506 int err;
4507
4508 BT_DBG("request for %s", hdev->name);
4509
Johan Hedbergb97109792014-06-24 14:00:28 +03004510 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004511 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4512 MGMT_STATUS_INVALID_PARAMS);
4513
4514 hci_dev_lock(hdev);
4515
4516 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004517 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4518 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004519 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004520 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4521 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004522
Johan Hedbergb97109792014-06-24 14:00:28 +03004523 if (cp->val == 0x02)
4524 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4525 &hdev->dev_flags);
4526 else
4527 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4528 &hdev->dev_flags);
4529
4530 if (hdev_is_powered(hdev) && use_changed &&
4531 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4532 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4533 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4534 sizeof(mode), &mode);
4535 }
4536
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004537 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4538 if (err < 0)
4539 goto unlock;
4540
4541 if (changed)
4542 err = new_settings(hdev, sk);
4543
4544unlock:
4545 hci_dev_unlock(hdev);
4546 return err;
4547}
4548
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004549static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4550 u16 len)
4551{
4552 struct mgmt_cp_set_privacy *cp = cp_data;
4553 bool changed;
4554 int err;
4555
4556 BT_DBG("request for %s", hdev->name);
4557
4558 if (!lmp_le_capable(hdev))
4559 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4560 MGMT_STATUS_NOT_SUPPORTED);
4561
4562 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4563 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4564 MGMT_STATUS_INVALID_PARAMS);
4565
4566 if (hdev_is_powered(hdev))
4567 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4568 MGMT_STATUS_REJECTED);
4569
4570 hci_dev_lock(hdev);
4571
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004572 /* If user space supports this command it is also expected to
4573 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4574 */
4575 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4576
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004577 if (cp->privacy) {
4578 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4579 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4580 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4581 } else {
4582 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4583 memset(hdev->irk, 0, sizeof(hdev->irk));
4584 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4585 }
4586
4587 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4588 if (err < 0)
4589 goto unlock;
4590
4591 if (changed)
4592 err = new_settings(hdev, sk);
4593
4594unlock:
4595 hci_dev_unlock(hdev);
4596 return err;
4597}
4598
Johan Hedberg41edf162014-02-18 10:19:35 +02004599static bool irk_is_valid(struct mgmt_irk_info *irk)
4600{
4601 switch (irk->addr.type) {
4602 case BDADDR_LE_PUBLIC:
4603 return true;
4604
4605 case BDADDR_LE_RANDOM:
4606 /* Two most significant bits shall be set */
4607 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4608 return false;
4609 return true;
4610 }
4611
4612 return false;
4613}
4614
4615static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4616 u16 len)
4617{
4618 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004619 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4620 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004621 u16 irk_count, expected_len;
4622 int i, err;
4623
4624 BT_DBG("request for %s", hdev->name);
4625
4626 if (!lmp_le_capable(hdev))
4627 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4628 MGMT_STATUS_NOT_SUPPORTED);
4629
4630 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004631 if (irk_count > max_irk_count) {
4632 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4633 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4634 MGMT_STATUS_INVALID_PARAMS);
4635 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004636
4637 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4638 if (expected_len != len) {
4639 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004640 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004641 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4642 MGMT_STATUS_INVALID_PARAMS);
4643 }
4644
4645 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4646
4647 for (i = 0; i < irk_count; i++) {
4648 struct mgmt_irk_info *key = &cp->irks[i];
4649
4650 if (!irk_is_valid(key))
4651 return cmd_status(sk, hdev->id,
4652 MGMT_OP_LOAD_IRKS,
4653 MGMT_STATUS_INVALID_PARAMS);
4654 }
4655
4656 hci_dev_lock(hdev);
4657
4658 hci_smp_irks_clear(hdev);
4659
4660 for (i = 0; i < irk_count; i++) {
4661 struct mgmt_irk_info *irk = &cp->irks[i];
4662 u8 addr_type;
4663
4664 if (irk->addr.type == BDADDR_LE_PUBLIC)
4665 addr_type = ADDR_LE_DEV_PUBLIC;
4666 else
4667 addr_type = ADDR_LE_DEV_RANDOM;
4668
4669 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4670 BDADDR_ANY);
4671 }
4672
4673 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4674
4675 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4676
4677 hci_dev_unlock(hdev);
4678
4679 return err;
4680}
4681
Johan Hedberg3f706b72013-01-20 14:27:16 +02004682static bool ltk_is_valid(struct mgmt_ltk_info *key)
4683{
4684 if (key->master != 0x00 && key->master != 0x01)
4685 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004686
4687 switch (key->addr.type) {
4688 case BDADDR_LE_PUBLIC:
4689 return true;
4690
4691 case BDADDR_LE_RANDOM:
4692 /* Two most significant bits shall be set */
4693 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4694 return false;
4695 return true;
4696 }
4697
4698 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004699}
4700
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004701static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004702 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004703{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004704 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004705 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4706 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004707 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004708 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004709
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004710 BT_DBG("request for %s", hdev->name);
4711
4712 if (!lmp_le_capable(hdev))
4713 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4714 MGMT_STATUS_NOT_SUPPORTED);
4715
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004716 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004717 if (key_count > max_key_count) {
4718 BT_ERR("load_ltks: too big key_count value %u", key_count);
4719 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4720 MGMT_STATUS_INVALID_PARAMS);
4721 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004722
4723 expected_len = sizeof(*cp) + key_count *
4724 sizeof(struct mgmt_ltk_info);
4725 if (expected_len != len) {
4726 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004727 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004728 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004729 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004730 }
4731
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004732 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004733
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004734 for (i = 0; i < key_count; i++) {
4735 struct mgmt_ltk_info *key = &cp->keys[i];
4736
Johan Hedberg3f706b72013-01-20 14:27:16 +02004737 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004738 return cmd_status(sk, hdev->id,
4739 MGMT_OP_LOAD_LONG_TERM_KEYS,
4740 MGMT_STATUS_INVALID_PARAMS);
4741 }
4742
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004743 hci_dev_lock(hdev);
4744
4745 hci_smp_ltks_clear(hdev);
4746
4747 for (i = 0; i < key_count; i++) {
4748 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004749 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004750
4751 if (key->addr.type == BDADDR_LE_PUBLIC)
4752 addr_type = ADDR_LE_DEV_PUBLIC;
4753 else
4754 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004755
4756 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004757 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004758 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004759 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004760
Johan Hedberg61b43352014-05-29 19:36:53 +03004761 switch (key->type) {
4762 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004763 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004764 break;
4765 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004766 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004767 break;
4768 default:
4769 continue;
4770 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004771
Johan Hedberg35d70272014-02-19 14:57:47 +02004772 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004773 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004774 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004775 }
4776
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004777 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4778 NULL, 0);
4779
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004780 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004781
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004782 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004783}
4784
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004785struct cmd_conn_lookup {
4786 struct hci_conn *conn;
4787 bool valid_tx_power;
4788 u8 mgmt_status;
4789};
4790
4791static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4792{
4793 struct cmd_conn_lookup *match = data;
4794 struct mgmt_cp_get_conn_info *cp;
4795 struct mgmt_rp_get_conn_info rp;
4796 struct hci_conn *conn = cmd->user_data;
4797
4798 if (conn != match->conn)
4799 return;
4800
4801 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4802
4803 memset(&rp, 0, sizeof(rp));
4804 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4805 rp.addr.type = cp->addr.type;
4806
4807 if (!match->mgmt_status) {
4808 rp.rssi = conn->rssi;
4809
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004810 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004811 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004812 rp.max_tx_power = conn->max_tx_power;
4813 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004814 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004815 rp.max_tx_power = HCI_TX_POWER_INVALID;
4816 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004817 }
4818
4819 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4820 match->mgmt_status, &rp, sizeof(rp));
4821
4822 hci_conn_drop(conn);
4823
4824 mgmt_pending_remove(cmd);
4825}
4826
4827static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4828{
4829 struct hci_cp_read_rssi *cp;
4830 struct hci_conn *conn;
4831 struct cmd_conn_lookup match;
4832 u16 handle;
4833
4834 BT_DBG("status 0x%02x", status);
4835
4836 hci_dev_lock(hdev);
4837
4838 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004839 * otherwise we assume it's not valid. At the moment we assume that
4840 * either both or none of current and max values are valid to keep code
4841 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004842 */
4843 match.valid_tx_power = !status;
4844
4845 /* Commands sent in request are either Read RSSI or Read Transmit Power
4846 * Level so we check which one was last sent to retrieve connection
4847 * handle. Both commands have handle as first parameter so it's safe to
4848 * cast data on the same command struct.
4849 *
4850 * First command sent is always Read RSSI and we fail only if it fails.
4851 * In other case we simply override error to indicate success as we
4852 * already remembered if TX power value is actually valid.
4853 */
4854 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4855 if (!cp) {
4856 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4857 status = 0;
4858 }
4859
4860 if (!cp) {
4861 BT_ERR("invalid sent_cmd in response");
4862 goto unlock;
4863 }
4864
4865 handle = __le16_to_cpu(cp->handle);
4866 conn = hci_conn_hash_lookup_handle(hdev, handle);
4867 if (!conn) {
4868 BT_ERR("unknown handle (%d) in response", handle);
4869 goto unlock;
4870 }
4871
4872 match.conn = conn;
4873 match.mgmt_status = mgmt_status(status);
4874
4875 /* Cache refresh is complete, now reply for mgmt request for given
4876 * connection only.
4877 */
4878 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4879 get_conn_info_complete, &match);
4880
4881unlock:
4882 hci_dev_unlock(hdev);
4883}
4884
4885static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4886 u16 len)
4887{
4888 struct mgmt_cp_get_conn_info *cp = data;
4889 struct mgmt_rp_get_conn_info rp;
4890 struct hci_conn *conn;
4891 unsigned long conn_info_age;
4892 int err = 0;
4893
4894 BT_DBG("%s", hdev->name);
4895
4896 memset(&rp, 0, sizeof(rp));
4897 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4898 rp.addr.type = cp->addr.type;
4899
4900 if (!bdaddr_type_is_valid(cp->addr.type))
4901 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4902 MGMT_STATUS_INVALID_PARAMS,
4903 &rp, sizeof(rp));
4904
4905 hci_dev_lock(hdev);
4906
4907 if (!hdev_is_powered(hdev)) {
4908 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4909 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4910 goto unlock;
4911 }
4912
4913 if (cp->addr.type == BDADDR_BREDR)
4914 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4915 &cp->addr.bdaddr);
4916 else
4917 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4918
4919 if (!conn || conn->state != BT_CONNECTED) {
4920 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4921 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4922 goto unlock;
4923 }
4924
4925 /* To avoid client trying to guess when to poll again for information we
4926 * calculate conn info age as random value between min/max set in hdev.
4927 */
4928 conn_info_age = hdev->conn_info_min_age +
4929 prandom_u32_max(hdev->conn_info_max_age -
4930 hdev->conn_info_min_age);
4931
4932 /* Query controller to refresh cached values if they are too old or were
4933 * never read.
4934 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004935 if (time_after(jiffies, conn->conn_info_timestamp +
4936 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004937 !conn->conn_info_timestamp) {
4938 struct hci_request req;
4939 struct hci_cp_read_tx_power req_txp_cp;
4940 struct hci_cp_read_rssi req_rssi_cp;
4941 struct pending_cmd *cmd;
4942
4943 hci_req_init(&req, hdev);
4944 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4945 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4946 &req_rssi_cp);
4947
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004948 /* For LE links TX power does not change thus we don't need to
4949 * query for it once value is known.
4950 */
4951 if (!bdaddr_type_is_le(cp->addr.type) ||
4952 conn->tx_power == HCI_TX_POWER_INVALID) {
4953 req_txp_cp.handle = cpu_to_le16(conn->handle);
4954 req_txp_cp.type = 0x00;
4955 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4956 sizeof(req_txp_cp), &req_txp_cp);
4957 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004958
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004959 /* Max TX power needs to be read only once per connection */
4960 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4961 req_txp_cp.handle = cpu_to_le16(conn->handle);
4962 req_txp_cp.type = 0x01;
4963 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4964 sizeof(req_txp_cp), &req_txp_cp);
4965 }
4966
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004967 err = hci_req_run(&req, conn_info_refresh_complete);
4968 if (err < 0)
4969 goto unlock;
4970
4971 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4972 data, len);
4973 if (!cmd) {
4974 err = -ENOMEM;
4975 goto unlock;
4976 }
4977
4978 hci_conn_hold(conn);
4979 cmd->user_data = conn;
4980
4981 conn->conn_info_timestamp = jiffies;
4982 } else {
4983 /* Cache is valid, just reply with values cached in hci_conn */
4984 rp.rssi = conn->rssi;
4985 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004986 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004987
4988 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4989 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4990 }
4991
4992unlock:
4993 hci_dev_unlock(hdev);
4994 return err;
4995}
4996
Johan Hedberg95868422014-06-28 17:54:07 +03004997static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4998{
4999 struct mgmt_cp_get_clock_info *cp;
5000 struct mgmt_rp_get_clock_info rp;
5001 struct hci_cp_read_clock *hci_cp;
5002 struct pending_cmd *cmd;
5003 struct hci_conn *conn;
5004
5005 BT_DBG("%s status %u", hdev->name, status);
5006
5007 hci_dev_lock(hdev);
5008
5009 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5010 if (!hci_cp)
5011 goto unlock;
5012
5013 if (hci_cp->which) {
5014 u16 handle = __le16_to_cpu(hci_cp->handle);
5015 conn = hci_conn_hash_lookup_handle(hdev, handle);
5016 } else {
5017 conn = NULL;
5018 }
5019
5020 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5021 if (!cmd)
5022 goto unlock;
5023
5024 cp = cmd->param;
5025
5026 memset(&rp, 0, sizeof(rp));
5027 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5028
5029 if (status)
5030 goto send_rsp;
5031
5032 rp.local_clock = cpu_to_le32(hdev->clock);
5033
5034 if (conn) {
5035 rp.piconet_clock = cpu_to_le32(conn->clock);
5036 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5037 }
5038
5039send_rsp:
5040 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5041 &rp, sizeof(rp));
5042 mgmt_pending_remove(cmd);
5043 if (conn)
5044 hci_conn_drop(conn);
5045
5046unlock:
5047 hci_dev_unlock(hdev);
5048}
5049
5050static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5051 u16 len)
5052{
5053 struct mgmt_cp_get_clock_info *cp = data;
5054 struct mgmt_rp_get_clock_info rp;
5055 struct hci_cp_read_clock hci_cp;
5056 struct pending_cmd *cmd;
5057 struct hci_request req;
5058 struct hci_conn *conn;
5059 int err;
5060
5061 BT_DBG("%s", hdev->name);
5062
5063 memset(&rp, 0, sizeof(rp));
5064 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5065 rp.addr.type = cp->addr.type;
5066
5067 if (cp->addr.type != BDADDR_BREDR)
5068 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5069 MGMT_STATUS_INVALID_PARAMS,
5070 &rp, sizeof(rp));
5071
5072 hci_dev_lock(hdev);
5073
5074 if (!hdev_is_powered(hdev)) {
5075 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5076 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5077 goto unlock;
5078 }
5079
5080 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5081 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5082 &cp->addr.bdaddr);
5083 if (!conn || conn->state != BT_CONNECTED) {
5084 err = cmd_complete(sk, hdev->id,
5085 MGMT_OP_GET_CLOCK_INFO,
5086 MGMT_STATUS_NOT_CONNECTED,
5087 &rp, sizeof(rp));
5088 goto unlock;
5089 }
5090 } else {
5091 conn = NULL;
5092 }
5093
5094 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5095 if (!cmd) {
5096 err = -ENOMEM;
5097 goto unlock;
5098 }
5099
5100 hci_req_init(&req, hdev);
5101
5102 memset(&hci_cp, 0, sizeof(hci_cp));
5103 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5104
5105 if (conn) {
5106 hci_conn_hold(conn);
5107 cmd->user_data = conn;
5108
5109 hci_cp.handle = cpu_to_le16(conn->handle);
5110 hci_cp.which = 0x01; /* Piconet clock */
5111 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5112 }
5113
5114 err = hci_req_run(&req, get_clock_info_complete);
5115 if (err < 0)
5116 mgmt_pending_remove(cmd);
5117
5118unlock:
5119 hci_dev_unlock(hdev);
5120 return err;
5121}
5122
Marcel Holtmann8afef092014-06-29 22:28:34 +02005123static void device_added(struct sock *sk, struct hci_dev *hdev,
5124 bdaddr_t *bdaddr, u8 type, u8 action)
5125{
5126 struct mgmt_ev_device_added ev;
5127
5128 bacpy(&ev.addr.bdaddr, bdaddr);
5129 ev.addr.type = type;
5130 ev.action = action;
5131
5132 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5133}
5134
Marcel Holtmann2faade52014-06-29 19:44:03 +02005135static int add_device(struct sock *sk, struct hci_dev *hdev,
5136 void *data, u16 len)
5137{
5138 struct mgmt_cp_add_device *cp = data;
5139 u8 auto_conn, addr_type;
5140 int err;
5141
5142 BT_DBG("%s", hdev->name);
5143
5144 if (!bdaddr_type_is_le(cp->addr.type) ||
5145 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5146 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5147 MGMT_STATUS_INVALID_PARAMS,
5148 &cp->addr, sizeof(cp->addr));
5149
5150 if (cp->action != 0x00 && cp->action != 0x01)
5151 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5152 MGMT_STATUS_INVALID_PARAMS,
5153 &cp->addr, sizeof(cp->addr));
5154
5155 hci_dev_lock(hdev);
5156
5157 if (cp->addr.type == BDADDR_LE_PUBLIC)
5158 addr_type = ADDR_LE_DEV_PUBLIC;
5159 else
5160 addr_type = ADDR_LE_DEV_RANDOM;
5161
5162 if (cp->action)
5163 auto_conn = HCI_AUTO_CONN_ALWAYS;
5164 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005165 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005166
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005167 /* If the connection parameters don't exist for this device,
5168 * they will be created and configured with defaults.
5169 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005170 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5171 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005172 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5173 MGMT_STATUS_FAILED,
5174 &cp->addr, sizeof(cp->addr));
5175 goto unlock;
5176 }
5177
Marcel Holtmann8afef092014-06-29 22:28:34 +02005178 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5179
Marcel Holtmann2faade52014-06-29 19:44:03 +02005180 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5181 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5182
5183unlock:
5184 hci_dev_unlock(hdev);
5185 return err;
5186}
5187
Marcel Holtmann8afef092014-06-29 22:28:34 +02005188static void device_removed(struct sock *sk, struct hci_dev *hdev,
5189 bdaddr_t *bdaddr, u8 type)
5190{
5191 struct mgmt_ev_device_removed ev;
5192
5193 bacpy(&ev.addr.bdaddr, bdaddr);
5194 ev.addr.type = type;
5195
5196 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5197}
5198
Marcel Holtmann2faade52014-06-29 19:44:03 +02005199static int remove_device(struct sock *sk, struct hci_dev *hdev,
5200 void *data, u16 len)
5201{
5202 struct mgmt_cp_remove_device *cp = data;
5203 int err;
5204
5205 BT_DBG("%s", hdev->name);
5206
5207 hci_dev_lock(hdev);
5208
5209 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005210 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005211 u8 addr_type;
5212
5213 if (!bdaddr_type_is_le(cp->addr.type)) {
5214 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5215 MGMT_STATUS_INVALID_PARAMS,
5216 &cp->addr, sizeof(cp->addr));
5217 goto unlock;
5218 }
5219
5220 if (cp->addr.type == BDADDR_LE_PUBLIC)
5221 addr_type = ADDR_LE_DEV_PUBLIC;
5222 else
5223 addr_type = ADDR_LE_DEV_RANDOM;
5224
Johan Hedbergc71593d2014-07-02 17:37:28 +03005225 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5226 addr_type);
5227 if (!params) {
5228 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5229 MGMT_STATUS_INVALID_PARAMS,
5230 &cp->addr, sizeof(cp->addr));
5231 goto unlock;
5232 }
5233
5234 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5235 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5236 MGMT_STATUS_INVALID_PARAMS,
5237 &cp->addr, sizeof(cp->addr));
5238 goto unlock;
5239 }
5240
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005241 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005242 list_del(&params->list);
5243 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005244 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005245
5246 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005247 } else {
5248 if (cp->addr.type) {
5249 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5250 MGMT_STATUS_INVALID_PARAMS,
5251 &cp->addr, sizeof(cp->addr));
5252 goto unlock;
5253 }
5254
Johan Hedbergc71593d2014-07-02 17:37:28 +03005255 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005256 }
5257
5258 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5259 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5260
5261unlock:
5262 hci_dev_unlock(hdev);
5263 return err;
5264}
5265
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005266static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5267 u16 len)
5268{
5269 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005270 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5271 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005272 u16 param_count, expected_len;
5273 int i;
5274
5275 if (!lmp_le_capable(hdev))
5276 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5277 MGMT_STATUS_NOT_SUPPORTED);
5278
5279 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005280 if (param_count > max_param_count) {
5281 BT_ERR("load_conn_param: too big param_count value %u",
5282 param_count);
5283 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5284 MGMT_STATUS_INVALID_PARAMS);
5285 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005286
5287 expected_len = sizeof(*cp) + param_count *
5288 sizeof(struct mgmt_conn_param);
5289 if (expected_len != len) {
5290 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5291 expected_len, len);
5292 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5293 MGMT_STATUS_INVALID_PARAMS);
5294 }
5295
5296 BT_DBG("%s param_count %u", hdev->name, param_count);
5297
5298 hci_dev_lock(hdev);
5299
5300 hci_conn_params_clear_disabled(hdev);
5301
5302 for (i = 0; i < param_count; i++) {
5303 struct mgmt_conn_param *param = &cp->params[i];
5304 struct hci_conn_params *hci_param;
5305 u16 min, max, latency, timeout;
5306 u8 addr_type;
5307
5308 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5309 param->addr.type);
5310
5311 if (param->addr.type == BDADDR_LE_PUBLIC) {
5312 addr_type = ADDR_LE_DEV_PUBLIC;
5313 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5314 addr_type = ADDR_LE_DEV_RANDOM;
5315 } else {
5316 BT_ERR("Ignoring invalid connection parameters");
5317 continue;
5318 }
5319
5320 min = le16_to_cpu(param->min_interval);
5321 max = le16_to_cpu(param->max_interval);
5322 latency = le16_to_cpu(param->latency);
5323 timeout = le16_to_cpu(param->timeout);
5324
5325 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5326 min, max, latency, timeout);
5327
5328 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5329 BT_ERR("Ignoring invalid connection parameters");
5330 continue;
5331 }
5332
5333 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5334 addr_type);
5335 if (!hci_param) {
5336 BT_ERR("Failed to add connection parameters");
5337 continue;
5338 }
5339
5340 hci_param->conn_min_interval = min;
5341 hci_param->conn_max_interval = max;
5342 hci_param->conn_latency = latency;
5343 hci_param->supervision_timeout = timeout;
5344 }
5345
5346 hci_dev_unlock(hdev);
5347
5348 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5349}
5350
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005351static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005352 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5353 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005354 bool var_len;
5355 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005356} mgmt_handlers[] = {
5357 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005358 { read_version, false, MGMT_READ_VERSION_SIZE },
5359 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5360 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5361 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5362 { set_powered, false, MGMT_SETTING_SIZE },
5363 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5364 { set_connectable, false, MGMT_SETTING_SIZE },
5365 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5366 { set_pairable, false, MGMT_SETTING_SIZE },
5367 { set_link_security, false, MGMT_SETTING_SIZE },
5368 { set_ssp, false, MGMT_SETTING_SIZE },
5369 { set_hs, false, MGMT_SETTING_SIZE },
5370 { set_le, false, MGMT_SETTING_SIZE },
5371 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5372 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5373 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5374 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5375 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5376 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5377 { disconnect, false, MGMT_DISCONNECT_SIZE },
5378 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5379 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5380 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5381 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5382 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5383 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5384 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5385 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5386 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5387 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5388 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5389 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005390 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005391 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5392 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5393 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5394 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5395 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5396 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005397 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005398 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005399 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005400 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005401 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005402 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005403 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005404 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005405 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005406 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005407 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005408 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5409 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005410 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5411 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005412 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005413};
5414
Johan Hedberg03811012010-12-08 00:21:06 +02005415int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5416{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005417 void *buf;
5418 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005419 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005420 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005421 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005422 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005423 int err;
5424
5425 BT_DBG("got %zu bytes", msglen);
5426
5427 if (msglen < sizeof(*hdr))
5428 return -EINVAL;
5429
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005430 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005431 if (!buf)
5432 return -ENOMEM;
5433
5434 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5435 err = -EFAULT;
5436 goto done;
5437 }
5438
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005439 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005440 opcode = __le16_to_cpu(hdr->opcode);
5441 index = __le16_to_cpu(hdr->index);
5442 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005443
5444 if (len != msglen - sizeof(*hdr)) {
5445 err = -EINVAL;
5446 goto done;
5447 }
5448
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005449 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005450 hdev = hci_dev_get(index);
5451 if (!hdev) {
5452 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005453 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005454 goto done;
5455 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005456
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005457 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005458 test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) ||
5459 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005460 err = cmd_status(sk, index, opcode,
5461 MGMT_STATUS_INVALID_INDEX);
5462 goto done;
5463 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005464 }
5465
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005466 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005467 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005468 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005469 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005470 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005471 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005472 }
5473
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005474 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5475 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5476 err = cmd_status(sk, index, opcode,
5477 MGMT_STATUS_INVALID_INDEX);
5478 goto done;
5479 }
5480
5481 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5482 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005483 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005484 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005485 goto done;
5486 }
5487
Johan Hedbergbe22b542012-03-01 22:24:41 +02005488 handler = &mgmt_handlers[opcode];
5489
5490 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005491 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005492 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005493 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005494 goto done;
5495 }
5496
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005497 if (hdev)
5498 mgmt_init_hdev(sk, hdev);
5499
5500 cp = buf + sizeof(*hdr);
5501
Johan Hedbergbe22b542012-03-01 22:24:41 +02005502 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005503 if (err < 0)
5504 goto done;
5505
Johan Hedberg03811012010-12-08 00:21:06 +02005506 err = msglen;
5507
5508done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005509 if (hdev)
5510 hci_dev_put(hdev);
5511
Johan Hedberg03811012010-12-08 00:21:06 +02005512 kfree(buf);
5513 return err;
5514}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005515
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005516void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005517{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005518 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005519 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005520
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005521 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5522 return;
5523
5524 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5525 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5526 else
5527 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005528}
5529
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005530void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005531{
Johan Hedberg5f159032012-03-02 03:13:19 +02005532 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005533
Marcel Holtmann1514b892013-10-06 08:25:01 -07005534 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005535 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005536
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005537 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5538 return;
5539
Johan Hedberg744cf192011-11-08 20:40:14 +02005540 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005541
Marcel Holtmannedd38962014-07-02 21:30:55 +02005542 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5543 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5544 else
5545 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005546}
5547
Andre Guedes6046dc32014-02-26 20:21:51 -03005548/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005549static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005550{
5551 struct hci_conn_params *p;
5552
5553 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005554 /* Needed for AUTO_OFF case where might not "really"
5555 * have been powered off.
5556 */
5557 list_del_init(&p->action);
5558
5559 switch (p->auto_connect) {
5560 case HCI_AUTO_CONN_ALWAYS:
5561 list_add(&p->action, &hdev->pend_le_conns);
5562 break;
5563 case HCI_AUTO_CONN_REPORT:
5564 list_add(&p->action, &hdev->pend_le_reports);
5565 break;
5566 default:
5567 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005568 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005569 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005570
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005571 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005572}
5573
Johan Hedberg229ab392013-03-15 17:06:53 -05005574static void powered_complete(struct hci_dev *hdev, u8 status)
5575{
5576 struct cmd_lookup match = { NULL, hdev };
5577
5578 BT_DBG("status 0x%02x", status);
5579
5580 hci_dev_lock(hdev);
5581
Johan Hedbergd7347f32014-07-04 12:37:23 +03005582 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005583
Johan Hedberg229ab392013-03-15 17:06:53 -05005584 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5585
5586 new_settings(hdev, match.sk);
5587
5588 hci_dev_unlock(hdev);
5589
5590 if (match.sk)
5591 sock_put(match.sk);
5592}
5593
Johan Hedberg70da6242013-03-15 17:06:51 -05005594static int powered_update_hci(struct hci_dev *hdev)
5595{
Johan Hedberg890ea892013-03-15 17:06:52 -05005596 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005597 u8 link_sec;
5598
Johan Hedberg890ea892013-03-15 17:06:52 -05005599 hci_req_init(&req, hdev);
5600
Johan Hedberg70da6242013-03-15 17:06:51 -05005601 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5602 !lmp_host_ssp_capable(hdev)) {
5603 u8 ssp = 1;
5604
Johan Hedberg890ea892013-03-15 17:06:52 -05005605 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005606 }
5607
Johan Hedbergc73eee92013-04-19 18:35:21 +03005608 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5609 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005610 struct hci_cp_write_le_host_supported cp;
5611
5612 cp.le = 1;
5613 cp.simul = lmp_le_br_capable(hdev);
5614
5615 /* Check first if we already have the right
5616 * host state (host features set)
5617 */
5618 if (cp.le != lmp_host_le_capable(hdev) ||
5619 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005620 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5621 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005622 }
5623
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005624 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005625 /* Make sure the controller has a good default for
5626 * advertising data. This also applies to the case
5627 * where BR/EDR was toggled during the AUTO_OFF phase.
5628 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005629 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005630 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005631 update_scan_rsp_data(&req);
5632 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005633
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005634 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5635 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005636 }
5637
Johan Hedberg70da6242013-03-15 17:06:51 -05005638 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5639 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005640 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5641 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005642
5643 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005644 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5645 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005646 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005647 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005648 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005649 }
5650
Johan Hedberg229ab392013-03-15 17:06:53 -05005651 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005652}
5653
Johan Hedberg744cf192011-11-08 20:40:14 +02005654int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005655{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005656 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005657 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5658 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005659 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005660
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005661 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5662 return 0;
5663
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005664 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005665 if (powered_update_hci(hdev) == 0)
5666 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005667
Johan Hedberg229ab392013-03-15 17:06:53 -05005668 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5669 &match);
5670 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005671 }
5672
Johan Hedberg229ab392013-03-15 17:06:53 -05005673 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5674 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5675
5676 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5677 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5678 zero_cod, sizeof(zero_cod), NULL);
5679
5680new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005681 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005682
5683 if (match.sk)
5684 sock_put(match.sk);
5685
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005686 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005687}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005688
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005689void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005690{
5691 struct pending_cmd *cmd;
5692 u8 status;
5693
5694 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5695 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005696 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005697
5698 if (err == -ERFKILL)
5699 status = MGMT_STATUS_RFKILLED;
5700 else
5701 status = MGMT_STATUS_FAILED;
5702
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005703 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005704
5705 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005706}
5707
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005708void mgmt_discoverable_timeout(struct hci_dev *hdev)
5709{
5710 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005711
5712 hci_dev_lock(hdev);
5713
5714 /* When discoverable timeout triggers, then just make sure
5715 * the limited discoverable flag is cleared. Even in the case
5716 * of a timeout triggered from general discoverable, it is
5717 * safe to unconditionally clear the flag.
5718 */
5719 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005720 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005721
5722 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005723 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5724 u8 scan = SCAN_PAGE;
5725 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5726 sizeof(scan), &scan);
5727 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005728 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005729 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005730 hci_req_run(&req, NULL);
5731
5732 hdev->discov_timeout = 0;
5733
Johan Hedberg9a43e252013-10-20 19:00:07 +03005734 new_settings(hdev, NULL);
5735
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005736 hci_dev_unlock(hdev);
5737}
5738
Marcel Holtmann86a75642013-10-15 06:33:54 -07005739void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005740{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005741 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005742
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005743 /* Nothing needed here if there's a pending command since that
5744 * commands request completion callback takes care of everything
5745 * necessary.
5746 */
5747 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005748 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005749
Johan Hedbergbd107992014-02-24 14:52:19 +02005750 /* Powering off may clear the scan mode - don't let that interfere */
5751 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5752 return;
5753
Johan Hedberg9a43e252013-10-20 19:00:07 +03005754 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005755 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005756 } else {
5757 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005758 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005759 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005760
Johan Hedberg9a43e252013-10-20 19:00:07 +03005761 if (changed) {
5762 struct hci_request req;
5763
5764 /* In case this change in discoverable was triggered by
5765 * a disabling of connectable there could be a need to
5766 * update the advertising flags.
5767 */
5768 hci_req_init(&req, hdev);
5769 update_adv_data(&req);
5770 hci_req_run(&req, NULL);
5771
Marcel Holtmann86a75642013-10-15 06:33:54 -07005772 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005773 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005774}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005775
Marcel Holtmanna3309162013-10-15 06:33:55 -07005776void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005777{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005778 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005779
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005780 /* Nothing needed here if there's a pending command since that
5781 * commands request completion callback takes care of everything
5782 * necessary.
5783 */
5784 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005785 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005786
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005787 /* Powering off may clear the scan mode - don't let that interfere */
5788 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5789 return;
5790
Marcel Holtmanna3309162013-10-15 06:33:55 -07005791 if (connectable)
5792 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5793 else
5794 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005795
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005796 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005797 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005798}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005799
Johan Hedberg778b2352014-02-24 14:52:17 +02005800void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5801{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005802 /* Powering off may stop advertising - don't let that interfere */
5803 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5804 return;
5805
Johan Hedberg778b2352014-02-24 14:52:17 +02005806 if (advertising)
5807 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5808 else
5809 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5810}
5811
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005812void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005813{
Johan Hedbergca69b792011-11-11 18:10:00 +02005814 u8 mgmt_err = mgmt_status(status);
5815
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005816 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005817 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005818 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005819
5820 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005821 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005822 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005823}
5824
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005825void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5826 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005827{
Johan Hedberg86742e12011-11-07 23:13:38 +02005828 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005829
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005830 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005831
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005832 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005833 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005834 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005835 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005836 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005837 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005838
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005839 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005840}
Johan Hedbergf7520542011-01-20 12:34:39 +02005841
Johan Hedbergd7b25452014-05-23 13:19:53 +03005842static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5843{
5844 if (ltk->authenticated)
5845 return MGMT_LTK_AUTHENTICATED;
5846
5847 return MGMT_LTK_UNAUTHENTICATED;
5848}
5849
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005850void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005851{
5852 struct mgmt_ev_new_long_term_key ev;
5853
5854 memset(&ev, 0, sizeof(ev));
5855
Marcel Holtmann5192d302014-02-19 17:11:58 -08005856 /* Devices using resolvable or non-resolvable random addresses
5857 * without providing an indentity resolving key don't require
5858 * to store long term keys. Their addresses will change the
5859 * next time around.
5860 *
5861 * Only when a remote device provides an identity address
5862 * make sure the long term key is stored. If the remote
5863 * identity is known, the long term keys are internally
5864 * mapped to the identity address. So allow static random
5865 * and public addresses here.
5866 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005867 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5868 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5869 ev.store_hint = 0x00;
5870 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005871 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005872
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005873 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005874 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005875 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005876 ev.key.enc_size = key->enc_size;
5877 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005878 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005879
Johan Hedberg2ceba532014-06-16 19:25:16 +03005880 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005881 ev.key.master = 1;
5882
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005883 memcpy(ev.key.val, key->val, sizeof(key->val));
5884
Marcel Holtmann083368f2013-10-15 14:26:29 -07005885 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005886}
5887
Johan Hedberg95fbac82014-02-19 15:18:31 +02005888void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5889{
5890 struct mgmt_ev_new_irk ev;
5891
5892 memset(&ev, 0, sizeof(ev));
5893
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005894 /* For identity resolving keys from devices that are already
5895 * using a public address or static random address, do not
5896 * ask for storing this key. The identity resolving key really
5897 * is only mandatory for devices using resovlable random
5898 * addresses.
5899 *
5900 * Storing all identity resolving keys has the downside that
5901 * they will be also loaded on next boot of they system. More
5902 * identity resolving keys, means more time during scanning is
5903 * needed to actually resolve these addresses.
5904 */
5905 if (bacmp(&irk->rpa, BDADDR_ANY))
5906 ev.store_hint = 0x01;
5907 else
5908 ev.store_hint = 0x00;
5909
Johan Hedberg95fbac82014-02-19 15:18:31 +02005910 bacpy(&ev.rpa, &irk->rpa);
5911 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5912 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5913 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5914
5915 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5916}
5917
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005918void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5919 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005920{
5921 struct mgmt_ev_new_csrk ev;
5922
5923 memset(&ev, 0, sizeof(ev));
5924
5925 /* Devices using resolvable or non-resolvable random addresses
5926 * without providing an indentity resolving key don't require
5927 * to store signature resolving keys. Their addresses will change
5928 * the next time around.
5929 *
5930 * Only when a remote device provides an identity address
5931 * make sure the signature resolving key is stored. So allow
5932 * static random and public addresses here.
5933 */
5934 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5935 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5936 ev.store_hint = 0x00;
5937 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005938 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005939
5940 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5941 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5942 ev.key.master = csrk->master;
5943 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5944
5945 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5946}
5947
Andre Guedesffb5a8272014-07-01 18:10:11 -03005948void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03005949 u8 bdaddr_type, u8 store_hint, u16 min_interval,
5950 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03005951{
5952 struct mgmt_ev_new_conn_param ev;
5953
Johan Hedbergc103aea2014-07-02 17:37:34 +03005954 if (!hci_is_identity_address(bdaddr, bdaddr_type))
5955 return;
5956
Andre Guedesffb5a8272014-07-01 18:10:11 -03005957 memset(&ev, 0, sizeof(ev));
5958 bacpy(&ev.addr.bdaddr, bdaddr);
5959 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03005960 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03005961 ev.min_interval = cpu_to_le16(min_interval);
5962 ev.max_interval = cpu_to_le16(max_interval);
5963 ev.latency = cpu_to_le16(latency);
5964 ev.timeout = cpu_to_le16(timeout);
5965
5966 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5967}
5968
Marcel Holtmann94933992013-10-15 10:26:39 -07005969static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5970 u8 data_len)
5971{
5972 eir[eir_len++] = sizeof(type) + data_len;
5973 eir[eir_len++] = type;
5974 memcpy(&eir[eir_len], data, data_len);
5975 eir_len += data_len;
5976
5977 return eir_len;
5978}
5979
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005980void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5981 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5982 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005983{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005984 char buf[512];
5985 struct mgmt_ev_device_connected *ev = (void *) buf;
5986 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005987
Johan Hedbergb644ba32012-01-17 21:48:47 +02005988 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005989 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005990
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005991 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005992
Johan Hedbergb644ba32012-01-17 21:48:47 +02005993 if (name_len > 0)
5994 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005995 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005996
5997 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005998 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005999 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006000
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006001 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006002
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006003 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6004 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006005}
6006
Johan Hedberg8962ee72011-01-20 12:40:27 +02006007static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6008{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006009 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006010 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006011 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006012
Johan Hedberg88c3df12012-02-09 14:27:38 +02006013 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6014 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006015
Johan Hedbergaee9b212012-02-18 15:07:59 +02006016 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006017 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006018
6019 *sk = cmd->sk;
6020 sock_hold(*sk);
6021
Johan Hedberga664b5b2011-02-19 12:06:02 -03006022 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006023}
6024
Johan Hedberg124f6e32012-02-09 13:50:12 +02006025static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006026{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006027 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006028 struct mgmt_cp_unpair_device *cp = cmd->param;
6029 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006030
6031 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006032 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6033 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006034
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006035 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6036
Johan Hedbergaee9b212012-02-18 15:07:59 +02006037 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006038
6039 mgmt_pending_remove(cmd);
6040}
6041
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006042void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006043 u8 link_type, u8 addr_type, u8 reason,
6044 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006045{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006046 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006047 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006048 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006049
Johan Hedberg8b064a32014-02-24 14:52:22 +02006050 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6051 if (power_off) {
6052 struct mgmt_mode *cp = power_off->param;
6053
6054 /* The connection is still in hci_conn_hash so test for 1
6055 * instead of 0 to know if this is the last one.
6056 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006057 if (!cp->val && hci_conn_count(hdev) == 1) {
6058 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006059 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006060 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006061 }
6062
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006063 if (!mgmt_connected)
6064 return;
6065
Andre Guedes57eb7762013-10-30 19:01:41 -03006066 if (link_type != ACL_LINK && link_type != LE_LINK)
6067 return;
6068
Johan Hedberg744cf192011-11-08 20:40:14 +02006069 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006070
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006071 bacpy(&ev.addr.bdaddr, bdaddr);
6072 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6073 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006074
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006075 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006076
6077 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006078 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006079
Johan Hedberg124f6e32012-02-09 13:50:12 +02006080 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006081 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006082}
6083
Marcel Holtmann78929242013-10-06 23:55:47 -07006084void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6085 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006086{
Andre Guedes3655bba2013-10-30 19:01:40 -03006087 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6088 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006089 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006090 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006091
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006092 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6093 hdev);
6094
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006095 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006096 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006097 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006098
Andre Guedes3655bba2013-10-30 19:01:40 -03006099 cp = cmd->param;
6100
6101 if (bacmp(bdaddr, &cp->addr.bdaddr))
6102 return;
6103
6104 if (cp->addr.type != bdaddr_type)
6105 return;
6106
Johan Hedberg88c3df12012-02-09 14:27:38 +02006107 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006108 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006109
Marcel Holtmann78929242013-10-06 23:55:47 -07006110 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6111 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006112
Johan Hedberga664b5b2011-02-19 12:06:02 -03006113 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006114}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006115
Marcel Holtmann445608d2013-10-06 23:55:48 -07006116void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6117 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006118{
6119 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006120 struct pending_cmd *power_off;
6121
6122 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6123 if (power_off) {
6124 struct mgmt_mode *cp = power_off->param;
6125
6126 /* The connection is still in hci_conn_hash so test for 1
6127 * instead of 0 to know if this is the last one.
6128 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006129 if (!cp->val && hci_conn_count(hdev) == 1) {
6130 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006131 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006132 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006133 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006134
Johan Hedberg4c659c32011-11-07 23:13:39 +02006135 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006136 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006137 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006138
Marcel Holtmann445608d2013-10-06 23:55:48 -07006139 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006140}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006141
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006142void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006143{
6144 struct mgmt_ev_pin_code_request ev;
6145
Johan Hedbergd8457692012-02-17 14:24:57 +02006146 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006147 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006148 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006149
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006150 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006151}
6152
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006153void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6154 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006155{
6156 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006157 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006158
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006159 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006160 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006161 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006162
Johan Hedbergd8457692012-02-17 14:24:57 +02006163 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006164 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006165
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006166 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6167 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006168
Johan Hedberga664b5b2011-02-19 12:06:02 -03006169 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006170}
6171
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006172void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6173 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006174{
6175 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006176 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006177
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006178 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006179 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006180 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006181
Johan Hedbergd8457692012-02-17 14:24:57 +02006182 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006183 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006184
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006185 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6186 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006187
Johan Hedberga664b5b2011-02-19 12:06:02 -03006188 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006189}
Johan Hedberga5c29682011-02-19 12:05:57 -03006190
Johan Hedberg744cf192011-11-08 20:40:14 +02006191int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006192 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006193 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006194{
6195 struct mgmt_ev_user_confirm_request ev;
6196
Johan Hedberg744cf192011-11-08 20:40:14 +02006197 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006198
Johan Hedberg272d90d2012-02-09 15:26:12 +02006199 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006200 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006201 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006202 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006203
Johan Hedberg744cf192011-11-08 20:40:14 +02006204 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006205 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006206}
6207
Johan Hedberg272d90d2012-02-09 15:26:12 +02006208int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006209 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006210{
6211 struct mgmt_ev_user_passkey_request ev;
6212
6213 BT_DBG("%s", hdev->name);
6214
Johan Hedberg272d90d2012-02-09 15:26:12 +02006215 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006216 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006217
6218 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006219 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006220}
6221
Brian Gix0df4c182011-11-16 13:53:13 -08006222static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006223 u8 link_type, u8 addr_type, u8 status,
6224 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006225{
6226 struct pending_cmd *cmd;
6227 struct mgmt_rp_user_confirm_reply rp;
6228 int err;
6229
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006230 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006231 if (!cmd)
6232 return -ENOENT;
6233
Johan Hedberg272d90d2012-02-09 15:26:12 +02006234 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006235 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006236 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006237 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006238
Johan Hedberga664b5b2011-02-19 12:06:02 -03006239 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006240
6241 return err;
6242}
6243
Johan Hedberg744cf192011-11-08 20:40:14 +02006244int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006245 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006246{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006247 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006248 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006249}
6250
Johan Hedberg272d90d2012-02-09 15:26:12 +02006251int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006252 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006253{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006254 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006255 status,
6256 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006257}
Johan Hedberg2a611692011-02-19 12:06:00 -03006258
Brian Gix604086b2011-11-23 08:28:33 -08006259int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006260 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006261{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006262 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006263 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006264}
6265
Johan Hedberg272d90d2012-02-09 15:26:12 +02006266int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006267 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006268{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006269 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006270 status,
6271 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006272}
6273
Johan Hedberg92a25252012-09-06 18:39:26 +03006274int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6275 u8 link_type, u8 addr_type, u32 passkey,
6276 u8 entered)
6277{
6278 struct mgmt_ev_passkey_notify ev;
6279
6280 BT_DBG("%s", hdev->name);
6281
6282 bacpy(&ev.addr.bdaddr, bdaddr);
6283 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6284 ev.passkey = __cpu_to_le32(passkey);
6285 ev.entered = entered;
6286
6287 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6288}
6289
Marcel Holtmanne5460992013-10-15 14:26:23 -07006290void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6291 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006292{
6293 struct mgmt_ev_auth_failed ev;
6294
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006295 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006296 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006297 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006298
Marcel Holtmanne5460992013-10-15 14:26:23 -07006299 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006300}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006301
Marcel Holtmann464996a2013-10-15 14:26:24 -07006302void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006303{
6304 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006305 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006306
6307 if (status) {
6308 u8 mgmt_err = mgmt_status(status);
6309 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006310 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006311 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006312 }
6313
Marcel Holtmann464996a2013-10-15 14:26:24 -07006314 if (test_bit(HCI_AUTH, &hdev->flags))
6315 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6316 &hdev->dev_flags);
6317 else
6318 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6319 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006320
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006321 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006322 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006323
Johan Hedberg47990ea2012-02-22 11:58:37 +02006324 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006325 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006326
6327 if (match.sk)
6328 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006329}
6330
Johan Hedberg890ea892013-03-15 17:06:52 -05006331static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006332{
Johan Hedberg890ea892013-03-15 17:06:52 -05006333 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006334 struct hci_cp_write_eir cp;
6335
Johan Hedberg976eb202012-10-24 21:12:01 +03006336 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006337 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006338
Johan Hedbergc80da272012-02-22 15:38:48 +02006339 memset(hdev->eir, 0, sizeof(hdev->eir));
6340
Johan Hedbergcacaf522012-02-21 00:52:42 +02006341 memset(&cp, 0, sizeof(cp));
6342
Johan Hedberg890ea892013-03-15 17:06:52 -05006343 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006344}
6345
Marcel Holtmann3e248562013-10-15 14:26:25 -07006346void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006347{
6348 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006349 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006350 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006351
6352 if (status) {
6353 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006354
6355 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006356 &hdev->dev_flags)) {
6357 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006358 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006359 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006360
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006361 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6362 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006363 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006364 }
6365
6366 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006367 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006368 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006369 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6370 if (!changed)
6371 changed = test_and_clear_bit(HCI_HS_ENABLED,
6372 &hdev->dev_flags);
6373 else
6374 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006375 }
6376
6377 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6378
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006379 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006380 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006381
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006382 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006383 sock_put(match.sk);
6384
Johan Hedberg890ea892013-03-15 17:06:52 -05006385 hci_req_init(&req, hdev);
6386
Johan Hedberg37699722014-06-24 14:00:27 +03006387 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6388 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6389 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6390 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006391 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006392 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006393 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006394 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006395
6396 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006397}
6398
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006399void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6400{
6401 struct cmd_lookup match = { NULL, hdev };
6402 bool changed = false;
6403
6404 if (status) {
6405 u8 mgmt_err = mgmt_status(status);
6406
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006407 if (enable) {
6408 if (test_and_clear_bit(HCI_SC_ENABLED,
6409 &hdev->dev_flags))
6410 new_settings(hdev, NULL);
6411 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6412 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006413
6414 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6415 cmd_status_rsp, &mgmt_err);
6416 return;
6417 }
6418
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006419 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006420 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006421 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006422 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006423 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6424 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006425
6426 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6427 settings_rsp, &match);
6428
6429 if (changed)
6430 new_settings(hdev, match.sk);
6431
6432 if (match.sk)
6433 sock_put(match.sk);
6434}
6435
Johan Hedberg92da6092013-03-15 17:06:55 -05006436static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006437{
6438 struct cmd_lookup *match = data;
6439
Johan Hedberg90e70452012-02-23 23:09:40 +02006440 if (match->sk == NULL) {
6441 match->sk = cmd->sk;
6442 sock_hold(match->sk);
6443 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006444}
6445
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006446void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6447 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006448{
Johan Hedberg90e70452012-02-23 23:09:40 +02006449 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006450
Johan Hedberg92da6092013-03-15 17:06:55 -05006451 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6452 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6453 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006454
6455 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006456 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6457 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006458
6459 if (match.sk)
6460 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006461}
6462
Marcel Holtmann7667da32013-10-15 14:26:27 -07006463void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006464{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006465 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006466 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006467
Johan Hedberg13928972013-03-15 17:07:00 -05006468 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006469 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006470
6471 memset(&ev, 0, sizeof(ev));
6472 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006473 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006474
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006475 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006476 if (!cmd) {
6477 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006478
Johan Hedberg13928972013-03-15 17:07:00 -05006479 /* If this is a HCI command related to powering on the
6480 * HCI dev don't send any mgmt signals.
6481 */
6482 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006483 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006484 }
6485
Marcel Holtmann7667da32013-10-15 14:26:27 -07006486 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6487 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006488}
Szymon Jancc35938b2011-03-22 13:12:21 +01006489
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006490void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6491 u8 *randomizer192, u8 *hash256,
6492 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006493{
6494 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006495
Johan Hedberg744cf192011-11-08 20:40:14 +02006496 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006497
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006498 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006499 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006500 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006501
6502 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006503 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6504 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006505 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006506 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6507 hash256 && randomizer256) {
6508 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006509
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006510 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6511 memcpy(rp.randomizer192, randomizer192,
6512 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006513
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006514 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6515 memcpy(rp.randomizer256, randomizer256,
6516 sizeof(rp.randomizer256));
6517
6518 cmd_complete(cmd->sk, hdev->id,
6519 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6520 &rp, sizeof(rp));
6521 } else {
6522 struct mgmt_rp_read_local_oob_data rp;
6523
6524 memcpy(rp.hash, hash192, sizeof(rp.hash));
6525 memcpy(rp.randomizer, randomizer192,
6526 sizeof(rp.randomizer));
6527
6528 cmd_complete(cmd->sk, hdev->id,
6529 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6530 &rp, sizeof(rp));
6531 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006532 }
6533
6534 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006535}
Johan Hedberge17acd42011-03-30 23:57:16 +03006536
Marcel Holtmann901801b2013-10-06 23:55:51 -07006537void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006538 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6539 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006540{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006541 char buf[512];
6542 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006543 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006544 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006545
Johan Hedberg75ce2082014-07-02 22:42:01 +03006546 /* Don't send events for a non-kernel initiated discovery. With
6547 * LE one exception is if we have pend_le_reports > 0 in which
6548 * case we're doing passive scanning and want these events.
6549 */
6550 if (!hci_discovery_active(hdev)) {
6551 if (link_type == ACL_LINK)
6552 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006553 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006554 return;
6555 }
Andre Guedes12602d02013-04-30 15:29:40 -03006556
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006557 /* Make sure that the buffer is big enough. The 5 extra bytes
6558 * are for the potential CoD field.
6559 */
6560 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006561 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006562
Johan Hedberg1dc06092012-01-15 21:01:23 +02006563 memset(buf, 0, sizeof(buf));
6564
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006565 irk = hci_get_irk(hdev, bdaddr, addr_type);
6566 if (irk) {
6567 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6568 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6569 } else {
6570 bacpy(&ev->addr.bdaddr, bdaddr);
6571 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6572 }
6573
Johan Hedberge319d2e2012-01-15 19:51:59 +02006574 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006575 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006576
Johan Hedberg1dc06092012-01-15 21:01:23 +02006577 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006578 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006579
Johan Hedberg1dc06092012-01-15 21:01:23 +02006580 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6581 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006582 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006583
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006584 if (scan_rsp_len > 0)
6585 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6586
6587 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6588 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006589
Marcel Holtmann901801b2013-10-06 23:55:51 -07006590 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006591}
Johan Hedberga88a9652011-03-30 13:18:12 +03006592
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006593void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6594 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006595{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006596 struct mgmt_ev_device_found *ev;
6597 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6598 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006599
Johan Hedbergb644ba32012-01-17 21:48:47 +02006600 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006601
Johan Hedbergb644ba32012-01-17 21:48:47 +02006602 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006603
Johan Hedbergb644ba32012-01-17 21:48:47 +02006604 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006605 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006606 ev->rssi = rssi;
6607
6608 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006609 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006610
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006611 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006612
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006613 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006614}
Johan Hedberg314b2382011-04-27 10:29:57 -04006615
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006616void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006617{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006618 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006619 struct pending_cmd *cmd;
6620
Andre Guedes343fb142011-11-22 17:14:19 -03006621 BT_DBG("%s discovering %u", hdev->name, discovering);
6622
Johan Hedberg164a6e72011-11-01 17:06:44 +02006623 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006624 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006625 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006626 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006627
6628 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006629 u8 type = hdev->discovery.type;
6630
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006631 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6632 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006633 mgmt_pending_remove(cmd);
6634 }
6635
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006636 memset(&ev, 0, sizeof(ev));
6637 ev.type = hdev->discovery.type;
6638 ev.discovering = discovering;
6639
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006640 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006641}
Antti Julku5e762442011-08-25 16:48:02 +03006642
Marcel Holtmann5976e602013-10-06 04:08:14 -07006643static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6644{
6645 BT_DBG("%s status %u", hdev->name, status);
6646
6647 /* Clear the advertising mgmt setting if we failed to re-enable it */
6648 if (status) {
6649 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006650 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006651 }
6652}
6653
6654void mgmt_reenable_advertising(struct hci_dev *hdev)
6655{
6656 struct hci_request req;
6657
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006658 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006659 return;
6660
6661 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6662 return;
6663
6664 hci_req_init(&req, hdev);
6665 enable_advertising(&req);
6666
6667 /* If this fails we have no option but to let user space know
6668 * that we've disabled advertising.
6669 */
6670 if (hci_req_run(&req, adv_enable_complete) < 0) {
6671 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006672 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006673 }
6674}