blob: f7217f9eda038dc6558bc01c2f591044a44d4f0c [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 Hedberge70bb2e2012-02-13 16:59:33 +020091};
92
93static const u16 mgmt_events[] = {
94 MGMT_EV_CONTROLLER_ERROR,
95 MGMT_EV_INDEX_ADDED,
96 MGMT_EV_INDEX_REMOVED,
97 MGMT_EV_NEW_SETTINGS,
98 MGMT_EV_CLASS_OF_DEV_CHANGED,
99 MGMT_EV_LOCAL_NAME_CHANGED,
100 MGMT_EV_NEW_LINK_KEY,
101 MGMT_EV_NEW_LONG_TERM_KEY,
102 MGMT_EV_DEVICE_CONNECTED,
103 MGMT_EV_DEVICE_DISCONNECTED,
104 MGMT_EV_CONNECT_FAILED,
105 MGMT_EV_PIN_CODE_REQUEST,
106 MGMT_EV_USER_CONFIRM_REQUEST,
107 MGMT_EV_USER_PASSKEY_REQUEST,
108 MGMT_EV_AUTH_FAILED,
109 MGMT_EV_DEVICE_FOUND,
110 MGMT_EV_DISCOVERING,
111 MGMT_EV_DEVICE_BLOCKED,
112 MGMT_EV_DEVICE_UNBLOCKED,
113 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300114 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800115 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700116 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200117 MGMT_EV_DEVICE_ADDED,
118 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300119 MGMT_EV_NEW_CONN_PARAM,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200120};
121
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800122#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200123
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200124#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
125 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
126
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200127struct pending_cmd {
128 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200129 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200130 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100131 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200132 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300133 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200134};
135
Johan Hedbergca69b792011-11-11 18:10:00 +0200136/* HCI to MGMT error code conversion table */
137static u8 mgmt_status_table[] = {
138 MGMT_STATUS_SUCCESS,
139 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
140 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
141 MGMT_STATUS_FAILED, /* Hardware Failure */
142 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
143 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200144 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200145 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
146 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
147 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
148 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
149 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
150 MGMT_STATUS_BUSY, /* Command Disallowed */
151 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
152 MGMT_STATUS_REJECTED, /* Rejected Security */
153 MGMT_STATUS_REJECTED, /* Rejected Personal */
154 MGMT_STATUS_TIMEOUT, /* Host Timeout */
155 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
156 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
157 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
158 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
159 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
160 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
161 MGMT_STATUS_BUSY, /* Repeated Attempts */
162 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
163 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
164 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
165 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
166 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
167 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
168 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
169 MGMT_STATUS_FAILED, /* Unspecified Error */
170 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
171 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
172 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
173 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
174 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
175 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
176 MGMT_STATUS_FAILED, /* Unit Link Key Used */
177 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
178 MGMT_STATUS_TIMEOUT, /* Instant Passed */
179 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
180 MGMT_STATUS_FAILED, /* Transaction Collision */
181 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
182 MGMT_STATUS_REJECTED, /* QoS Rejected */
183 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
184 MGMT_STATUS_REJECTED, /* Insufficient Security */
185 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
186 MGMT_STATUS_BUSY, /* Role Switch Pending */
187 MGMT_STATUS_FAILED, /* Slot Violation */
188 MGMT_STATUS_FAILED, /* Role Switch Failed */
189 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
190 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
191 MGMT_STATUS_BUSY, /* Host Busy Pairing */
192 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
193 MGMT_STATUS_BUSY, /* Controller Busy */
194 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
195 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
196 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
197 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
198 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
199};
200
201static u8 mgmt_status(u8 hci_status)
202{
203 if (hci_status < ARRAY_SIZE(mgmt_status_table))
204 return mgmt_status_table[hci_status];
205
206 return MGMT_STATUS_FAILED;
207}
208
Szymon Janc4e51eae2011-02-25 19:05:48 +0100209static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200210{
211 struct sk_buff *skb;
212 struct mgmt_hdr *hdr;
213 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300214 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200215
Szymon Janc34eb5252011-02-28 14:10:08 +0100216 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200217
Andre Guedes790eff42012-06-07 19:05:46 -0300218 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200219 if (!skb)
220 return -ENOMEM;
221
222 hdr = (void *) skb_put(skb, sizeof(*hdr));
223
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700224 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100225 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200226 hdr->len = cpu_to_le16(sizeof(*ev));
227
228 ev = (void *) skb_put(skb, sizeof(*ev));
229 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200230 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200231
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300232 err = sock_queue_rcv_skb(sk, skb);
233 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200234 kfree_skb(skb);
235
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300236 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200237}
238
Johan Hedbergaee9b212012-02-18 15:07:59 +0200239static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300240 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200241{
242 struct sk_buff *skb;
243 struct mgmt_hdr *hdr;
244 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300245 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200246
247 BT_DBG("sock %p", sk);
248
Andre Guedes790eff42012-06-07 19:05:46 -0300249 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200250 if (!skb)
251 return -ENOMEM;
252
253 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200254
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700255 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100256 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200257 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200258
Johan Hedberga38528f2011-01-22 06:46:43 +0200259 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200260 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200261 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100262
263 if (rp)
264 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200265
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300266 err = sock_queue_rcv_skb(sk, skb);
267 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200268 kfree_skb(skb);
269
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100270 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200271}
272
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300273static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
274 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200275{
276 struct mgmt_rp_read_version rp;
277
278 BT_DBG("sock %p", sk);
279
280 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700281 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200282
Johan Hedbergaee9b212012-02-18 15:07:59 +0200283 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300284 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200285}
286
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300287static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
288 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200289{
290 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200291 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
292 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200293 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200294 size_t rp_size;
295 int i, err;
296
297 BT_DBG("sock %p", sk);
298
299 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
300
301 rp = kmalloc(rp_size, GFP_KERNEL);
302 if (!rp)
303 return -ENOMEM;
304
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700305 rp->num_commands = cpu_to_le16(num_commands);
306 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200307
308 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
309 put_unaligned_le16(mgmt_commands[i], opcode);
310
311 for (i = 0; i < num_events; i++, opcode++)
312 put_unaligned_le16(mgmt_events[i], opcode);
313
Johan Hedbergaee9b212012-02-18 15:07:59 +0200314 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300315 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200316 kfree(rp);
317
318 return err;
319}
320
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300321static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
322 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200323{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200324 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200325 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200326 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200327 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300328 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200329
330 BT_DBG("sock %p", sk);
331
332 read_lock(&hci_dev_list_lock);
333
334 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300335 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700336 if (d->dev_type == HCI_BREDR)
337 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200338 }
339
Johan Hedberga38528f2011-01-22 06:46:43 +0200340 rp_len = sizeof(*rp) + (2 * count);
341 rp = kmalloc(rp_len, GFP_ATOMIC);
342 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100343 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200344 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100345 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200346
Johan Hedberg476e44c2012-10-19 20:10:46 +0300347 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200348 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200349 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200350 continue;
351
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700352 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
353 continue;
354
Marcel Holtmannfee746b2014-06-29 12:13:05 +0200355 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
356 continue;
357
Marcel Holtmann1514b892013-10-06 08:25:01 -0700358 if (d->dev_type == HCI_BREDR) {
359 rp->index[count++] = cpu_to_le16(d->id);
360 BT_DBG("Added hci%u", d->id);
361 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 }
363
Johan Hedberg476e44c2012-10-19 20:10:46 +0300364 rp->num_controllers = cpu_to_le16(count);
365 rp_len = sizeof(*rp) + (2 * count);
366
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367 read_unlock(&hci_dev_list_lock);
368
Johan Hedbergaee9b212012-02-18 15:07:59 +0200369 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300370 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200371
Johan Hedberga38528f2011-01-22 06:46:43 +0200372 kfree(rp);
373
374 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375}
376
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200377static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200378{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200379 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200380
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200381 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200382 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800383 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200384
Andre Guedesed3fa312012-07-24 15:03:46 -0300385 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300386 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500387 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
388 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300389 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200390 settings |= MGMT_SETTING_BREDR;
391 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700392
393 if (lmp_ssp_capable(hdev)) {
394 settings |= MGMT_SETTING_SSP;
395 settings |= MGMT_SETTING_HS;
396 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800397
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800398 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200399 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800400 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700401 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100402
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300403 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200404 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300405 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200406 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300407 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200408
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200409 return settings;
410}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200411
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200412static u32 get_current_settings(struct hci_dev *hdev)
413{
414 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200415
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200416 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100417 settings |= MGMT_SETTING_POWERED;
418
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200419 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200420 settings |= MGMT_SETTING_CONNECTABLE;
421
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500422 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
423 settings |= MGMT_SETTING_FAST_CONNECTABLE;
424
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200425 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200426 settings |= MGMT_SETTING_DISCOVERABLE;
427
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200428 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_PAIRABLE;
430
Johan Hedberg56f87902013-10-02 13:43:13 +0300431 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200432 settings |= MGMT_SETTING_BREDR;
433
Johan Hedberg06199cf2012-02-22 16:37:11 +0200434 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200435 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200436
Johan Hedberg47990ea2012-02-22 11:58:37 +0200437 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200438 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200439
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200440 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200441 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200442
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200443 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
444 settings |= MGMT_SETTING_HS;
445
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200446 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300447 settings |= MGMT_SETTING_ADVERTISING;
448
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800449 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
450 settings |= MGMT_SETTING_SECURE_CONN;
451
Johan Hedberg0663b292014-06-24 13:15:50 +0300452 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800453 settings |= MGMT_SETTING_DEBUG_KEYS;
454
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200455 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
456 settings |= MGMT_SETTING_PRIVACY;
457
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200458 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200459}
460
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300461#define PNP_INFO_SVCLASS_ID 0x1200
462
Johan Hedberg213202e2013-01-27 00:31:33 +0200463static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
464{
465 u8 *ptr = data, *uuids_start = NULL;
466 struct bt_uuid *uuid;
467
468 if (len < 4)
469 return ptr;
470
471 list_for_each_entry(uuid, &hdev->uuids, list) {
472 u16 uuid16;
473
474 if (uuid->size != 16)
475 continue;
476
477 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
478 if (uuid16 < 0x1100)
479 continue;
480
481 if (uuid16 == PNP_INFO_SVCLASS_ID)
482 continue;
483
484 if (!uuids_start) {
485 uuids_start = ptr;
486 uuids_start[0] = 1;
487 uuids_start[1] = EIR_UUID16_ALL;
488 ptr += 2;
489 }
490
491 /* Stop if not enough space to put next UUID */
492 if ((ptr - data) + sizeof(u16) > len) {
493 uuids_start[1] = EIR_UUID16_SOME;
494 break;
495 }
496
497 *ptr++ = (uuid16 & 0x00ff);
498 *ptr++ = (uuid16 & 0xff00) >> 8;
499 uuids_start[0] += sizeof(uuid16);
500 }
501
502 return ptr;
503}
504
Johan Hedbergcdf19632013-01-27 00:31:34 +0200505static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
506{
507 u8 *ptr = data, *uuids_start = NULL;
508 struct bt_uuid *uuid;
509
510 if (len < 6)
511 return ptr;
512
513 list_for_each_entry(uuid, &hdev->uuids, list) {
514 if (uuid->size != 32)
515 continue;
516
517 if (!uuids_start) {
518 uuids_start = ptr;
519 uuids_start[0] = 1;
520 uuids_start[1] = EIR_UUID32_ALL;
521 ptr += 2;
522 }
523
524 /* Stop if not enough space to put next UUID */
525 if ((ptr - data) + sizeof(u32) > len) {
526 uuids_start[1] = EIR_UUID32_SOME;
527 break;
528 }
529
530 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
531 ptr += sizeof(u32);
532 uuids_start[0] += sizeof(u32);
533 }
534
535 return ptr;
536}
537
Johan Hedbergc00d5752013-01-27 00:31:35 +0200538static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
539{
540 u8 *ptr = data, *uuids_start = NULL;
541 struct bt_uuid *uuid;
542
543 if (len < 18)
544 return ptr;
545
546 list_for_each_entry(uuid, &hdev->uuids, list) {
547 if (uuid->size != 128)
548 continue;
549
550 if (!uuids_start) {
551 uuids_start = ptr;
552 uuids_start[0] = 1;
553 uuids_start[1] = EIR_UUID128_ALL;
554 ptr += 2;
555 }
556
557 /* Stop if not enough space to put next UUID */
558 if ((ptr - data) + 16 > len) {
559 uuids_start[1] = EIR_UUID128_SOME;
560 break;
561 }
562
563 memcpy(ptr, uuid->uuid, 16);
564 ptr += 16;
565 uuids_start[0] += 16;
566 }
567
568 return ptr;
569}
570
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300571static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
572{
573 struct pending_cmd *cmd;
574
575 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
576 if (cmd->opcode == opcode)
577 return cmd;
578 }
579
580 return NULL;
581}
582
Johan Hedberg95868422014-06-28 17:54:07 +0300583static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
584 struct hci_dev *hdev,
585 const void *data)
586{
587 struct pending_cmd *cmd;
588
589 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
590 if (cmd->user_data != data)
591 continue;
592 if (cmd->opcode == opcode)
593 return cmd;
594 }
595
596 return NULL;
597}
598
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700599static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
600{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700601 u8 ad_len = 0;
602 size_t name_len;
603
604 name_len = strlen(hdev->dev_name);
605 if (name_len > 0) {
606 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
607
608 if (name_len > max_len) {
609 name_len = max_len;
610 ptr[1] = EIR_NAME_SHORT;
611 } else
612 ptr[1] = EIR_NAME_COMPLETE;
613
614 ptr[0] = name_len + 1;
615
616 memcpy(ptr + 2, hdev->dev_name, name_len);
617
618 ad_len += (name_len + 2);
619 ptr += (name_len + 2);
620 }
621
622 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700623}
624
625static void update_scan_rsp_data(struct hci_request *req)
626{
627 struct hci_dev *hdev = req->hdev;
628 struct hci_cp_le_set_scan_rsp_data cp;
629 u8 len;
630
Johan Hedberg7751ef12013-10-19 23:38:15 +0300631 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700632 return;
633
634 memset(&cp, 0, sizeof(cp));
635
636 len = create_scan_rsp_data(hdev, cp.data);
637
Johan Hedbergeb438b52013-10-16 15:31:07 +0300638 if (hdev->scan_rsp_data_len == len &&
639 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700640 return;
641
Johan Hedbergeb438b52013-10-16 15:31:07 +0300642 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
643 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700644
645 cp.length = len;
646
647 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
648}
649
Johan Hedberg9a43e252013-10-20 19:00:07 +0300650static u8 get_adv_discov_flags(struct hci_dev *hdev)
651{
652 struct pending_cmd *cmd;
653
654 /* If there's a pending mgmt command the flags will not yet have
655 * their final values, so check for this first.
656 */
657 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
658 if (cmd) {
659 struct mgmt_mode *cp = cmd->param;
660 if (cp->val == 0x01)
661 return LE_AD_GENERAL;
662 else if (cp->val == 0x02)
663 return LE_AD_LIMITED;
664 } else {
665 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
666 return LE_AD_LIMITED;
667 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
668 return LE_AD_GENERAL;
669 }
670
671 return 0;
672}
673
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700674static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700675{
676 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700677
Johan Hedberg9a43e252013-10-20 19:00:07 +0300678 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700679
Johan Hedberge8340042014-01-30 11:16:50 -0800680 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700681 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700682
683 if (flags) {
684 BT_DBG("adv flags 0x%02x", flags);
685
686 ptr[0] = 2;
687 ptr[1] = EIR_FLAGS;
688 ptr[2] = flags;
689
690 ad_len += 3;
691 ptr += 3;
692 }
693
694 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
695 ptr[0] = 2;
696 ptr[1] = EIR_TX_POWER;
697 ptr[2] = (u8) hdev->adv_tx_power;
698
699 ad_len += 3;
700 ptr += 3;
701 }
702
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700703 return ad_len;
704}
705
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700706static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700707{
708 struct hci_dev *hdev = req->hdev;
709 struct hci_cp_le_set_adv_data cp;
710 u8 len;
711
Johan Hedberg10994ce2013-10-19 23:38:16 +0300712 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700713 return;
714
715 memset(&cp, 0, sizeof(cp));
716
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700717 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700718
719 if (hdev->adv_data_len == len &&
720 memcmp(cp.data, hdev->adv_data, len) == 0)
721 return;
722
723 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
724 hdev->adv_data_len = len;
725
726 cp.length = len;
727
728 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
729}
730
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300731static void create_eir(struct hci_dev *hdev, u8 *data)
732{
733 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300734 size_t name_len;
735
736 name_len = strlen(hdev->dev_name);
737
738 if (name_len > 0) {
739 /* EIR Data type */
740 if (name_len > 48) {
741 name_len = 48;
742 ptr[1] = EIR_NAME_SHORT;
743 } else
744 ptr[1] = EIR_NAME_COMPLETE;
745
746 /* EIR Data length */
747 ptr[0] = name_len + 1;
748
749 memcpy(ptr + 2, hdev->dev_name, name_len);
750
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300751 ptr += (name_len + 2);
752 }
753
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100754 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700755 ptr[0] = 2;
756 ptr[1] = EIR_TX_POWER;
757 ptr[2] = (u8) hdev->inq_tx_power;
758
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700759 ptr += 3;
760 }
761
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700762 if (hdev->devid_source > 0) {
763 ptr[0] = 9;
764 ptr[1] = EIR_DEVICE_ID;
765
766 put_unaligned_le16(hdev->devid_source, ptr + 2);
767 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
768 put_unaligned_le16(hdev->devid_product, ptr + 6);
769 put_unaligned_le16(hdev->devid_version, ptr + 8);
770
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700771 ptr += 10;
772 }
773
Johan Hedberg213202e2013-01-27 00:31:33 +0200774 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200775 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200776 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300777}
778
Johan Hedberg890ea892013-03-15 17:06:52 -0500779static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300780{
Johan Hedberg890ea892013-03-15 17:06:52 -0500781 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300782 struct hci_cp_write_eir cp;
783
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200784 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500785 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200786
Johan Hedberg976eb202012-10-24 21:12:01 +0300787 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500788 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300789
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200790 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500791 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300792
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200793 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500794 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300795
796 memset(&cp, 0, sizeof(cp));
797
798 create_eir(hdev, cp.data);
799
800 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500801 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300802
803 memcpy(hdev->eir, cp.data, sizeof(cp.data));
804
Johan Hedberg890ea892013-03-15 17:06:52 -0500805 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300806}
807
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200808static u8 get_service_classes(struct hci_dev *hdev)
809{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300810 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200811 u8 val = 0;
812
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300813 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200814 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200815
816 return val;
817}
818
Johan Hedberg890ea892013-03-15 17:06:52 -0500819static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200820{
Johan Hedberg890ea892013-03-15 17:06:52 -0500821 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200822 u8 cod[3];
823
824 BT_DBG("%s", hdev->name);
825
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200826 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500827 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200828
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300829 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
830 return;
831
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200832 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500833 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200834
835 cod[0] = hdev->minor_class;
836 cod[1] = hdev->major_class;
837 cod[2] = get_service_classes(hdev);
838
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700839 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
840 cod[1] |= 0x20;
841
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200842 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500843 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200844
Johan Hedberg890ea892013-03-15 17:06:52 -0500845 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200846}
847
Johan Hedberga4858cb2014-02-25 19:56:31 +0200848static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200849{
850 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200851
852 /* If there's a pending mgmt command the flag will not yet have
853 * it's final value, so check for this first.
854 */
855 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
856 if (cmd) {
857 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200858 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200859 }
860
Johan Hedberga4858cb2014-02-25 19:56:31 +0200861 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200862}
863
864static void enable_advertising(struct hci_request *req)
865{
866 struct hci_dev *hdev = req->hdev;
867 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200868 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200869 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200870
Johan Hedberg8d972502014-02-28 12:54:14 +0200871 /* Clear the HCI_ADVERTISING bit temporarily so that the
872 * hci_update_random_address knows that it's safe to go ahead
873 * and write a new random address. The flag will be set back on
874 * as soon as the SET_ADV_ENABLE HCI command completes.
875 */
876 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
877
Johan Hedberga4858cb2014-02-25 19:56:31 +0200878 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200879
Johan Hedberga4858cb2014-02-25 19:56:31 +0200880 /* Set require_privacy to true only when non-connectable
881 * advertising is used. In that case it is fine to use a
882 * non-resolvable private address.
883 */
884 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200885 return;
886
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800887 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700888 cp.min_interval = cpu_to_le16(0x0800);
889 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200890 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200891 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200892 cp.channel_map = hdev->le_adv_channel_map;
893
894 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
895
896 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
897}
898
899static void disable_advertising(struct hci_request *req)
900{
901 u8 enable = 0x00;
902
903 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
904}
905
Johan Hedberg7d785252011-12-15 00:47:39 +0200906static void service_cache_off(struct work_struct *work)
907{
908 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300909 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500910 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200911
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200912 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200913 return;
914
Johan Hedberg890ea892013-03-15 17:06:52 -0500915 hci_req_init(&req, hdev);
916
Johan Hedberg7d785252011-12-15 00:47:39 +0200917 hci_dev_lock(hdev);
918
Johan Hedberg890ea892013-03-15 17:06:52 -0500919 update_eir(&req);
920 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200921
922 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500923
924 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200925}
926
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200927static void rpa_expired(struct work_struct *work)
928{
929 struct hci_dev *hdev = container_of(work, struct hci_dev,
930 rpa_expired.work);
931 struct hci_request req;
932
933 BT_DBG("");
934
935 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
936
937 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
938 hci_conn_num(hdev, LE_LINK) > 0)
939 return;
940
941 /* The generation of a new RPA and programming it into the
942 * controller happens in the enable_advertising() function.
943 */
944
945 hci_req_init(&req, hdev);
946
947 disable_advertising(&req);
948 enable_advertising(&req);
949
950 hci_req_run(&req, NULL);
951}
952
Johan Hedberg6a919082012-02-28 06:17:26 +0200953static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200954{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200955 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200956 return;
957
Johan Hedberg4f87da82012-03-02 19:55:56 +0200958 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200959 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200960
Johan Hedberg4f87da82012-03-02 19:55:56 +0200961 /* Non-mgmt controlled devices get this bit set
962 * implicitly so that pairing works for them, however
963 * for mgmt we require user-space to explicitly enable
964 * it
965 */
966 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200967}
968
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200969static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300970 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200971{
972 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200973
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200974 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300976 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200977
Johan Hedberg03811012010-12-08 00:21:06 +0200978 memset(&rp, 0, sizeof(rp));
979
Johan Hedberg03811012010-12-08 00:21:06 +0200980 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200981
982 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200983 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200984
985 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
986 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
987
988 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200989
990 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200991 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200992
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300993 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200994
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200995 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300996 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200997}
998
999static void mgmt_pending_free(struct pending_cmd *cmd)
1000{
1001 sock_put(cmd->sk);
1002 kfree(cmd->param);
1003 kfree(cmd);
1004}
1005
1006static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001007 struct hci_dev *hdev, void *data,
1008 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001009{
1010 struct pending_cmd *cmd;
1011
Johan Hedbergfca20012014-06-28 17:54:05 +03001012 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001013 if (!cmd)
1014 return NULL;
1015
1016 cmd->opcode = opcode;
1017 cmd->index = hdev->id;
1018
Andre Guedes12b94562012-06-07 19:05:45 -03001019 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001020 if (!cmd->param) {
1021 kfree(cmd);
1022 return NULL;
1023 }
1024
1025 if (data)
1026 memcpy(cmd->param, data, len);
1027
1028 cmd->sk = sk;
1029 sock_hold(sk);
1030
1031 list_add(&cmd->list, &hdev->mgmt_pending);
1032
1033 return cmd;
1034}
1035
1036static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001037 void (*cb)(struct pending_cmd *cmd,
1038 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001039 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001040{
Andre Guedesa3d09352013-02-01 11:21:30 -03001041 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001042
Andre Guedesa3d09352013-02-01 11:21:30 -03001043 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001044 if (opcode > 0 && cmd->opcode != opcode)
1045 continue;
1046
1047 cb(cmd, data);
1048 }
1049}
1050
Johan Hedberg03811012010-12-08 00:21:06 +02001051static void mgmt_pending_remove(struct pending_cmd *cmd)
1052{
1053 list_del(&cmd->list);
1054 mgmt_pending_free(cmd);
1055}
1056
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001057static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001058{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001059 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001060
Johan Hedbergaee9b212012-02-18 15:07:59 +02001061 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001062 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001063}
1064
Johan Hedberg8b064a32014-02-24 14:52:22 +02001065static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1066{
1067 BT_DBG("%s status 0x%02x", hdev->name, status);
1068
Johan Hedberga3172b72014-02-28 09:33:44 +02001069 if (hci_conn_count(hdev) == 0) {
1070 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001071 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001072 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001073}
1074
Johan Hedberg21a60d32014-06-10 14:05:58 +03001075static void hci_stop_discovery(struct hci_request *req)
1076{
1077 struct hci_dev *hdev = req->hdev;
1078 struct hci_cp_remote_name_req_cancel cp;
1079 struct inquiry_entry *e;
1080
1081 switch (hdev->discovery.state) {
1082 case DISCOVERY_FINDING:
1083 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1084 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1085 } else {
1086 cancel_delayed_work(&hdev->le_scan_disable);
1087 hci_req_add_le_scan_disable(req);
1088 }
1089
1090 break;
1091
1092 case DISCOVERY_RESOLVING:
1093 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1094 NAME_PENDING);
1095 if (!e)
1096 return;
1097
1098 bacpy(&cp.bdaddr, &e->data.bdaddr);
1099 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1100 &cp);
1101
1102 break;
1103
1104 default:
1105 /* Passive scanning */
1106 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1107 hci_req_add_le_scan_disable(req);
1108 break;
1109 }
1110}
1111
Johan Hedberg8b064a32014-02-24 14:52:22 +02001112static int clean_up_hci_state(struct hci_dev *hdev)
1113{
1114 struct hci_request req;
1115 struct hci_conn *conn;
1116
1117 hci_req_init(&req, hdev);
1118
1119 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1120 test_bit(HCI_PSCAN, &hdev->flags)) {
1121 u8 scan = 0x00;
1122 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1123 }
1124
1125 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1126 disable_advertising(&req);
1127
Johan Hedbergf8680f12014-06-10 14:05:59 +03001128 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001129
1130 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1131 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001132 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001133
Johan Hedbergc9910d02014-02-27 14:35:12 +02001134 switch (conn->state) {
1135 case BT_CONNECTED:
1136 case BT_CONFIG:
1137 dc.handle = cpu_to_le16(conn->handle);
1138 dc.reason = 0x15; /* Terminated due to Power Off */
1139 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1140 break;
1141 case BT_CONNECT:
1142 if (conn->type == LE_LINK)
1143 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1144 0, NULL);
1145 else if (conn->type == ACL_LINK)
1146 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1147 6, &conn->dst);
1148 break;
1149 case BT_CONNECT2:
1150 bacpy(&rej.bdaddr, &conn->dst);
1151 rej.reason = 0x15; /* Terminated due to Power Off */
1152 if (conn->type == ACL_LINK)
1153 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1154 sizeof(rej), &rej);
1155 else if (conn->type == SCO_LINK)
1156 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1157 sizeof(rej), &rej);
1158 break;
1159 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001160 }
1161
1162 return hci_req_run(&req, clean_up_hci_complete);
1163}
1164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001165static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001166 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001167{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001168 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001169 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001170 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001171
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001172 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001173
Johan Hedberga7e80f22013-01-09 16:05:19 +02001174 if (cp->val != 0x00 && cp->val != 0x01)
1175 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1176 MGMT_STATUS_INVALID_PARAMS);
1177
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001178 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001179
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001180 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1181 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1182 MGMT_STATUS_BUSY);
1183 goto failed;
1184 }
1185
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001186 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1187 cancel_delayed_work(&hdev->power_off);
1188
1189 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001190 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1191 data, len);
1192 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001193 goto failed;
1194 }
1195 }
1196
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001197 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001198 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001199 goto failed;
1200 }
1201
Johan Hedberg03811012010-12-08 00:21:06 +02001202 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1203 if (!cmd) {
1204 err = -ENOMEM;
1205 goto failed;
1206 }
1207
Johan Hedberg8b064a32014-02-24 14:52:22 +02001208 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001209 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001210 err = 0;
1211 } else {
1212 /* Disconnect connections, stop scans, etc */
1213 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001214 if (!err)
1215 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1216 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001217
Johan Hedberg8b064a32014-02-24 14:52:22 +02001218 /* ENODATA means there were no HCI commands queued */
1219 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001220 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001221 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1222 err = 0;
1223 }
1224 }
Johan Hedberg03811012010-12-08 00:21:06 +02001225
1226failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001227 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001228 return err;
1229}
1230
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001231static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1232 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001233{
1234 struct sk_buff *skb;
1235 struct mgmt_hdr *hdr;
1236
Andre Guedes790eff42012-06-07 19:05:46 -03001237 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001238 if (!skb)
1239 return -ENOMEM;
1240
1241 hdr = (void *) skb_put(skb, sizeof(*hdr));
1242 hdr->opcode = cpu_to_le16(event);
1243 if (hdev)
1244 hdr->index = cpu_to_le16(hdev->id);
1245 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001246 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001247 hdr->len = cpu_to_le16(data_len);
1248
1249 if (data)
1250 memcpy(skb_put(skb, data_len), data, data_len);
1251
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001252 /* Time stamp */
1253 __net_timestamp(skb);
1254
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001255 hci_send_to_control(skb, skip_sk);
1256 kfree_skb(skb);
1257
1258 return 0;
1259}
1260
1261static int new_settings(struct hci_dev *hdev, struct sock *skip)
1262{
1263 __le32 ev;
1264
1265 ev = cpu_to_le32(get_current_settings(hdev));
1266
1267 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1268}
1269
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001270struct cmd_lookup {
1271 struct sock *sk;
1272 struct hci_dev *hdev;
1273 u8 mgmt_status;
1274};
1275
1276static void settings_rsp(struct pending_cmd *cmd, void *data)
1277{
1278 struct cmd_lookup *match = data;
1279
1280 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1281
1282 list_del(&cmd->list);
1283
1284 if (match->sk == NULL) {
1285 match->sk = cmd->sk;
1286 sock_hold(match->sk);
1287 }
1288
1289 mgmt_pending_free(cmd);
1290}
1291
1292static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1293{
1294 u8 *status = data;
1295
1296 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1297 mgmt_pending_remove(cmd);
1298}
1299
Johan Hedberge6fe7982013-10-02 15:45:22 +03001300static u8 mgmt_bredr_support(struct hci_dev *hdev)
1301{
1302 if (!lmp_bredr_capable(hdev))
1303 return MGMT_STATUS_NOT_SUPPORTED;
1304 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1305 return MGMT_STATUS_REJECTED;
1306 else
1307 return MGMT_STATUS_SUCCESS;
1308}
1309
1310static u8 mgmt_le_support(struct hci_dev *hdev)
1311{
1312 if (!lmp_le_capable(hdev))
1313 return MGMT_STATUS_NOT_SUPPORTED;
1314 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1315 return MGMT_STATUS_REJECTED;
1316 else
1317 return MGMT_STATUS_SUCCESS;
1318}
1319
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001320static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1321{
1322 struct pending_cmd *cmd;
1323 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001324 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001325 bool changed;
1326
1327 BT_DBG("status 0x%02x", status);
1328
1329 hci_dev_lock(hdev);
1330
1331 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1332 if (!cmd)
1333 goto unlock;
1334
1335 if (status) {
1336 u8 mgmt_err = mgmt_status(status);
1337 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001338 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001339 goto remove_cmd;
1340 }
1341
1342 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001343 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001344 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1345 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001346
1347 if (hdev->discov_timeout > 0) {
1348 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1349 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1350 to);
1351 }
1352 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001353 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1354 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001355 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001356
1357 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1358
1359 if (changed)
1360 new_settings(hdev, cmd->sk);
1361
Marcel Holtmann970ba522013-10-15 06:33:57 -07001362 /* When the discoverable mode gets changed, make sure
1363 * that class of device has the limited discoverable
1364 * bit correctly set.
1365 */
1366 hci_req_init(&req, hdev);
1367 update_class(&req);
1368 hci_req_run(&req, NULL);
1369
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001370remove_cmd:
1371 mgmt_pending_remove(cmd);
1372
1373unlock:
1374 hci_dev_unlock(hdev);
1375}
1376
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001377static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001378 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001379{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001380 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001381 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001382 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001383 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001384 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001385 int err;
1386
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001387 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001388
Johan Hedberg9a43e252013-10-20 19:00:07 +03001389 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1390 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001391 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001392 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001393
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001394 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001395 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1396 MGMT_STATUS_INVALID_PARAMS);
1397
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001398 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001399
1400 /* Disabling discoverable requires that no timeout is set,
1401 * and enabling limited discoverable requires a timeout.
1402 */
1403 if ((cp->val == 0x00 && timeout > 0) ||
1404 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001405 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001406 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001407
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001408 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001409
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001410 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001411 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001412 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001413 goto failed;
1414 }
1415
1416 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001417 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001418 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001419 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001420 goto failed;
1421 }
1422
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001423 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001424 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001425 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001426 goto failed;
1427 }
1428
1429 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001430 bool changed = false;
1431
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001432 /* Setting limited discoverable when powered off is
1433 * not a valid operation since it requires a timeout
1434 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1435 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001436 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1437 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1438 changed = true;
1439 }
1440
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001441 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001442 if (err < 0)
1443 goto failed;
1444
1445 if (changed)
1446 err = new_settings(hdev, sk);
1447
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001448 goto failed;
1449 }
1450
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001451 /* If the current mode is the same, then just update the timeout
1452 * value with the new value. And if only the timeout gets updated,
1453 * then no need for any HCI transactions.
1454 */
1455 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1456 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1457 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001458 cancel_delayed_work(&hdev->discov_off);
1459 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001460
Marcel Holtmann36261542013-10-15 08:28:51 -07001461 if (cp->val && hdev->discov_timeout > 0) {
1462 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001463 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001464 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001465 }
1466
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001467 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001468 goto failed;
1469 }
1470
1471 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1472 if (!cmd) {
1473 err = -ENOMEM;
1474 goto failed;
1475 }
1476
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001477 /* Cancel any potential discoverable timeout that might be
1478 * still active and store new timeout value. The arming of
1479 * the timeout happens in the complete handler.
1480 */
1481 cancel_delayed_work(&hdev->discov_off);
1482 hdev->discov_timeout = timeout;
1483
Johan Hedbergb456f872013-10-19 23:38:22 +03001484 /* Limited discoverable mode */
1485 if (cp->val == 0x02)
1486 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1487 else
1488 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1489
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001490 hci_req_init(&req, hdev);
1491
Johan Hedberg9a43e252013-10-20 19:00:07 +03001492 /* The procedure for LE-only controllers is much simpler - just
1493 * update the advertising data.
1494 */
1495 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1496 goto update_ad;
1497
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001498 scan = SCAN_PAGE;
1499
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001500 if (cp->val) {
1501 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001502
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001503 if (cp->val == 0x02) {
1504 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001505 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001506 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1507 hci_cp.iac_lap[1] = 0x8b;
1508 hci_cp.iac_lap[2] = 0x9e;
1509 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1510 hci_cp.iac_lap[4] = 0x8b;
1511 hci_cp.iac_lap[5] = 0x9e;
1512 } else {
1513 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001514 hci_cp.num_iac = 1;
1515 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1516 hci_cp.iac_lap[1] = 0x8b;
1517 hci_cp.iac_lap[2] = 0x9e;
1518 }
1519
1520 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1521 (hci_cp.num_iac * 3) + 1, &hci_cp);
1522
1523 scan |= SCAN_INQUIRY;
1524 } else {
1525 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1526 }
1527
1528 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001529
Johan Hedberg9a43e252013-10-20 19:00:07 +03001530update_ad:
1531 update_adv_data(&req);
1532
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001533 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001534 if (err < 0)
1535 mgmt_pending_remove(cmd);
1536
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001537failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001538 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001539 return err;
1540}
1541
Johan Hedberg406d7802013-03-15 17:07:09 -05001542static void write_fast_connectable(struct hci_request *req, bool enable)
1543{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001544 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001545 struct hci_cp_write_page_scan_activity acp;
1546 u8 type;
1547
Johan Hedberg547003b2013-10-21 16:51:53 +03001548 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1549 return;
1550
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001551 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1552 return;
1553
Johan Hedberg406d7802013-03-15 17:07:09 -05001554 if (enable) {
1555 type = PAGE_SCAN_TYPE_INTERLACED;
1556
1557 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001558 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001559 } else {
1560 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1561
1562 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001563 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001564 }
1565
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001566 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001567
Johan Hedbergbd98b992013-03-15 17:07:13 -05001568 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1569 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1570 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1571 sizeof(acp), &acp);
1572
1573 if (hdev->page_scan_type != type)
1574 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001575}
1576
Johan Hedberg2b76f452013-03-15 17:07:04 -05001577static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1578{
1579 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001580 struct mgmt_mode *cp;
1581 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001582
1583 BT_DBG("status 0x%02x", status);
1584
1585 hci_dev_lock(hdev);
1586
1587 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1588 if (!cmd)
1589 goto unlock;
1590
Johan Hedberg37438c12013-10-14 16:20:05 +03001591 if (status) {
1592 u8 mgmt_err = mgmt_status(status);
1593 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1594 goto remove_cmd;
1595 }
1596
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001597 cp = cmd->param;
1598 if (cp->val)
1599 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1600 else
1601 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1602
Johan Hedberg2b76f452013-03-15 17:07:04 -05001603 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1604
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001605 if (changed)
1606 new_settings(hdev, cmd->sk);
1607
Johan Hedberg37438c12013-10-14 16:20:05 +03001608remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001609 mgmt_pending_remove(cmd);
1610
1611unlock:
1612 hci_dev_unlock(hdev);
1613}
1614
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001615static int set_connectable_update_settings(struct hci_dev *hdev,
1616 struct sock *sk, u8 val)
1617{
1618 bool changed = false;
1619 int err;
1620
1621 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1622 changed = true;
1623
1624 if (val) {
1625 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1626 } else {
1627 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1628 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1629 }
1630
1631 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1632 if (err < 0)
1633 return err;
1634
1635 if (changed)
1636 return new_settings(hdev, sk);
1637
1638 return 0;
1639}
1640
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001641static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001642 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001643{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001644 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001645 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001646 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001647 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001648 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001649
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001650 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001651
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001652 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1653 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001654 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001655 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001656
Johan Hedberga7e80f22013-01-09 16:05:19 +02001657 if (cp->val != 0x00 && cp->val != 0x01)
1658 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1659 MGMT_STATUS_INVALID_PARAMS);
1660
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001661 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001662
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001663 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001664 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001665 goto failed;
1666 }
1667
1668 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001669 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001670 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001671 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001672 goto failed;
1673 }
1674
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001675 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1676 if (!cmd) {
1677 err = -ENOMEM;
1678 goto failed;
1679 }
1680
Johan Hedberg2b76f452013-03-15 17:07:04 -05001681 hci_req_init(&req, hdev);
1682
Johan Hedberg9a43e252013-10-20 19:00:07 +03001683 /* If BR/EDR is not enabled and we disable advertising as a
1684 * by-product of disabling connectable, we need to update the
1685 * advertising flags.
1686 */
1687 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1688 if (!cp->val) {
1689 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1690 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1691 }
1692 update_adv_data(&req);
1693 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001694 if (cp->val) {
1695 scan = SCAN_PAGE;
1696 } else {
1697 scan = 0;
1698
1699 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001700 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001701 cancel_delayed_work(&hdev->discov_off);
1702 }
1703
1704 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1705 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001706
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001707 /* If we're going from non-connectable to connectable or
1708 * vice-versa when fast connectable is enabled ensure that fast
1709 * connectable gets disabled. write_fast_connectable won't do
1710 * anything if the page scan parameters are already what they
1711 * should be.
1712 */
1713 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001714 write_fast_connectable(&req, false);
1715
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001716 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1717 hci_conn_num(hdev, LE_LINK) == 0) {
1718 disable_advertising(&req);
1719 enable_advertising(&req);
1720 }
1721
Johan Hedberg2b76f452013-03-15 17:07:04 -05001722 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001723 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001724 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001725 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001726 err = set_connectable_update_settings(hdev, sk,
1727 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001728 goto failed;
1729 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001730
1731failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001732 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001733 return err;
1734}
1735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001736static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001737 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001738{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001739 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001740 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001741 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001742
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001743 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001744
Johan Hedberga7e80f22013-01-09 16:05:19 +02001745 if (cp->val != 0x00 && cp->val != 0x01)
1746 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1747 MGMT_STATUS_INVALID_PARAMS);
1748
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001749 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001750
1751 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001752 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001753 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001754 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001755
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001756 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001757 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001758 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001759
Marcel Holtmann55594352013-10-06 16:11:57 -07001760 if (changed)
1761 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001762
Marcel Holtmann55594352013-10-06 16:11:57 -07001763unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001764 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001765 return err;
1766}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001767
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001768static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1769 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001770{
1771 struct mgmt_mode *cp = data;
1772 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001773 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001774 int err;
1775
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001776 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001777
Johan Hedberge6fe7982013-10-02 15:45:22 +03001778 status = mgmt_bredr_support(hdev);
1779 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001780 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001781 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001782
Johan Hedberga7e80f22013-01-09 16:05:19 +02001783 if (cp->val != 0x00 && cp->val != 0x01)
1784 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1785 MGMT_STATUS_INVALID_PARAMS);
1786
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001787 hci_dev_lock(hdev);
1788
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001789 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001790 bool changed = false;
1791
1792 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001793 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001794 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1795 changed = true;
1796 }
1797
1798 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1799 if (err < 0)
1800 goto failed;
1801
1802 if (changed)
1803 err = new_settings(hdev, sk);
1804
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001805 goto failed;
1806 }
1807
1808 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001809 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001810 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001811 goto failed;
1812 }
1813
1814 val = !!cp->val;
1815
1816 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1817 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1818 goto failed;
1819 }
1820
1821 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1822 if (!cmd) {
1823 err = -ENOMEM;
1824 goto failed;
1825 }
1826
1827 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1828 if (err < 0) {
1829 mgmt_pending_remove(cmd);
1830 goto failed;
1831 }
1832
1833failed:
1834 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001835 return err;
1836}
1837
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001838static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001839{
1840 struct mgmt_mode *cp = data;
1841 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001842 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001843 int err;
1844
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001845 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001846
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001847 status = mgmt_bredr_support(hdev);
1848 if (status)
1849 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1850
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001851 if (!lmp_ssp_capable(hdev))
1852 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1853 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001854
Johan Hedberga7e80f22013-01-09 16:05:19 +02001855 if (cp->val != 0x00 && cp->val != 0x01)
1856 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1857 MGMT_STATUS_INVALID_PARAMS);
1858
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001859 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001860
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001861 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001862 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001863
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001864 if (cp->val) {
1865 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1866 &hdev->dev_flags);
1867 } else {
1868 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1869 &hdev->dev_flags);
1870 if (!changed)
1871 changed = test_and_clear_bit(HCI_HS_ENABLED,
1872 &hdev->dev_flags);
1873 else
1874 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001875 }
1876
1877 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1878 if (err < 0)
1879 goto failed;
1880
1881 if (changed)
1882 err = new_settings(hdev, sk);
1883
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001884 goto failed;
1885 }
1886
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001887 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1888 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001889 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1890 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001891 goto failed;
1892 }
1893
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001894 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001895 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1896 goto failed;
1897 }
1898
1899 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1900 if (!cmd) {
1901 err = -ENOMEM;
1902 goto failed;
1903 }
1904
Johan Hedberg37699722014-06-24 14:00:27 +03001905 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1906 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1907 sizeof(cp->val), &cp->val);
1908
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001909 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001910 if (err < 0) {
1911 mgmt_pending_remove(cmd);
1912 goto failed;
1913 }
1914
1915failed:
1916 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001917 return err;
1918}
1919
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001920static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001921{
1922 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001923 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001924 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001925 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001926
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001927 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001928
Johan Hedberge6fe7982013-10-02 15:45:22 +03001929 status = mgmt_bredr_support(hdev);
1930 if (status)
1931 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001932
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001933 if (!lmp_ssp_capable(hdev))
1934 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1935 MGMT_STATUS_NOT_SUPPORTED);
1936
1937 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1938 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1939 MGMT_STATUS_REJECTED);
1940
Johan Hedberga7e80f22013-01-09 16:05:19 +02001941 if (cp->val != 0x00 && cp->val != 0x01)
1942 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1943 MGMT_STATUS_INVALID_PARAMS);
1944
Marcel Holtmannee392692013-10-01 22:59:23 -07001945 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001946
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001947 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001948 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001949 } else {
1950 if (hdev_is_powered(hdev)) {
1951 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1952 MGMT_STATUS_REJECTED);
1953 goto unlock;
1954 }
1955
Marcel Holtmannee392692013-10-01 22:59:23 -07001956 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001957 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001958
1959 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1960 if (err < 0)
1961 goto unlock;
1962
1963 if (changed)
1964 err = new_settings(hdev, sk);
1965
1966unlock:
1967 hci_dev_unlock(hdev);
1968 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001969}
1970
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001971static void le_enable_complete(struct hci_dev *hdev, u8 status)
1972{
1973 struct cmd_lookup match = { NULL, hdev };
1974
1975 if (status) {
1976 u8 mgmt_err = mgmt_status(status);
1977
1978 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1979 &mgmt_err);
1980 return;
1981 }
1982
1983 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1984
1985 new_settings(hdev, match.sk);
1986
1987 if (match.sk)
1988 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001989
1990 /* Make sure the controller has a good default for
1991 * advertising data. Restrict the update to when LE
1992 * has actually been enabled. During power on, the
1993 * update in powered_update_hci will take care of it.
1994 */
1995 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1996 struct hci_request req;
1997
1998 hci_dev_lock(hdev);
1999
2000 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002001 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002002 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002003 hci_req_run(&req, NULL);
2004
2005 hci_dev_unlock(hdev);
2006 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002007}
2008
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002009static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002010{
2011 struct mgmt_mode *cp = data;
2012 struct hci_cp_write_le_host_supported hci_cp;
2013 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002014 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002015 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002016 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002017
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002018 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002019
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002020 if (!lmp_le_capable(hdev))
2021 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2022 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002023
Johan Hedberga7e80f22013-01-09 16:05:19 +02002024 if (cp->val != 0x00 && cp->val != 0x01)
2025 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2026 MGMT_STATUS_INVALID_PARAMS);
2027
Johan Hedbergc73eee92013-04-19 18:35:21 +03002028 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002029 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002030 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2031 MGMT_STATUS_REJECTED);
2032
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002033 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002034
2035 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002036 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002037
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002038 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002039 bool changed = false;
2040
2041 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2042 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2043 changed = true;
2044 }
2045
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002046 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2047 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002048 changed = true;
2049 }
2050
Johan Hedberg06199cf2012-02-22 16:37:11 +02002051 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2052 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002053 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002054
2055 if (changed)
2056 err = new_settings(hdev, sk);
2057
Johan Hedberg1de028c2012-02-29 19:55:35 -08002058 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002059 }
2060
Johan Hedberg4375f102013-09-25 13:26:10 +03002061 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2062 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002063 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002064 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002065 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002066 }
2067
2068 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2069 if (!cmd) {
2070 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002071 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002072 }
2073
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002074 hci_req_init(&req, hdev);
2075
Johan Hedberg06199cf2012-02-22 16:37:11 +02002076 memset(&hci_cp, 0, sizeof(hci_cp));
2077
2078 if (val) {
2079 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002080 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002081 } else {
2082 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2083 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002084 }
2085
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002086 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2087 &hci_cp);
2088
2089 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302090 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002091 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002092
Johan Hedberg1de028c2012-02-29 19:55:35 -08002093unlock:
2094 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002095 return err;
2096}
2097
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002098/* This is a helper function to test for pending mgmt commands that can
2099 * cause CoD or EIR HCI commands. We can only allow one such pending
2100 * mgmt command at a time since otherwise we cannot easily track what
2101 * the current values are, will be, and based on that calculate if a new
2102 * HCI command needs to be sent and if yes with what value.
2103 */
2104static bool pending_eir_or_class(struct hci_dev *hdev)
2105{
2106 struct pending_cmd *cmd;
2107
2108 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2109 switch (cmd->opcode) {
2110 case MGMT_OP_ADD_UUID:
2111 case MGMT_OP_REMOVE_UUID:
2112 case MGMT_OP_SET_DEV_CLASS:
2113 case MGMT_OP_SET_POWERED:
2114 return true;
2115 }
2116 }
2117
2118 return false;
2119}
2120
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002121static const u8 bluetooth_base_uuid[] = {
2122 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2123 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2124};
2125
2126static u8 get_uuid_size(const u8 *uuid)
2127{
2128 u32 val;
2129
2130 if (memcmp(uuid, bluetooth_base_uuid, 12))
2131 return 128;
2132
2133 val = get_unaligned_le32(&uuid[12]);
2134 if (val > 0xffff)
2135 return 32;
2136
2137 return 16;
2138}
2139
Johan Hedberg92da6092013-03-15 17:06:55 -05002140static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2141{
2142 struct pending_cmd *cmd;
2143
2144 hci_dev_lock(hdev);
2145
2146 cmd = mgmt_pending_find(mgmt_op, hdev);
2147 if (!cmd)
2148 goto unlock;
2149
2150 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2151 hdev->dev_class, 3);
2152
2153 mgmt_pending_remove(cmd);
2154
2155unlock:
2156 hci_dev_unlock(hdev);
2157}
2158
2159static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2160{
2161 BT_DBG("status 0x%02x", status);
2162
2163 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2164}
2165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002166static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002167{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002168 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002169 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002170 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002171 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002172 int err;
2173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002174 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002175
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002176 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002177
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002178 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002179 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002180 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002181 goto failed;
2182 }
2183
Andre Guedes92c4c202012-06-07 19:05:44 -03002184 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002185 if (!uuid) {
2186 err = -ENOMEM;
2187 goto failed;
2188 }
2189
2190 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002191 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002192 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002193
Johan Hedbergde66aa62013-01-27 00:31:27 +02002194 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002195
Johan Hedberg890ea892013-03-15 17:06:52 -05002196 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002197
Johan Hedberg890ea892013-03-15 17:06:52 -05002198 update_class(&req);
2199 update_eir(&req);
2200
Johan Hedberg92da6092013-03-15 17:06:55 -05002201 err = hci_req_run(&req, add_uuid_complete);
2202 if (err < 0) {
2203 if (err != -ENODATA)
2204 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002205
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002206 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002207 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002208 goto failed;
2209 }
2210
2211 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002212 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002213 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002214 goto failed;
2215 }
2216
2217 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002218
2219failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002220 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002221 return err;
2222}
2223
Johan Hedberg24b78d02012-02-23 23:24:30 +02002224static bool enable_service_cache(struct hci_dev *hdev)
2225{
2226 if (!hdev_is_powered(hdev))
2227 return false;
2228
2229 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002230 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2231 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002232 return true;
2233 }
2234
2235 return false;
2236}
2237
Johan Hedberg92da6092013-03-15 17:06:55 -05002238static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2239{
2240 BT_DBG("status 0x%02x", status);
2241
2242 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2243}
2244
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002245static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002246 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002247{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002248 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002249 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002250 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002251 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 -05002252 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002253 int err, found;
2254
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002255 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002256
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002257 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002258
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002259 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002260 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002261 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002262 goto unlock;
2263 }
2264
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002265 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002266 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002267
Johan Hedberg24b78d02012-02-23 23:24:30 +02002268 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002269 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002270 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002271 goto unlock;
2272 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002273
Johan Hedberg9246a862012-02-23 21:33:16 +02002274 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002275 }
2276
2277 found = 0;
2278
Johan Hedberg056341c2013-01-27 00:31:30 +02002279 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002280 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2281 continue;
2282
2283 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002284 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002285 found++;
2286 }
2287
2288 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002289 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002290 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002291 goto unlock;
2292 }
2293
Johan Hedberg9246a862012-02-23 21:33:16 +02002294update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002295 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002296
Johan Hedberg890ea892013-03-15 17:06:52 -05002297 update_class(&req);
2298 update_eir(&req);
2299
Johan Hedberg92da6092013-03-15 17:06:55 -05002300 err = hci_req_run(&req, remove_uuid_complete);
2301 if (err < 0) {
2302 if (err != -ENODATA)
2303 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002305 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002306 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002307 goto unlock;
2308 }
2309
2310 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002311 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002312 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002313 goto unlock;
2314 }
2315
2316 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002317
2318unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002319 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002320 return err;
2321}
2322
Johan Hedberg92da6092013-03-15 17:06:55 -05002323static void set_class_complete(struct hci_dev *hdev, u8 status)
2324{
2325 BT_DBG("status 0x%02x", status);
2326
2327 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2328}
2329
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002330static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002331 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002332{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002333 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002334 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002335 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002336 int err;
2337
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002338 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002339
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002340 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002341 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2342 MGMT_STATUS_NOT_SUPPORTED);
2343
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002344 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002345
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002346 if (pending_eir_or_class(hdev)) {
2347 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2348 MGMT_STATUS_BUSY);
2349 goto unlock;
2350 }
2351
2352 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2353 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2354 MGMT_STATUS_INVALID_PARAMS);
2355 goto unlock;
2356 }
2357
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002358 hdev->major_class = cp->major;
2359 hdev->minor_class = cp->minor;
2360
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002361 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002362 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002363 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002364 goto unlock;
2365 }
2366
Johan Hedberg890ea892013-03-15 17:06:52 -05002367 hci_req_init(&req, hdev);
2368
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002369 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002370 hci_dev_unlock(hdev);
2371 cancel_delayed_work_sync(&hdev->service_cache);
2372 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002373 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002374 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002375
Johan Hedberg890ea892013-03-15 17:06:52 -05002376 update_class(&req);
2377
Johan Hedberg92da6092013-03-15 17:06:55 -05002378 err = hci_req_run(&req, set_class_complete);
2379 if (err < 0) {
2380 if (err != -ENODATA)
2381 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002382
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002383 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002384 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002385 goto unlock;
2386 }
2387
2388 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002389 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002390 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002391 goto unlock;
2392 }
2393
2394 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002395
Johan Hedbergb5235a62012-02-21 14:32:24 +02002396unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002397 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002398 return err;
2399}
2400
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002401static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002402 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002403{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002404 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002405 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002406 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002407 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002408
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002409 BT_DBG("request for %s", hdev->name);
2410
2411 if (!lmp_bredr_capable(hdev))
2412 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2413 MGMT_STATUS_NOT_SUPPORTED);
2414
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002415 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002416
Johan Hedberg86742e12011-11-07 23:13:38 +02002417 expected_len = sizeof(*cp) + key_count *
2418 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002419 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002420 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002421 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002422 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002423 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002424 }
2425
Johan Hedberg4ae14302013-01-20 14:27:13 +02002426 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2427 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2428 MGMT_STATUS_INVALID_PARAMS);
2429
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002430 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002431 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002432
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002433 for (i = 0; i < key_count; i++) {
2434 struct mgmt_link_key_info *key = &cp->keys[i];
2435
Marcel Holtmann8e991132014-01-10 02:07:25 -08002436 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002437 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2438 MGMT_STATUS_INVALID_PARAMS);
2439 }
2440
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002441 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002442
2443 hci_link_keys_clear(hdev);
2444
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002445 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002446 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2447 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002448 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002449 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2450 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002451
2452 if (changed)
2453 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002454
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002455 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002456 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002457
Johan Hedberg58e92932014-06-24 14:00:26 +03002458 /* Always ignore debug keys and require a new pairing if
2459 * the user wants to use them.
2460 */
2461 if (key->type == HCI_LK_DEBUG_COMBINATION)
2462 continue;
2463
Johan Hedberg7652ff62014-06-24 13:15:49 +03002464 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2465 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002466 }
2467
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002468 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002469
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002470 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002471
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002472 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002473}
2474
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002475static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002476 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002477{
2478 struct mgmt_ev_device_unpaired ev;
2479
2480 bacpy(&ev.addr.bdaddr, bdaddr);
2481 ev.addr.type = addr_type;
2482
2483 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002484 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002485}
2486
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002487static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002488 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002489{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002490 struct mgmt_cp_unpair_device *cp = data;
2491 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002492 struct hci_cp_disconnect dc;
2493 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002494 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002495 int err;
2496
Johan Hedberga8a1d192011-11-10 15:54:38 +02002497 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002498 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2499 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002500
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002501 if (!bdaddr_type_is_valid(cp->addr.type))
2502 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2503 MGMT_STATUS_INVALID_PARAMS,
2504 &rp, sizeof(rp));
2505
Johan Hedberg118da702013-01-20 14:27:20 +02002506 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2507 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2508 MGMT_STATUS_INVALID_PARAMS,
2509 &rp, sizeof(rp));
2510
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002511 hci_dev_lock(hdev);
2512
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002513 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002514 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002515 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002516 goto unlock;
2517 }
2518
Johan Hedberge0b2b272014-02-18 17:14:31 +02002519 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002520 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002521 } else {
2522 u8 addr_type;
2523
2524 if (cp->addr.type == BDADDR_LE_PUBLIC)
2525 addr_type = ADDR_LE_DEV_PUBLIC;
2526 else
2527 addr_type = ADDR_LE_DEV_RANDOM;
2528
Johan Hedberga7ec7332014-02-18 17:14:35 +02002529 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2530
Andre Guedesa9b0a042014-02-26 20:21:52 -03002531 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2532
Johan Hedberge0b2b272014-02-18 17:14:31 +02002533 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2534 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002535
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002536 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002537 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002538 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002539 goto unlock;
2540 }
2541
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002542 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002543 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002544 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002545 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002546 else
2547 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002548 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002549 } else {
2550 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002551 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002552
Johan Hedberga8a1d192011-11-10 15:54:38 +02002553 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002554 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002555 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002556 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002557 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002558 }
2559
Johan Hedberg124f6e32012-02-09 13:50:12 +02002560 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002561 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002562 if (!cmd) {
2563 err = -ENOMEM;
2564 goto unlock;
2565 }
2566
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002567 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002568 dc.reason = 0x13; /* Remote User Terminated Connection */
2569 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2570 if (err < 0)
2571 mgmt_pending_remove(cmd);
2572
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002573unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002574 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002575 return err;
2576}
2577
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002578static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002579 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002580{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002581 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002582 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002583 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002584 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002585 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002586 int err;
2587
2588 BT_DBG("");
2589
Johan Hedberg06a63b12013-01-20 14:27:21 +02002590 memset(&rp, 0, sizeof(rp));
2591 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2592 rp.addr.type = cp->addr.type;
2593
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002594 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002595 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2596 MGMT_STATUS_INVALID_PARAMS,
2597 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002598
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002599 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002600
2601 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002602 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2603 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002604 goto failed;
2605 }
2606
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002607 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002608 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2609 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002610 goto failed;
2611 }
2612
Andre Guedes591f47f2012-04-24 21:02:49 -03002613 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002614 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2615 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002616 else
2617 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002618
Vishal Agarwalf9607272012-06-13 05:32:43 +05302619 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002620 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2621 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002622 goto failed;
2623 }
2624
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002625 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002626 if (!cmd) {
2627 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002628 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002629 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002630
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002631 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002632 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002633
2634 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2635 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002636 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002637
2638failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002639 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002640 return err;
2641}
2642
Andre Guedes57c14772012-04-24 21:02:50 -03002643static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002644{
2645 switch (link_type) {
2646 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002647 switch (addr_type) {
2648 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002649 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002650
Johan Hedberg48264f02011-11-09 13:58:58 +02002651 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002652 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002653 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002654 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002655
Johan Hedberg4c659c32011-11-07 23:13:39 +02002656 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002657 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002658 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002659 }
2660}
2661
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002662static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2663 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002664{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002665 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002666 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002667 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002668 int err;
2669 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002670
2671 BT_DBG("");
2672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002673 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002674
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002675 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002676 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002677 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002678 goto unlock;
2679 }
2680
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002681 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002682 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2683 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002684 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002685 }
2686
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002687 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002688 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002689 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002690 err = -ENOMEM;
2691 goto unlock;
2692 }
2693
Johan Hedberg2784eb42011-01-21 13:56:35 +02002694 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002695 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002696 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2697 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002698 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002699 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002700 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002701 continue;
2702 i++;
2703 }
2704
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002705 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002706
Johan Hedberg4c659c32011-11-07 23:13:39 +02002707 /* Recalculate length in case of filtered SCO connections, etc */
2708 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002709
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002710 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002711 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002712
Johan Hedberga38528f2011-01-22 06:46:43 +02002713 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002714
2715unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002716 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002717 return err;
2718}
2719
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002720static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002721 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002722{
2723 struct pending_cmd *cmd;
2724 int err;
2725
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002726 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002727 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002728 if (!cmd)
2729 return -ENOMEM;
2730
Johan Hedbergd8457692012-02-17 14:24:57 +02002731 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002732 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002733 if (err < 0)
2734 mgmt_pending_remove(cmd);
2735
2736 return err;
2737}
2738
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002739static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002740 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002741{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002742 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002743 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002744 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002745 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002746 int err;
2747
2748 BT_DBG("");
2749
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002750 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002751
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002752 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002753 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002754 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002755 goto failed;
2756 }
2757
Johan Hedbergd8457692012-02-17 14:24:57 +02002758 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002759 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002760 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002761 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002762 goto failed;
2763 }
2764
2765 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002766 struct mgmt_cp_pin_code_neg_reply ncp;
2767
2768 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002769
2770 BT_ERR("PIN code is not 16 bytes long");
2771
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002772 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002773 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002774 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002775 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002776
2777 goto failed;
2778 }
2779
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002780 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002781 if (!cmd) {
2782 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002783 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002784 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002785
Johan Hedbergd8457692012-02-17 14:24:57 +02002786 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002787 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002788 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002789
2790 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2791 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002792 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002793
2794failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002795 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002796 return err;
2797}
2798
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002799static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2800 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002801{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002802 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002803
2804 BT_DBG("");
2805
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002806 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2807 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2808 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2809
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002810 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002811
2812 hdev->io_capability = cp->io_capability;
2813
2814 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002815 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002816
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002817 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002818
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002819 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2820 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002821}
2822
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002823static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002824{
2825 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002826 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002827
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002828 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002829 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2830 continue;
2831
Johan Hedberge9a416b2011-02-19 12:05:56 -03002832 if (cmd->user_data != conn)
2833 continue;
2834
2835 return cmd;
2836 }
2837
2838 return NULL;
2839}
2840
2841static void pairing_complete(struct pending_cmd *cmd, u8 status)
2842{
2843 struct mgmt_rp_pair_device rp;
2844 struct hci_conn *conn = cmd->user_data;
2845
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002846 bacpy(&rp.addr.bdaddr, &conn->dst);
2847 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002848
Johan Hedbergaee9b212012-02-18 15:07:59 +02002849 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002850 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002851
2852 /* So we don't get further callbacks for this connection */
2853 conn->connect_cfm_cb = NULL;
2854 conn->security_cfm_cb = NULL;
2855 conn->disconn_cfm_cb = NULL;
2856
David Herrmann76a68ba2013-04-06 20:28:37 +02002857 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002858
Johan Hedberga664b5b2011-02-19 12:06:02 -03002859 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002860}
2861
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002862void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2863{
2864 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2865 struct pending_cmd *cmd;
2866
2867 cmd = find_pairing(conn);
2868 if (cmd)
2869 pairing_complete(cmd, status);
2870}
2871
Johan Hedberge9a416b2011-02-19 12:05:56 -03002872static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2873{
2874 struct pending_cmd *cmd;
2875
2876 BT_DBG("status %u", status);
2877
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002878 cmd = find_pairing(conn);
2879 if (!cmd)
2880 BT_DBG("Unable to find a pending command");
2881 else
Johan Hedberge2113262012-02-18 15:20:03 +02002882 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002883}
2884
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002885static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302886{
2887 struct pending_cmd *cmd;
2888
2889 BT_DBG("status %u", status);
2890
2891 if (!status)
2892 return;
2893
2894 cmd = find_pairing(conn);
2895 if (!cmd)
2896 BT_DBG("Unable to find a pending command");
2897 else
2898 pairing_complete(cmd, mgmt_status(status));
2899}
2900
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002901static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002902 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002903{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002904 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002905 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002906 struct pending_cmd *cmd;
2907 u8 sec_level, auth_type;
2908 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002909 int err;
2910
2911 BT_DBG("");
2912
Szymon Jancf950a30e2013-01-18 12:48:07 +01002913 memset(&rp, 0, sizeof(rp));
2914 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2915 rp.addr.type = cp->addr.type;
2916
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002917 if (!bdaddr_type_is_valid(cp->addr.type))
2918 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2919 MGMT_STATUS_INVALID_PARAMS,
2920 &rp, sizeof(rp));
2921
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002922 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2923 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2924 MGMT_STATUS_INVALID_PARAMS,
2925 &rp, sizeof(rp));
2926
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002927 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002928
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002929 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002930 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2931 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002932 goto unlock;
2933 }
2934
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002935 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002936 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002937
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002938 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002939 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2940 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002941 } else {
2942 u8 addr_type;
2943
2944 /* Convert from L2CAP channel address type to HCI address type
2945 */
2946 if (cp->addr.type == BDADDR_LE_PUBLIC)
2947 addr_type = ADDR_LE_DEV_PUBLIC;
2948 else
2949 addr_type = ADDR_LE_DEV_RANDOM;
2950
Marcel Holtmann7c264b12014-06-30 12:34:40 +02002951 /* When pairing a new device, it is expected to remember
2952 * this device for future connections. Adding the connection
2953 * parameter information ahead of time allows tracking
2954 * of the slave preferred values and will speed up any
2955 * further connection establishment.
2956 *
2957 * If connection parameters already exist, then they
2958 * will be kept and this function does nothing.
2959 */
2960 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
2961
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002962 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002963 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002964 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002965
Ville Tervo30e76272011-02-22 16:10:53 -03002966 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002967 int status;
2968
2969 if (PTR_ERR(conn) == -EBUSY)
2970 status = MGMT_STATUS_BUSY;
2971 else
2972 status = MGMT_STATUS_CONNECT_FAILED;
2973
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002974 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002975 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002977 goto unlock;
2978 }
2979
2980 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002981 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002982 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002983 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002984 goto unlock;
2985 }
2986
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002987 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002988 if (!cmd) {
2989 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002990 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002991 goto unlock;
2992 }
2993
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002994 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002995 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002996 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002997 conn->security_cfm_cb = pairing_complete_cb;
2998 conn->disconn_cfm_cb = pairing_complete_cb;
2999 } else {
3000 conn->connect_cfm_cb = le_pairing_complete_cb;
3001 conn->security_cfm_cb = le_pairing_complete_cb;
3002 conn->disconn_cfm_cb = le_pairing_complete_cb;
3003 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003004
Johan Hedberge9a416b2011-02-19 12:05:56 -03003005 conn->io_capability = cp->io_cap;
3006 cmd->user_data = conn;
3007
3008 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003009 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003010 pairing_complete(cmd, 0);
3011
3012 err = 0;
3013
3014unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003015 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003016 return err;
3017}
3018
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003019static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3020 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003021{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003022 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003023 struct pending_cmd *cmd;
3024 struct hci_conn *conn;
3025 int err;
3026
3027 BT_DBG("");
3028
Johan Hedberg28424702012-02-02 04:02:29 +02003029 hci_dev_lock(hdev);
3030
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003031 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003032 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003033 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003034 goto unlock;
3035 }
3036
Johan Hedberg28424702012-02-02 04:02:29 +02003037 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3038 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003039 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003040 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003041 goto unlock;
3042 }
3043
3044 conn = cmd->user_data;
3045
3046 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003047 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003048 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003049 goto unlock;
3050 }
3051
3052 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3053
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003054 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003055 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003056unlock:
3057 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003058 return err;
3059}
3060
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003061static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003062 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003063 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003064{
Johan Hedberga5c29682011-02-19 12:05:57 -03003065 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003066 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003067 int err;
3068
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003069 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003070
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003071 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003072 err = cmd_complete(sk, hdev->id, mgmt_op,
3073 MGMT_STATUS_NOT_POWERED, addr,
3074 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003075 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003076 }
3077
Johan Hedberg1707c602013-03-15 17:07:15 -05003078 if (addr->type == BDADDR_BREDR)
3079 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003080 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003081 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003082
Johan Hedberg272d90d2012-02-09 15:26:12 +02003083 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003084 err = cmd_complete(sk, hdev->id, mgmt_op,
3085 MGMT_STATUS_NOT_CONNECTED, addr,
3086 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003087 goto done;
3088 }
3089
Johan Hedberg1707c602013-03-15 17:07:15 -05003090 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003091 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003092 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003093 err = cmd_complete(sk, hdev->id, mgmt_op,
3094 MGMT_STATUS_SUCCESS, addr,
3095 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003096 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003097 err = cmd_complete(sk, hdev->id, mgmt_op,
3098 MGMT_STATUS_FAILED, addr,
3099 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003100
Brian Gix47c15e22011-11-16 13:53:14 -08003101 goto done;
3102 }
3103
Johan Hedberg1707c602013-03-15 17:07:15 -05003104 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003105 if (!cmd) {
3106 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003107 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003108 }
3109
Brian Gix0df4c182011-11-16 13:53:13 -08003110 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003111 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3112 struct hci_cp_user_passkey_reply cp;
3113
Johan Hedberg1707c602013-03-15 17:07:15 -05003114 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003115 cp.passkey = passkey;
3116 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3117 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003118 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3119 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003120
Johan Hedberga664b5b2011-02-19 12:06:02 -03003121 if (err < 0)
3122 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003123
Brian Gix0df4c182011-11-16 13:53:13 -08003124done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003125 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003126 return err;
3127}
3128
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303129static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3130 void *data, u16 len)
3131{
3132 struct mgmt_cp_pin_code_neg_reply *cp = data;
3133
3134 BT_DBG("");
3135
Johan Hedberg1707c602013-03-15 17:07:15 -05003136 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303137 MGMT_OP_PIN_CODE_NEG_REPLY,
3138 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3139}
3140
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003141static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3142 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003143{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003144 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003145
3146 BT_DBG("");
3147
3148 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003149 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003150 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003151
Johan Hedberg1707c602013-03-15 17:07:15 -05003152 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003153 MGMT_OP_USER_CONFIRM_REPLY,
3154 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003155}
3156
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003157static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003158 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003159{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003160 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003161
3162 BT_DBG("");
3163
Johan Hedberg1707c602013-03-15 17:07:15 -05003164 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003165 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3166 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003167}
3168
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003169static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3170 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003171{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003172 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003173
3174 BT_DBG("");
3175
Johan Hedberg1707c602013-03-15 17:07:15 -05003176 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003177 MGMT_OP_USER_PASSKEY_REPLY,
3178 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003179}
3180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003181static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003182 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003183{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003184 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003185
3186 BT_DBG("");
3187
Johan Hedberg1707c602013-03-15 17:07:15 -05003188 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003189 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3190 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003191}
3192
Johan Hedberg13928972013-03-15 17:07:00 -05003193static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003194{
Johan Hedberg13928972013-03-15 17:07:00 -05003195 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003196 struct hci_cp_write_local_name cp;
3197
Johan Hedberg13928972013-03-15 17:07:00 -05003198 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003199
Johan Hedberg890ea892013-03-15 17:06:52 -05003200 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003201}
3202
Johan Hedberg13928972013-03-15 17:07:00 -05003203static void set_name_complete(struct hci_dev *hdev, u8 status)
3204{
3205 struct mgmt_cp_set_local_name *cp;
3206 struct pending_cmd *cmd;
3207
3208 BT_DBG("status 0x%02x", status);
3209
3210 hci_dev_lock(hdev);
3211
3212 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3213 if (!cmd)
3214 goto unlock;
3215
3216 cp = cmd->param;
3217
3218 if (status)
3219 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3220 mgmt_status(status));
3221 else
3222 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3223 cp, sizeof(*cp));
3224
3225 mgmt_pending_remove(cmd);
3226
3227unlock:
3228 hci_dev_unlock(hdev);
3229}
3230
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003231static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003232 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003233{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003234 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003235 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003236 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003237 int err;
3238
3239 BT_DBG("");
3240
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003241 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003242
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003243 /* If the old values are the same as the new ones just return a
3244 * direct command complete event.
3245 */
3246 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3247 !memcmp(hdev->short_name, cp->short_name,
3248 sizeof(hdev->short_name))) {
3249 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3250 data, len);
3251 goto failed;
3252 }
3253
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003254 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003255
Johan Hedbergb5235a62012-02-21 14:32:24 +02003256 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003257 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003258
3259 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003260 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003261 if (err < 0)
3262 goto failed;
3263
3264 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003265 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003266
Johan Hedbergb5235a62012-02-21 14:32:24 +02003267 goto failed;
3268 }
3269
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003270 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003271 if (!cmd) {
3272 err = -ENOMEM;
3273 goto failed;
3274 }
3275
Johan Hedberg13928972013-03-15 17:07:00 -05003276 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3277
Johan Hedberg890ea892013-03-15 17:06:52 -05003278 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003279
3280 if (lmp_bredr_capable(hdev)) {
3281 update_name(&req);
3282 update_eir(&req);
3283 }
3284
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003285 /* The name is stored in the scan response data and so
3286 * no need to udpate the advertising data here.
3287 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003288 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003289 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003290
Johan Hedberg13928972013-03-15 17:07:00 -05003291 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003292 if (err < 0)
3293 mgmt_pending_remove(cmd);
3294
3295failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003296 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003297 return err;
3298}
3299
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003300static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003301 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003302{
Szymon Jancc35938b2011-03-22 13:12:21 +01003303 struct pending_cmd *cmd;
3304 int err;
3305
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003306 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003307
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003308 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003309
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003310 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003311 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003312 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003313 goto unlock;
3314 }
3315
Andre Guedes9a1a1992012-07-24 15:03:48 -03003316 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003317 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003318 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003319 goto unlock;
3320 }
3321
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003322 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003323 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003324 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003325 goto unlock;
3326 }
3327
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003328 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003329 if (!cmd) {
3330 err = -ENOMEM;
3331 goto unlock;
3332 }
3333
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003334 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3335 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3336 0, NULL);
3337 else
3338 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3339
Szymon Jancc35938b2011-03-22 13:12:21 +01003340 if (err < 0)
3341 mgmt_pending_remove(cmd);
3342
3343unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003344 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003345 return err;
3346}
3347
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003348static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003349 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003350{
Szymon Janc2763eda2011-03-22 13:12:22 +01003351 int err;
3352
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003353 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003354
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003355 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003356
Marcel Holtmannec109112014-01-10 02:07:30 -08003357 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3358 struct mgmt_cp_add_remote_oob_data *cp = data;
3359 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003360
Marcel Holtmannec109112014-01-10 02:07:30 -08003361 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3362 cp->hash, cp->randomizer);
3363 if (err < 0)
3364 status = MGMT_STATUS_FAILED;
3365 else
3366 status = MGMT_STATUS_SUCCESS;
3367
3368 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3369 status, &cp->addr, sizeof(cp->addr));
3370 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3371 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3372 u8 status;
3373
3374 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3375 cp->hash192,
3376 cp->randomizer192,
3377 cp->hash256,
3378 cp->randomizer256);
3379 if (err < 0)
3380 status = MGMT_STATUS_FAILED;
3381 else
3382 status = MGMT_STATUS_SUCCESS;
3383
3384 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3385 status, &cp->addr, sizeof(cp->addr));
3386 } else {
3387 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3388 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3389 MGMT_STATUS_INVALID_PARAMS);
3390 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003391
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003392 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003393 return err;
3394}
3395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003396static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003397 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003398{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003399 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003400 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003401 int err;
3402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003403 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003405 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003406
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003407 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003408 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003409 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003410 else
Szymon Janca6785be2012-12-13 15:11:21 +01003411 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003412
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003413 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003414 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003415
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003416 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003417 return err;
3418}
3419
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003420static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3421{
3422 struct pending_cmd *cmd;
3423 u8 type;
3424 int err;
3425
3426 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3427
3428 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3429 if (!cmd)
3430 return -ENOENT;
3431
3432 type = hdev->discovery.type;
3433
3434 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3435 &type, sizeof(type));
3436 mgmt_pending_remove(cmd);
3437
3438 return err;
3439}
3440
Andre Guedes7c307722013-04-30 15:29:28 -03003441static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3442{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003443 unsigned long timeout = 0;
3444
Andre Guedes7c307722013-04-30 15:29:28 -03003445 BT_DBG("status %d", status);
3446
3447 if (status) {
3448 hci_dev_lock(hdev);
3449 mgmt_start_discovery_failed(hdev, status);
3450 hci_dev_unlock(hdev);
3451 return;
3452 }
3453
3454 hci_dev_lock(hdev);
3455 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3456 hci_dev_unlock(hdev);
3457
3458 switch (hdev->discovery.type) {
3459 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003460 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003461 break;
3462
3463 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003464 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003465 break;
3466
3467 case DISCOV_TYPE_BREDR:
3468 break;
3469
3470 default:
3471 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3472 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003473
3474 if (!timeout)
3475 return;
3476
3477 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003478}
3479
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003480static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003481 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003482{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003483 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003484 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003485 struct hci_cp_le_set_scan_param param_cp;
3486 struct hci_cp_le_set_scan_enable enable_cp;
3487 struct hci_cp_inquiry inq_cp;
3488 struct hci_request req;
3489 /* General inquiry access code (GIAC) */
3490 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003491 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003492 int err;
3493
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003494 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003495
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003496 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003497
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003498 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003499 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003500 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003501 goto failed;
3502 }
3503
Andre Guedes642be6c2012-03-21 00:03:37 -03003504 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3505 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3506 MGMT_STATUS_BUSY);
3507 goto failed;
3508 }
3509
Johan Hedbergff9ef572012-01-04 14:23:45 +02003510 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003511 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003512 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003513 goto failed;
3514 }
3515
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003516 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003517 if (!cmd) {
3518 err = -ENOMEM;
3519 goto failed;
3520 }
3521
Andre Guedes4aab14e2012-02-17 20:39:36 -03003522 hdev->discovery.type = cp->type;
3523
Andre Guedes7c307722013-04-30 15:29:28 -03003524 hci_req_init(&req, hdev);
3525
Andre Guedes4aab14e2012-02-17 20:39:36 -03003526 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003527 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003528 status = mgmt_bredr_support(hdev);
3529 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003530 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003531 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003532 mgmt_pending_remove(cmd);
3533 goto failed;
3534 }
3535
Andre Guedes7c307722013-04-30 15:29:28 -03003536 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3537 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3538 MGMT_STATUS_BUSY);
3539 mgmt_pending_remove(cmd);
3540 goto failed;
3541 }
3542
3543 hci_inquiry_cache_flush(hdev);
3544
3545 memset(&inq_cp, 0, sizeof(inq_cp));
3546 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003547 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003548 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003549 break;
3550
3551 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003552 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003553 status = mgmt_le_support(hdev);
3554 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003555 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003556 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003557 mgmt_pending_remove(cmd);
3558 goto failed;
3559 }
3560
Andre Guedes7c307722013-04-30 15:29:28 -03003561 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003562 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003563 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3564 MGMT_STATUS_NOT_SUPPORTED);
3565 mgmt_pending_remove(cmd);
3566 goto failed;
3567 }
3568
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003569 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003570 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3571 MGMT_STATUS_REJECTED);
3572 mgmt_pending_remove(cmd);
3573 goto failed;
3574 }
3575
Andre Guedesc54c3862014-02-26 20:21:50 -03003576 /* If controller is scanning, it means the background scanning
3577 * is running. Thus, we should temporarily stop it in order to
3578 * set the discovery scanning parameters.
3579 */
3580 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3581 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003582
3583 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003584
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003585 /* All active scans will be done with either a resolvable
3586 * private address (when privacy feature has been enabled)
3587 * or unresolvable private address.
3588 */
3589 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003590 if (err < 0) {
3591 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3592 MGMT_STATUS_FAILED);
3593 mgmt_pending_remove(cmd);
3594 goto failed;
3595 }
3596
Andre Guedes7c307722013-04-30 15:29:28 -03003597 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003598 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3599 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003600 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003601 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3602 &param_cp);
3603
3604 memset(&enable_cp, 0, sizeof(enable_cp));
3605 enable_cp.enable = LE_SCAN_ENABLE;
3606 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3607 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3608 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003609 break;
3610
Andre Guedesf39799f2012-02-17 20:39:35 -03003611 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003612 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3613 MGMT_STATUS_INVALID_PARAMS);
3614 mgmt_pending_remove(cmd);
3615 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003616 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003617
Andre Guedes7c307722013-04-30 15:29:28 -03003618 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003619 if (err < 0)
3620 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003621 else
3622 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003623
3624failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003625 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003626 return err;
3627}
3628
Andre Guedes1183fdc2013-04-30 15:29:35 -03003629static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3630{
3631 struct pending_cmd *cmd;
3632 int err;
3633
3634 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3635 if (!cmd)
3636 return -ENOENT;
3637
3638 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3639 &hdev->discovery.type, sizeof(hdev->discovery.type));
3640 mgmt_pending_remove(cmd);
3641
3642 return err;
3643}
3644
Andre Guedes0e05bba2013-04-30 15:29:33 -03003645static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3646{
3647 BT_DBG("status %d", status);
3648
3649 hci_dev_lock(hdev);
3650
3651 if (status) {
3652 mgmt_stop_discovery_failed(hdev, status);
3653 goto unlock;
3654 }
3655
3656 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3657
3658unlock:
3659 hci_dev_unlock(hdev);
3660}
3661
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003662static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003663 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003664{
Johan Hedbergd9306502012-02-20 23:25:18 +02003665 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003666 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003667 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003668 int err;
3669
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003670 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003671
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003672 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003673
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003674 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003675 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003676 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3677 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003678 goto unlock;
3679 }
3680
3681 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003682 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003683 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3684 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003685 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003686 }
3687
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003688 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003689 if (!cmd) {
3690 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003691 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003692 }
3693
Andre Guedes0e05bba2013-04-30 15:29:33 -03003694 hci_req_init(&req, hdev);
3695
Johan Hedberg21a60d32014-06-10 14:05:58 +03003696 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003697
Johan Hedberg21a60d32014-06-10 14:05:58 +03003698 err = hci_req_run(&req, stop_discovery_complete);
3699 if (!err) {
3700 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003701 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003702 }
3703
Johan Hedberg21a60d32014-06-10 14:05:58 +03003704 mgmt_pending_remove(cmd);
3705
3706 /* If no HCI commands were sent we're done */
3707 if (err == -ENODATA) {
3708 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3709 &mgmt_cp->type, sizeof(mgmt_cp->type));
3710 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3711 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003712
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003713unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003714 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003715 return err;
3716}
3717
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003718static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003719 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003720{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003721 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003722 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003723 int err;
3724
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003725 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003726
Johan Hedberg561aafb2012-01-04 13:31:59 +02003727 hci_dev_lock(hdev);
3728
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003729 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003730 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3731 MGMT_STATUS_FAILED, &cp->addr,
3732 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003733 goto failed;
3734 }
3735
Johan Hedberga198e7b2012-02-17 14:27:06 +02003736 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003737 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003738 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3739 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3740 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003741 goto failed;
3742 }
3743
3744 if (cp->name_known) {
3745 e->name_state = NAME_KNOWN;
3746 list_del(&e->list);
3747 } else {
3748 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003749 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003750 }
3751
Johan Hedberge3846622013-01-09 15:29:33 +02003752 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3753 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003754
3755failed:
3756 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003757 return err;
3758}
3759
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003760static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003761 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003762{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003763 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003764 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003765 int err;
3766
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003767 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003768
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003769 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003770 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3771 MGMT_STATUS_INVALID_PARAMS,
3772 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003773
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003774 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003775
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003776 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003777 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003778 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003779 goto done;
3780 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003781
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003782 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3783 sk);
3784 status = MGMT_STATUS_SUCCESS;
3785
3786done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003787 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003788 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003789
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003790 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003791
3792 return err;
3793}
3794
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003795static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003796 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003797{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003798 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003799 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003800 int err;
3801
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003802 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003803
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003804 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003805 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3806 MGMT_STATUS_INVALID_PARAMS,
3807 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003808
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003809 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003810
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003811 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003812 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003813 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003814 goto done;
3815 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003816
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003817 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3818 sk);
3819 status = MGMT_STATUS_SUCCESS;
3820
3821done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003822 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003823 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003824
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003825 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003826
3827 return err;
3828}
3829
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003830static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3831 u16 len)
3832{
3833 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003834 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003835 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003836 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003837
3838 BT_DBG("%s", hdev->name);
3839
Szymon Jancc72d4b82012-03-16 16:02:57 +01003840 source = __le16_to_cpu(cp->source);
3841
3842 if (source > 0x0002)
3843 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3844 MGMT_STATUS_INVALID_PARAMS);
3845
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003846 hci_dev_lock(hdev);
3847
Szymon Jancc72d4b82012-03-16 16:02:57 +01003848 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003849 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3850 hdev->devid_product = __le16_to_cpu(cp->product);
3851 hdev->devid_version = __le16_to_cpu(cp->version);
3852
3853 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3854
Johan Hedberg890ea892013-03-15 17:06:52 -05003855 hci_req_init(&req, hdev);
3856 update_eir(&req);
3857 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003858
3859 hci_dev_unlock(hdev);
3860
3861 return err;
3862}
3863
Johan Hedberg4375f102013-09-25 13:26:10 +03003864static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3865{
3866 struct cmd_lookup match = { NULL, hdev };
3867
3868 if (status) {
3869 u8 mgmt_err = mgmt_status(status);
3870
3871 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3872 cmd_status_rsp, &mgmt_err);
3873 return;
3874 }
3875
3876 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3877 &match);
3878
3879 new_settings(hdev, match.sk);
3880
3881 if (match.sk)
3882 sock_put(match.sk);
3883}
3884
Marcel Holtmann21b51872013-10-10 09:47:53 -07003885static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3886 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003887{
3888 struct mgmt_mode *cp = data;
3889 struct pending_cmd *cmd;
3890 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003891 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003892 int err;
3893
3894 BT_DBG("request for %s", hdev->name);
3895
Johan Hedberge6fe7982013-10-02 15:45:22 +03003896 status = mgmt_le_support(hdev);
3897 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003898 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003899 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003900
3901 if (cp->val != 0x00 && cp->val != 0x01)
3902 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3903 MGMT_STATUS_INVALID_PARAMS);
3904
3905 hci_dev_lock(hdev);
3906
3907 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003908 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003909
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003910 /* The following conditions are ones which mean that we should
3911 * not do any HCI communication but directly send a mgmt
3912 * response to user space (after toggling the flag if
3913 * necessary).
3914 */
3915 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003916 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003917 bool changed = false;
3918
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003919 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3920 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003921 changed = true;
3922 }
3923
3924 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3925 if (err < 0)
3926 goto unlock;
3927
3928 if (changed)
3929 err = new_settings(hdev, sk);
3930
3931 goto unlock;
3932 }
3933
3934 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3935 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3936 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3937 MGMT_STATUS_BUSY);
3938 goto unlock;
3939 }
3940
3941 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3942 if (!cmd) {
3943 err = -ENOMEM;
3944 goto unlock;
3945 }
3946
3947 hci_req_init(&req, hdev);
3948
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003949 if (val)
3950 enable_advertising(&req);
3951 else
3952 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003953
3954 err = hci_req_run(&req, set_advertising_complete);
3955 if (err < 0)
3956 mgmt_pending_remove(cmd);
3957
3958unlock:
3959 hci_dev_unlock(hdev);
3960 return err;
3961}
3962
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003963static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3964 void *data, u16 len)
3965{
3966 struct mgmt_cp_set_static_address *cp = data;
3967 int err;
3968
3969 BT_DBG("%s", hdev->name);
3970
Marcel Holtmann62af4442013-10-02 22:10:32 -07003971 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003972 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003973 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003974
3975 if (hdev_is_powered(hdev))
3976 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3977 MGMT_STATUS_REJECTED);
3978
3979 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3980 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3981 return cmd_status(sk, hdev->id,
3982 MGMT_OP_SET_STATIC_ADDRESS,
3983 MGMT_STATUS_INVALID_PARAMS);
3984
3985 /* Two most significant bits shall be set */
3986 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3987 return cmd_status(sk, hdev->id,
3988 MGMT_OP_SET_STATIC_ADDRESS,
3989 MGMT_STATUS_INVALID_PARAMS);
3990 }
3991
3992 hci_dev_lock(hdev);
3993
3994 bacpy(&hdev->static_addr, &cp->bdaddr);
3995
3996 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3997
3998 hci_dev_unlock(hdev);
3999
4000 return err;
4001}
4002
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004003static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4004 void *data, u16 len)
4005{
4006 struct mgmt_cp_set_scan_params *cp = data;
4007 __u16 interval, window;
4008 int err;
4009
4010 BT_DBG("%s", hdev->name);
4011
4012 if (!lmp_le_capable(hdev))
4013 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4014 MGMT_STATUS_NOT_SUPPORTED);
4015
4016 interval = __le16_to_cpu(cp->interval);
4017
4018 if (interval < 0x0004 || interval > 0x4000)
4019 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4020 MGMT_STATUS_INVALID_PARAMS);
4021
4022 window = __le16_to_cpu(cp->window);
4023
4024 if (window < 0x0004 || window > 0x4000)
4025 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4026 MGMT_STATUS_INVALID_PARAMS);
4027
Marcel Holtmann899e1072013-10-14 09:55:32 -07004028 if (window > interval)
4029 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4030 MGMT_STATUS_INVALID_PARAMS);
4031
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004032 hci_dev_lock(hdev);
4033
4034 hdev->le_scan_interval = interval;
4035 hdev->le_scan_window = window;
4036
4037 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4038
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004039 /* If background scan is running, restart it so new parameters are
4040 * loaded.
4041 */
4042 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4043 hdev->discovery.state == DISCOVERY_STOPPED) {
4044 struct hci_request req;
4045
4046 hci_req_init(&req, hdev);
4047
4048 hci_req_add_le_scan_disable(&req);
4049 hci_req_add_le_passive_scan(&req);
4050
4051 hci_req_run(&req, NULL);
4052 }
4053
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004054 hci_dev_unlock(hdev);
4055
4056 return err;
4057}
4058
Johan Hedberg33e38b32013-03-15 17:07:05 -05004059static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4060{
4061 struct pending_cmd *cmd;
4062
4063 BT_DBG("status 0x%02x", status);
4064
4065 hci_dev_lock(hdev);
4066
4067 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4068 if (!cmd)
4069 goto unlock;
4070
4071 if (status) {
4072 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4073 mgmt_status(status));
4074 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004075 struct mgmt_mode *cp = cmd->param;
4076
4077 if (cp->val)
4078 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4079 else
4080 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4081
Johan Hedberg33e38b32013-03-15 17:07:05 -05004082 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4083 new_settings(hdev, cmd->sk);
4084 }
4085
4086 mgmt_pending_remove(cmd);
4087
4088unlock:
4089 hci_dev_unlock(hdev);
4090}
4091
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004092static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004093 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004094{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004095 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004096 struct pending_cmd *cmd;
4097 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004098 int err;
4099
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004100 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004101
Johan Hedberg56f87902013-10-02 13:43:13 +03004102 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4103 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004104 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4105 MGMT_STATUS_NOT_SUPPORTED);
4106
Johan Hedberga7e80f22013-01-09 16:05:19 +02004107 if (cp->val != 0x00 && cp->val != 0x01)
4108 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4109 MGMT_STATUS_INVALID_PARAMS);
4110
Johan Hedberg5400c042012-02-21 16:40:33 +02004111 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004112 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004113 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004114
4115 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004116 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004117 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004118
4119 hci_dev_lock(hdev);
4120
Johan Hedberg05cbf292013-03-15 17:07:07 -05004121 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4122 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4123 MGMT_STATUS_BUSY);
4124 goto unlock;
4125 }
4126
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004127 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4128 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4129 hdev);
4130 goto unlock;
4131 }
4132
Johan Hedberg33e38b32013-03-15 17:07:05 -05004133 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4134 data, len);
4135 if (!cmd) {
4136 err = -ENOMEM;
4137 goto unlock;
4138 }
4139
4140 hci_req_init(&req, hdev);
4141
Johan Hedberg406d7802013-03-15 17:07:09 -05004142 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004143
4144 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004145 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004146 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004147 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004148 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004149 }
4150
Johan Hedberg33e38b32013-03-15 17:07:05 -05004151unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004152 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004153
Antti Julkuf6422ec2011-06-22 13:11:56 +03004154 return err;
4155}
4156
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004157static void set_bredr_scan(struct hci_request *req)
4158{
4159 struct hci_dev *hdev = req->hdev;
4160 u8 scan = 0;
4161
4162 /* Ensure that fast connectable is disabled. This function will
4163 * not do anything if the page scan parameters are already what
4164 * they should be.
4165 */
4166 write_fast_connectable(req, false);
4167
4168 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4169 scan |= SCAN_PAGE;
4170 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4171 scan |= SCAN_INQUIRY;
4172
4173 if (scan)
4174 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4175}
4176
Johan Hedberg0663ca22013-10-02 13:43:14 +03004177static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4178{
4179 struct pending_cmd *cmd;
4180
4181 BT_DBG("status 0x%02x", status);
4182
4183 hci_dev_lock(hdev);
4184
4185 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4186 if (!cmd)
4187 goto unlock;
4188
4189 if (status) {
4190 u8 mgmt_err = mgmt_status(status);
4191
4192 /* We need to restore the flag if related HCI commands
4193 * failed.
4194 */
4195 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4196
4197 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4198 } else {
4199 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4200 new_settings(hdev, cmd->sk);
4201 }
4202
4203 mgmt_pending_remove(cmd);
4204
4205unlock:
4206 hci_dev_unlock(hdev);
4207}
4208
4209static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4210{
4211 struct mgmt_mode *cp = data;
4212 struct pending_cmd *cmd;
4213 struct hci_request req;
4214 int err;
4215
4216 BT_DBG("request for %s", hdev->name);
4217
4218 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4219 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4220 MGMT_STATUS_NOT_SUPPORTED);
4221
4222 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4223 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4224 MGMT_STATUS_REJECTED);
4225
4226 if (cp->val != 0x00 && cp->val != 0x01)
4227 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4228 MGMT_STATUS_INVALID_PARAMS);
4229
4230 hci_dev_lock(hdev);
4231
4232 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4233 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4234 goto unlock;
4235 }
4236
4237 if (!hdev_is_powered(hdev)) {
4238 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004239 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4240 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4241 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4242 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4243 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4244 }
4245
4246 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4247
4248 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4249 if (err < 0)
4250 goto unlock;
4251
4252 err = new_settings(hdev, sk);
4253 goto unlock;
4254 }
4255
4256 /* Reject disabling when powered on */
4257 if (!cp->val) {
4258 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4259 MGMT_STATUS_REJECTED);
4260 goto unlock;
4261 }
4262
4263 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4264 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4265 MGMT_STATUS_BUSY);
4266 goto unlock;
4267 }
4268
4269 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4270 if (!cmd) {
4271 err = -ENOMEM;
4272 goto unlock;
4273 }
4274
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004275 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004276 * generates the correct flags.
4277 */
4278 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4279
4280 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004281
4282 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4283 set_bredr_scan(&req);
4284
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004285 /* Since only the advertising data flags will change, there
4286 * is no need to update the scan response data.
4287 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004288 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004289
Johan Hedberg0663ca22013-10-02 13:43:14 +03004290 err = hci_req_run(&req, set_bredr_complete);
4291 if (err < 0)
4292 mgmt_pending_remove(cmd);
4293
4294unlock:
4295 hci_dev_unlock(hdev);
4296 return err;
4297}
4298
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004299static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4300 void *data, u16 len)
4301{
4302 struct mgmt_mode *cp = data;
4303 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004304 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004305 int err;
4306
4307 BT_DBG("request for %s", hdev->name);
4308
4309 status = mgmt_bredr_support(hdev);
4310 if (status)
4311 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4312 status);
4313
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004314 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004315 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004316 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4317 MGMT_STATUS_NOT_SUPPORTED);
4318
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004319 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004320 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4321 MGMT_STATUS_INVALID_PARAMS);
4322
4323 hci_dev_lock(hdev);
4324
4325 if (!hdev_is_powered(hdev)) {
4326 bool changed;
4327
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004328 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004329 changed = !test_and_set_bit(HCI_SC_ENABLED,
4330 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004331 if (cp->val == 0x02)
4332 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4333 else
4334 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4335 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004336 changed = test_and_clear_bit(HCI_SC_ENABLED,
4337 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004338 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4339 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004340
4341 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4342 if (err < 0)
4343 goto failed;
4344
4345 if (changed)
4346 err = new_settings(hdev, sk);
4347
4348 goto failed;
4349 }
4350
4351 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4352 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4353 MGMT_STATUS_BUSY);
4354 goto failed;
4355 }
4356
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004357 val = !!cp->val;
4358
4359 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4360 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004361 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4362 goto failed;
4363 }
4364
4365 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4366 if (!cmd) {
4367 err = -ENOMEM;
4368 goto failed;
4369 }
4370
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004371 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004372 if (err < 0) {
4373 mgmt_pending_remove(cmd);
4374 goto failed;
4375 }
4376
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004377 if (cp->val == 0x02)
4378 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4379 else
4380 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4381
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004382failed:
4383 hci_dev_unlock(hdev);
4384 return err;
4385}
4386
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004387static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4388 void *data, u16 len)
4389{
4390 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004391 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004392 int err;
4393
4394 BT_DBG("request for %s", hdev->name);
4395
Johan Hedbergb97109792014-06-24 14:00:28 +03004396 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004397 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4398 MGMT_STATUS_INVALID_PARAMS);
4399
4400 hci_dev_lock(hdev);
4401
4402 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004403 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4404 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004405 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004406 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4407 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004408
Johan Hedbergb97109792014-06-24 14:00:28 +03004409 if (cp->val == 0x02)
4410 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4411 &hdev->dev_flags);
4412 else
4413 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4414 &hdev->dev_flags);
4415
4416 if (hdev_is_powered(hdev) && use_changed &&
4417 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4418 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4419 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4420 sizeof(mode), &mode);
4421 }
4422
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004423 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4424 if (err < 0)
4425 goto unlock;
4426
4427 if (changed)
4428 err = new_settings(hdev, sk);
4429
4430unlock:
4431 hci_dev_unlock(hdev);
4432 return err;
4433}
4434
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004435static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4436 u16 len)
4437{
4438 struct mgmt_cp_set_privacy *cp = cp_data;
4439 bool changed;
4440 int err;
4441
4442 BT_DBG("request for %s", hdev->name);
4443
4444 if (!lmp_le_capable(hdev))
4445 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4446 MGMT_STATUS_NOT_SUPPORTED);
4447
4448 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4449 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4450 MGMT_STATUS_INVALID_PARAMS);
4451
4452 if (hdev_is_powered(hdev))
4453 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4454 MGMT_STATUS_REJECTED);
4455
4456 hci_dev_lock(hdev);
4457
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004458 /* If user space supports this command it is also expected to
4459 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4460 */
4461 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4462
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004463 if (cp->privacy) {
4464 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4465 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4466 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4467 } else {
4468 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4469 memset(hdev->irk, 0, sizeof(hdev->irk));
4470 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4471 }
4472
4473 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4474 if (err < 0)
4475 goto unlock;
4476
4477 if (changed)
4478 err = new_settings(hdev, sk);
4479
4480unlock:
4481 hci_dev_unlock(hdev);
4482 return err;
4483}
4484
Johan Hedberg41edf162014-02-18 10:19:35 +02004485static bool irk_is_valid(struct mgmt_irk_info *irk)
4486{
4487 switch (irk->addr.type) {
4488 case BDADDR_LE_PUBLIC:
4489 return true;
4490
4491 case BDADDR_LE_RANDOM:
4492 /* Two most significant bits shall be set */
4493 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4494 return false;
4495 return true;
4496 }
4497
4498 return false;
4499}
4500
4501static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4502 u16 len)
4503{
4504 struct mgmt_cp_load_irks *cp = cp_data;
4505 u16 irk_count, expected_len;
4506 int i, err;
4507
4508 BT_DBG("request for %s", hdev->name);
4509
4510 if (!lmp_le_capable(hdev))
4511 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4512 MGMT_STATUS_NOT_SUPPORTED);
4513
4514 irk_count = __le16_to_cpu(cp->irk_count);
4515
4516 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4517 if (expected_len != len) {
4518 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004519 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004520 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4521 MGMT_STATUS_INVALID_PARAMS);
4522 }
4523
4524 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4525
4526 for (i = 0; i < irk_count; i++) {
4527 struct mgmt_irk_info *key = &cp->irks[i];
4528
4529 if (!irk_is_valid(key))
4530 return cmd_status(sk, hdev->id,
4531 MGMT_OP_LOAD_IRKS,
4532 MGMT_STATUS_INVALID_PARAMS);
4533 }
4534
4535 hci_dev_lock(hdev);
4536
4537 hci_smp_irks_clear(hdev);
4538
4539 for (i = 0; i < irk_count; i++) {
4540 struct mgmt_irk_info *irk = &cp->irks[i];
4541 u8 addr_type;
4542
4543 if (irk->addr.type == BDADDR_LE_PUBLIC)
4544 addr_type = ADDR_LE_DEV_PUBLIC;
4545 else
4546 addr_type = ADDR_LE_DEV_RANDOM;
4547
4548 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4549 BDADDR_ANY);
4550 }
4551
4552 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4553
4554 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4555
4556 hci_dev_unlock(hdev);
4557
4558 return err;
4559}
4560
Johan Hedberg3f706b72013-01-20 14:27:16 +02004561static bool ltk_is_valid(struct mgmt_ltk_info *key)
4562{
4563 if (key->master != 0x00 && key->master != 0x01)
4564 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004565
4566 switch (key->addr.type) {
4567 case BDADDR_LE_PUBLIC:
4568 return true;
4569
4570 case BDADDR_LE_RANDOM:
4571 /* Two most significant bits shall be set */
4572 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4573 return false;
4574 return true;
4575 }
4576
4577 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004578}
4579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004580static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004581 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004582{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004583 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4584 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004585 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004586
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004587 BT_DBG("request for %s", hdev->name);
4588
4589 if (!lmp_le_capable(hdev))
4590 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4591 MGMT_STATUS_NOT_SUPPORTED);
4592
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004593 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004594
4595 expected_len = sizeof(*cp) + key_count *
4596 sizeof(struct mgmt_ltk_info);
4597 if (expected_len != len) {
4598 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004599 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004600 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004601 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004602 }
4603
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004604 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004605
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004606 for (i = 0; i < key_count; i++) {
4607 struct mgmt_ltk_info *key = &cp->keys[i];
4608
Johan Hedberg3f706b72013-01-20 14:27:16 +02004609 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004610 return cmd_status(sk, hdev->id,
4611 MGMT_OP_LOAD_LONG_TERM_KEYS,
4612 MGMT_STATUS_INVALID_PARAMS);
4613 }
4614
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004615 hci_dev_lock(hdev);
4616
4617 hci_smp_ltks_clear(hdev);
4618
4619 for (i = 0; i < key_count; i++) {
4620 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004621 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004622
4623 if (key->addr.type == BDADDR_LE_PUBLIC)
4624 addr_type = ADDR_LE_DEV_PUBLIC;
4625 else
4626 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004627
4628 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004629 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004630 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004631 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004632
Johan Hedberg61b43352014-05-29 19:36:53 +03004633 switch (key->type) {
4634 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004635 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004636 break;
4637 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004638 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004639 break;
4640 default:
4641 continue;
4642 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004643
Johan Hedberg35d70272014-02-19 14:57:47 +02004644 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004645 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004646 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004647 }
4648
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004649 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4650 NULL, 0);
4651
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004652 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004653
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004654 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004655}
4656
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004657struct cmd_conn_lookup {
4658 struct hci_conn *conn;
4659 bool valid_tx_power;
4660 u8 mgmt_status;
4661};
4662
4663static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4664{
4665 struct cmd_conn_lookup *match = data;
4666 struct mgmt_cp_get_conn_info *cp;
4667 struct mgmt_rp_get_conn_info rp;
4668 struct hci_conn *conn = cmd->user_data;
4669
4670 if (conn != match->conn)
4671 return;
4672
4673 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4674
4675 memset(&rp, 0, sizeof(rp));
4676 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4677 rp.addr.type = cp->addr.type;
4678
4679 if (!match->mgmt_status) {
4680 rp.rssi = conn->rssi;
4681
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004682 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004683 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004684 rp.max_tx_power = conn->max_tx_power;
4685 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004686 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004687 rp.max_tx_power = HCI_TX_POWER_INVALID;
4688 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004689 }
4690
4691 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4692 match->mgmt_status, &rp, sizeof(rp));
4693
4694 hci_conn_drop(conn);
4695
4696 mgmt_pending_remove(cmd);
4697}
4698
4699static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4700{
4701 struct hci_cp_read_rssi *cp;
4702 struct hci_conn *conn;
4703 struct cmd_conn_lookup match;
4704 u16 handle;
4705
4706 BT_DBG("status 0x%02x", status);
4707
4708 hci_dev_lock(hdev);
4709
4710 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004711 * otherwise we assume it's not valid. At the moment we assume that
4712 * either both or none of current and max values are valid to keep code
4713 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004714 */
4715 match.valid_tx_power = !status;
4716
4717 /* Commands sent in request are either Read RSSI or Read Transmit Power
4718 * Level so we check which one was last sent to retrieve connection
4719 * handle. Both commands have handle as first parameter so it's safe to
4720 * cast data on the same command struct.
4721 *
4722 * First command sent is always Read RSSI and we fail only if it fails.
4723 * In other case we simply override error to indicate success as we
4724 * already remembered if TX power value is actually valid.
4725 */
4726 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4727 if (!cp) {
4728 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4729 status = 0;
4730 }
4731
4732 if (!cp) {
4733 BT_ERR("invalid sent_cmd in response");
4734 goto unlock;
4735 }
4736
4737 handle = __le16_to_cpu(cp->handle);
4738 conn = hci_conn_hash_lookup_handle(hdev, handle);
4739 if (!conn) {
4740 BT_ERR("unknown handle (%d) in response", handle);
4741 goto unlock;
4742 }
4743
4744 match.conn = conn;
4745 match.mgmt_status = mgmt_status(status);
4746
4747 /* Cache refresh is complete, now reply for mgmt request for given
4748 * connection only.
4749 */
4750 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4751 get_conn_info_complete, &match);
4752
4753unlock:
4754 hci_dev_unlock(hdev);
4755}
4756
4757static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4758 u16 len)
4759{
4760 struct mgmt_cp_get_conn_info *cp = data;
4761 struct mgmt_rp_get_conn_info rp;
4762 struct hci_conn *conn;
4763 unsigned long conn_info_age;
4764 int err = 0;
4765
4766 BT_DBG("%s", hdev->name);
4767
4768 memset(&rp, 0, sizeof(rp));
4769 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4770 rp.addr.type = cp->addr.type;
4771
4772 if (!bdaddr_type_is_valid(cp->addr.type))
4773 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4774 MGMT_STATUS_INVALID_PARAMS,
4775 &rp, sizeof(rp));
4776
4777 hci_dev_lock(hdev);
4778
4779 if (!hdev_is_powered(hdev)) {
4780 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4781 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4782 goto unlock;
4783 }
4784
4785 if (cp->addr.type == BDADDR_BREDR)
4786 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4787 &cp->addr.bdaddr);
4788 else
4789 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4790
4791 if (!conn || conn->state != BT_CONNECTED) {
4792 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4793 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4794 goto unlock;
4795 }
4796
4797 /* To avoid client trying to guess when to poll again for information we
4798 * calculate conn info age as random value between min/max set in hdev.
4799 */
4800 conn_info_age = hdev->conn_info_min_age +
4801 prandom_u32_max(hdev->conn_info_max_age -
4802 hdev->conn_info_min_age);
4803
4804 /* Query controller to refresh cached values if they are too old or were
4805 * never read.
4806 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004807 if (time_after(jiffies, conn->conn_info_timestamp +
4808 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004809 !conn->conn_info_timestamp) {
4810 struct hci_request req;
4811 struct hci_cp_read_tx_power req_txp_cp;
4812 struct hci_cp_read_rssi req_rssi_cp;
4813 struct pending_cmd *cmd;
4814
4815 hci_req_init(&req, hdev);
4816 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4817 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4818 &req_rssi_cp);
4819
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004820 /* For LE links TX power does not change thus we don't need to
4821 * query for it once value is known.
4822 */
4823 if (!bdaddr_type_is_le(cp->addr.type) ||
4824 conn->tx_power == HCI_TX_POWER_INVALID) {
4825 req_txp_cp.handle = cpu_to_le16(conn->handle);
4826 req_txp_cp.type = 0x00;
4827 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4828 sizeof(req_txp_cp), &req_txp_cp);
4829 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004830
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004831 /* Max TX power needs to be read only once per connection */
4832 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4833 req_txp_cp.handle = cpu_to_le16(conn->handle);
4834 req_txp_cp.type = 0x01;
4835 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4836 sizeof(req_txp_cp), &req_txp_cp);
4837 }
4838
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004839 err = hci_req_run(&req, conn_info_refresh_complete);
4840 if (err < 0)
4841 goto unlock;
4842
4843 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4844 data, len);
4845 if (!cmd) {
4846 err = -ENOMEM;
4847 goto unlock;
4848 }
4849
4850 hci_conn_hold(conn);
4851 cmd->user_data = conn;
4852
4853 conn->conn_info_timestamp = jiffies;
4854 } else {
4855 /* Cache is valid, just reply with values cached in hci_conn */
4856 rp.rssi = conn->rssi;
4857 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004858 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004859
4860 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4861 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4862 }
4863
4864unlock:
4865 hci_dev_unlock(hdev);
4866 return err;
4867}
4868
Johan Hedberg95868422014-06-28 17:54:07 +03004869static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4870{
4871 struct mgmt_cp_get_clock_info *cp;
4872 struct mgmt_rp_get_clock_info rp;
4873 struct hci_cp_read_clock *hci_cp;
4874 struct pending_cmd *cmd;
4875 struct hci_conn *conn;
4876
4877 BT_DBG("%s status %u", hdev->name, status);
4878
4879 hci_dev_lock(hdev);
4880
4881 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4882 if (!hci_cp)
4883 goto unlock;
4884
4885 if (hci_cp->which) {
4886 u16 handle = __le16_to_cpu(hci_cp->handle);
4887 conn = hci_conn_hash_lookup_handle(hdev, handle);
4888 } else {
4889 conn = NULL;
4890 }
4891
4892 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4893 if (!cmd)
4894 goto unlock;
4895
4896 cp = cmd->param;
4897
4898 memset(&rp, 0, sizeof(rp));
4899 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4900
4901 if (status)
4902 goto send_rsp;
4903
4904 rp.local_clock = cpu_to_le32(hdev->clock);
4905
4906 if (conn) {
4907 rp.piconet_clock = cpu_to_le32(conn->clock);
4908 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4909 }
4910
4911send_rsp:
4912 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4913 &rp, sizeof(rp));
4914 mgmt_pending_remove(cmd);
4915 if (conn)
4916 hci_conn_drop(conn);
4917
4918unlock:
4919 hci_dev_unlock(hdev);
4920}
4921
4922static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4923 u16 len)
4924{
4925 struct mgmt_cp_get_clock_info *cp = data;
4926 struct mgmt_rp_get_clock_info rp;
4927 struct hci_cp_read_clock hci_cp;
4928 struct pending_cmd *cmd;
4929 struct hci_request req;
4930 struct hci_conn *conn;
4931 int err;
4932
4933 BT_DBG("%s", hdev->name);
4934
4935 memset(&rp, 0, sizeof(rp));
4936 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4937 rp.addr.type = cp->addr.type;
4938
4939 if (cp->addr.type != BDADDR_BREDR)
4940 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4941 MGMT_STATUS_INVALID_PARAMS,
4942 &rp, sizeof(rp));
4943
4944 hci_dev_lock(hdev);
4945
4946 if (!hdev_is_powered(hdev)) {
4947 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4948 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4949 goto unlock;
4950 }
4951
4952 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4953 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4954 &cp->addr.bdaddr);
4955 if (!conn || conn->state != BT_CONNECTED) {
4956 err = cmd_complete(sk, hdev->id,
4957 MGMT_OP_GET_CLOCK_INFO,
4958 MGMT_STATUS_NOT_CONNECTED,
4959 &rp, sizeof(rp));
4960 goto unlock;
4961 }
4962 } else {
4963 conn = NULL;
4964 }
4965
4966 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4967 if (!cmd) {
4968 err = -ENOMEM;
4969 goto unlock;
4970 }
4971
4972 hci_req_init(&req, hdev);
4973
4974 memset(&hci_cp, 0, sizeof(hci_cp));
4975 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4976
4977 if (conn) {
4978 hci_conn_hold(conn);
4979 cmd->user_data = conn;
4980
4981 hci_cp.handle = cpu_to_le16(conn->handle);
4982 hci_cp.which = 0x01; /* Piconet clock */
4983 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4984 }
4985
4986 err = hci_req_run(&req, get_clock_info_complete);
4987 if (err < 0)
4988 mgmt_pending_remove(cmd);
4989
4990unlock:
4991 hci_dev_unlock(hdev);
4992 return err;
4993}
4994
Marcel Holtmann8afef092014-06-29 22:28:34 +02004995static void device_added(struct sock *sk, struct hci_dev *hdev,
4996 bdaddr_t *bdaddr, u8 type, u8 action)
4997{
4998 struct mgmt_ev_device_added ev;
4999
5000 bacpy(&ev.addr.bdaddr, bdaddr);
5001 ev.addr.type = type;
5002 ev.action = action;
5003
5004 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5005}
5006
Marcel Holtmann2faade52014-06-29 19:44:03 +02005007static int add_device(struct sock *sk, struct hci_dev *hdev,
5008 void *data, u16 len)
5009{
5010 struct mgmt_cp_add_device *cp = data;
5011 u8 auto_conn, addr_type;
5012 int err;
5013
5014 BT_DBG("%s", hdev->name);
5015
5016 if (!bdaddr_type_is_le(cp->addr.type) ||
5017 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5018 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5019 MGMT_STATUS_INVALID_PARAMS,
5020 &cp->addr, sizeof(cp->addr));
5021
5022 if (cp->action != 0x00 && cp->action != 0x01)
5023 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5024 MGMT_STATUS_INVALID_PARAMS,
5025 &cp->addr, sizeof(cp->addr));
5026
5027 hci_dev_lock(hdev);
5028
5029 if (cp->addr.type == BDADDR_LE_PUBLIC)
5030 addr_type = ADDR_LE_DEV_PUBLIC;
5031 else
5032 addr_type = ADDR_LE_DEV_RANDOM;
5033
5034 if (cp->action)
5035 auto_conn = HCI_AUTO_CONN_ALWAYS;
5036 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005037 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005038
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005039 /* If the connection parameters don't exist for this device,
5040 * they will be created and configured with defaults.
5041 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005042 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5043 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005044 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5045 MGMT_STATUS_FAILED,
5046 &cp->addr, sizeof(cp->addr));
5047 goto unlock;
5048 }
5049
Marcel Holtmann8afef092014-06-29 22:28:34 +02005050 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5051
Marcel Holtmann2faade52014-06-29 19:44:03 +02005052 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5053 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5054
5055unlock:
5056 hci_dev_unlock(hdev);
5057 return err;
5058}
5059
Marcel Holtmann8afef092014-06-29 22:28:34 +02005060static void device_removed(struct sock *sk, struct hci_dev *hdev,
5061 bdaddr_t *bdaddr, u8 type)
5062{
5063 struct mgmt_ev_device_removed ev;
5064
5065 bacpy(&ev.addr.bdaddr, bdaddr);
5066 ev.addr.type = type;
5067
5068 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5069}
5070
Marcel Holtmann2faade52014-06-29 19:44:03 +02005071static int remove_device(struct sock *sk, struct hci_dev *hdev,
5072 void *data, u16 len)
5073{
5074 struct mgmt_cp_remove_device *cp = data;
5075 int err;
5076
5077 BT_DBG("%s", hdev->name);
5078
5079 hci_dev_lock(hdev);
5080
5081 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5082 u8 addr_type;
5083
5084 if (!bdaddr_type_is_le(cp->addr.type)) {
5085 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5086 MGMT_STATUS_INVALID_PARAMS,
5087 &cp->addr, sizeof(cp->addr));
5088 goto unlock;
5089 }
5090
5091 if (cp->addr.type == BDADDR_LE_PUBLIC)
5092 addr_type = ADDR_LE_DEV_PUBLIC;
5093 else
5094 addr_type = ADDR_LE_DEV_RANDOM;
5095
5096 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005097
5098 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005099 } else {
5100 if (cp->addr.type) {
5101 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5102 MGMT_STATUS_INVALID_PARAMS,
5103 &cp->addr, sizeof(cp->addr));
5104 goto unlock;
5105 }
5106
Johan Hedberg373110c2014-07-02 17:37:25 +03005107 hci_conn_params_clear_all(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005108 }
5109
5110 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5111 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5112
5113unlock:
5114 hci_dev_unlock(hdev);
5115 return err;
5116}
5117
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005118static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005119 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5120 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005121 bool var_len;
5122 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005123} mgmt_handlers[] = {
5124 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005125 { read_version, false, MGMT_READ_VERSION_SIZE },
5126 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5127 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5128 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5129 { set_powered, false, MGMT_SETTING_SIZE },
5130 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5131 { set_connectable, false, MGMT_SETTING_SIZE },
5132 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5133 { set_pairable, false, MGMT_SETTING_SIZE },
5134 { set_link_security, false, MGMT_SETTING_SIZE },
5135 { set_ssp, false, MGMT_SETTING_SIZE },
5136 { set_hs, false, MGMT_SETTING_SIZE },
5137 { set_le, false, MGMT_SETTING_SIZE },
5138 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5139 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5140 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5141 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5142 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5143 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5144 { disconnect, false, MGMT_DISCONNECT_SIZE },
5145 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5146 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5147 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5148 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5149 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5150 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5151 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5152 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5153 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5154 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5155 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5156 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005157 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005158 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5159 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5160 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5161 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5162 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5163 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005164 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005165 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005166 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005167 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005168 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005169 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005170 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005171 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005172 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005173 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005174 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005175 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5176 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005177};
5178
Johan Hedberg03811012010-12-08 00:21:06 +02005179int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5180{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005181 void *buf;
5182 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005183 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005184 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005185 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005186 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005187 int err;
5188
5189 BT_DBG("got %zu bytes", msglen);
5190
5191 if (msglen < sizeof(*hdr))
5192 return -EINVAL;
5193
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005194 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005195 if (!buf)
5196 return -ENOMEM;
5197
5198 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5199 err = -EFAULT;
5200 goto done;
5201 }
5202
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005203 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005204 opcode = __le16_to_cpu(hdr->opcode);
5205 index = __le16_to_cpu(hdr->index);
5206 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005207
5208 if (len != msglen - sizeof(*hdr)) {
5209 err = -EINVAL;
5210 goto done;
5211 }
5212
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005213 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005214 hdev = hci_dev_get(index);
5215 if (!hdev) {
5216 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005217 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005218 goto done;
5219 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005220
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005221 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannfee746b2014-06-29 12:13:05 +02005222 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) ||
5223 test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005224 err = cmd_status(sk, index, opcode,
5225 MGMT_STATUS_INVALID_INDEX);
5226 goto done;
5227 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005228 }
5229
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005230 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005231 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005232 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005233 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005234 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005235 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005236 }
5237
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005238 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005239 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005240 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005241 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005242 goto done;
5243 }
5244
Johan Hedbergbe22b542012-03-01 22:24:41 +02005245 handler = &mgmt_handlers[opcode];
5246
5247 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005248 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005249 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005250 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005251 goto done;
5252 }
5253
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005254 if (hdev)
5255 mgmt_init_hdev(sk, hdev);
5256
5257 cp = buf + sizeof(*hdr);
5258
Johan Hedbergbe22b542012-03-01 22:24:41 +02005259 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005260 if (err < 0)
5261 goto done;
5262
Johan Hedberg03811012010-12-08 00:21:06 +02005263 err = msglen;
5264
5265done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005266 if (hdev)
5267 hci_dev_put(hdev);
5268
Johan Hedberg03811012010-12-08 00:21:06 +02005269 kfree(buf);
5270 return err;
5271}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005272
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005273void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005274{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005275 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005276 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005277
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005278 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005279}
5280
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005281void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005282{
Johan Hedberg5f159032012-03-02 03:13:19 +02005283 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005284
Marcel Holtmann1514b892013-10-06 08:25:01 -07005285 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005286 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005287
Johan Hedberg744cf192011-11-08 20:40:14 +02005288 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005289
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005290 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005291}
5292
Andre Guedes6046dc32014-02-26 20:21:51 -03005293/* This function requires the caller holds hdev->lock */
5294static void restart_le_auto_conns(struct hci_dev *hdev)
5295{
5296 struct hci_conn_params *p;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005297 bool added = false;
Andre Guedes6046dc32014-02-26 20:21:51 -03005298
5299 list_for_each_entry(p, &hdev->le_conn_params, list) {
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005300 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) {
Andre Guedes6046dc32014-02-26 20:21:51 -03005301 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005302 added = true;
5303 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005304 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005305
5306 /* Calling hci_pend_le_conn_add will actually already trigger
5307 * background scanning when needed. So no need to trigger it
5308 * just another time.
5309 *
5310 * This check is here to avoid an unneeded restart of the
5311 * passive scanning. Since this is during the controller
5312 * power up phase the duplicate filtering is not an issue.
5313 */
5314 if (added)
5315 return;
5316
5317 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005318}
5319
Johan Hedberg229ab392013-03-15 17:06:53 -05005320static void powered_complete(struct hci_dev *hdev, u8 status)
5321{
5322 struct cmd_lookup match = { NULL, hdev };
5323
5324 BT_DBG("status 0x%02x", status);
5325
5326 hci_dev_lock(hdev);
5327
Andre Guedes6046dc32014-02-26 20:21:51 -03005328 restart_le_auto_conns(hdev);
5329
Johan Hedberg229ab392013-03-15 17:06:53 -05005330 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5331
5332 new_settings(hdev, match.sk);
5333
5334 hci_dev_unlock(hdev);
5335
5336 if (match.sk)
5337 sock_put(match.sk);
5338}
5339
Johan Hedberg70da6242013-03-15 17:06:51 -05005340static int powered_update_hci(struct hci_dev *hdev)
5341{
Johan Hedberg890ea892013-03-15 17:06:52 -05005342 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005343 u8 link_sec;
5344
Johan Hedberg890ea892013-03-15 17:06:52 -05005345 hci_req_init(&req, hdev);
5346
Johan Hedberg70da6242013-03-15 17:06:51 -05005347 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5348 !lmp_host_ssp_capable(hdev)) {
5349 u8 ssp = 1;
5350
Johan Hedberg890ea892013-03-15 17:06:52 -05005351 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005352 }
5353
Johan Hedbergc73eee92013-04-19 18:35:21 +03005354 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5355 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005356 struct hci_cp_write_le_host_supported cp;
5357
5358 cp.le = 1;
5359 cp.simul = lmp_le_br_capable(hdev);
5360
5361 /* Check first if we already have the right
5362 * host state (host features set)
5363 */
5364 if (cp.le != lmp_host_le_capable(hdev) ||
5365 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005366 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5367 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005368 }
5369
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005370 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005371 /* Make sure the controller has a good default for
5372 * advertising data. This also applies to the case
5373 * where BR/EDR was toggled during the AUTO_OFF phase.
5374 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005375 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005376 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005377 update_scan_rsp_data(&req);
5378 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005379
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005380 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5381 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005382 }
5383
Johan Hedberg70da6242013-03-15 17:06:51 -05005384 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5385 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005386 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5387 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005388
5389 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005390 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5391 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005392 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005393 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005394 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005395 }
5396
Johan Hedberg229ab392013-03-15 17:06:53 -05005397 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005398}
5399
Johan Hedberg744cf192011-11-08 20:40:14 +02005400int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005401{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005402 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005403 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5404 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005405 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005406
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005407 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5408 return 0;
5409
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005410 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005411 if (powered_update_hci(hdev) == 0)
5412 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005413
Johan Hedberg229ab392013-03-15 17:06:53 -05005414 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5415 &match);
5416 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005417 }
5418
Johan Hedberg229ab392013-03-15 17:06:53 -05005419 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5420 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5421
5422 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5423 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5424 zero_cod, sizeof(zero_cod), NULL);
5425
5426new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005427 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005428
5429 if (match.sk)
5430 sock_put(match.sk);
5431
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005432 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005433}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005434
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005435void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005436{
5437 struct pending_cmd *cmd;
5438 u8 status;
5439
5440 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5441 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005442 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005443
5444 if (err == -ERFKILL)
5445 status = MGMT_STATUS_RFKILLED;
5446 else
5447 status = MGMT_STATUS_FAILED;
5448
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005449 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005450
5451 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005452}
5453
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005454void mgmt_discoverable_timeout(struct hci_dev *hdev)
5455{
5456 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005457
5458 hci_dev_lock(hdev);
5459
5460 /* When discoverable timeout triggers, then just make sure
5461 * the limited discoverable flag is cleared. Even in the case
5462 * of a timeout triggered from general discoverable, it is
5463 * safe to unconditionally clear the flag.
5464 */
5465 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005466 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005467
5468 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005469 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5470 u8 scan = SCAN_PAGE;
5471 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5472 sizeof(scan), &scan);
5473 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005474 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005475 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005476 hci_req_run(&req, NULL);
5477
5478 hdev->discov_timeout = 0;
5479
Johan Hedberg9a43e252013-10-20 19:00:07 +03005480 new_settings(hdev, NULL);
5481
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005482 hci_dev_unlock(hdev);
5483}
5484
Marcel Holtmann86a75642013-10-15 06:33:54 -07005485void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005486{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005487 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005488
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005489 /* Nothing needed here if there's a pending command since that
5490 * commands request completion callback takes care of everything
5491 * necessary.
5492 */
5493 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005494 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005495
Johan Hedbergbd107992014-02-24 14:52:19 +02005496 /* Powering off may clear the scan mode - don't let that interfere */
5497 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5498 return;
5499
Johan Hedberg9a43e252013-10-20 19:00:07 +03005500 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005501 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005502 } else {
5503 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005504 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005505 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005506
Johan Hedberg9a43e252013-10-20 19:00:07 +03005507 if (changed) {
5508 struct hci_request req;
5509
5510 /* In case this change in discoverable was triggered by
5511 * a disabling of connectable there could be a need to
5512 * update the advertising flags.
5513 */
5514 hci_req_init(&req, hdev);
5515 update_adv_data(&req);
5516 hci_req_run(&req, NULL);
5517
Marcel Holtmann86a75642013-10-15 06:33:54 -07005518 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005519 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005520}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005521
Marcel Holtmanna3309162013-10-15 06:33:55 -07005522void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005523{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005524 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005525
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005526 /* Nothing needed here if there's a pending command since that
5527 * commands request completion callback takes care of everything
5528 * necessary.
5529 */
5530 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005531 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005532
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005533 /* Powering off may clear the scan mode - don't let that interfere */
5534 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5535 return;
5536
Marcel Holtmanna3309162013-10-15 06:33:55 -07005537 if (connectable)
5538 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5539 else
5540 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005541
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005542 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005543 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005544}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005545
Johan Hedberg778b2352014-02-24 14:52:17 +02005546void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5547{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005548 /* Powering off may stop advertising - don't let that interfere */
5549 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5550 return;
5551
Johan Hedberg778b2352014-02-24 14:52:17 +02005552 if (advertising)
5553 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5554 else
5555 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5556}
5557
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005558void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005559{
Johan Hedbergca69b792011-11-11 18:10:00 +02005560 u8 mgmt_err = mgmt_status(status);
5561
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005562 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005563 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005564 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005565
5566 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005567 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005568 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005569}
5570
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005571void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5572 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005573{
Johan Hedberg86742e12011-11-07 23:13:38 +02005574 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005575
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005576 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005577
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005578 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005579 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005580 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005581 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005582 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005583 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005584
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005585 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005586}
Johan Hedbergf7520542011-01-20 12:34:39 +02005587
Johan Hedbergd7b25452014-05-23 13:19:53 +03005588static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5589{
5590 if (ltk->authenticated)
5591 return MGMT_LTK_AUTHENTICATED;
5592
5593 return MGMT_LTK_UNAUTHENTICATED;
5594}
5595
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005596void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005597{
5598 struct mgmt_ev_new_long_term_key ev;
5599
5600 memset(&ev, 0, sizeof(ev));
5601
Marcel Holtmann5192d302014-02-19 17:11:58 -08005602 /* Devices using resolvable or non-resolvable random addresses
5603 * without providing an indentity resolving key don't require
5604 * to store long term keys. Their addresses will change the
5605 * next time around.
5606 *
5607 * Only when a remote device provides an identity address
5608 * make sure the long term key is stored. If the remote
5609 * identity is known, the long term keys are internally
5610 * mapped to the identity address. So allow static random
5611 * and public addresses here.
5612 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005613 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5614 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5615 ev.store_hint = 0x00;
5616 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005617 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005618
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005619 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005620 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005621 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005622 ev.key.enc_size = key->enc_size;
5623 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005624 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005625
Johan Hedberg2ceba532014-06-16 19:25:16 +03005626 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005627 ev.key.master = 1;
5628
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005629 memcpy(ev.key.val, key->val, sizeof(key->val));
5630
Marcel Holtmann083368f2013-10-15 14:26:29 -07005631 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005632}
5633
Johan Hedberg95fbac82014-02-19 15:18:31 +02005634void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5635{
5636 struct mgmt_ev_new_irk ev;
5637
5638 memset(&ev, 0, sizeof(ev));
5639
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005640 /* For identity resolving keys from devices that are already
5641 * using a public address or static random address, do not
5642 * ask for storing this key. The identity resolving key really
5643 * is only mandatory for devices using resovlable random
5644 * addresses.
5645 *
5646 * Storing all identity resolving keys has the downside that
5647 * they will be also loaded on next boot of they system. More
5648 * identity resolving keys, means more time during scanning is
5649 * needed to actually resolve these addresses.
5650 */
5651 if (bacmp(&irk->rpa, BDADDR_ANY))
5652 ev.store_hint = 0x01;
5653 else
5654 ev.store_hint = 0x00;
5655
Johan Hedberg95fbac82014-02-19 15:18:31 +02005656 bacpy(&ev.rpa, &irk->rpa);
5657 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5658 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5659 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5660
5661 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5662}
5663
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005664void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5665 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005666{
5667 struct mgmt_ev_new_csrk ev;
5668
5669 memset(&ev, 0, sizeof(ev));
5670
5671 /* Devices using resolvable or non-resolvable random addresses
5672 * without providing an indentity resolving key don't require
5673 * to store signature resolving keys. Their addresses will change
5674 * the next time around.
5675 *
5676 * Only when a remote device provides an identity address
5677 * make sure the signature resolving key is stored. So allow
5678 * static random and public addresses here.
5679 */
5680 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5681 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5682 ev.store_hint = 0x00;
5683 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005684 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005685
5686 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5687 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5688 ev.key.master = csrk->master;
5689 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5690
5691 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5692}
5693
Andre Guedesffb5a8272014-07-01 18:10:11 -03005694void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
5695 u8 bdaddr_type, u16 min_interval, u16 max_interval,
5696 u16 latency, u16 timeout)
5697{
5698 struct mgmt_ev_new_conn_param ev;
5699
5700 memset(&ev, 0, sizeof(ev));
5701 bacpy(&ev.addr.bdaddr, bdaddr);
5702 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
5703 ev.store_hint = 0x00;
5704 ev.min_interval = cpu_to_le16(min_interval);
5705 ev.max_interval = cpu_to_le16(max_interval);
5706 ev.latency = cpu_to_le16(latency);
5707 ev.timeout = cpu_to_le16(timeout);
5708
5709 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5710}
5711
Marcel Holtmann94933992013-10-15 10:26:39 -07005712static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5713 u8 data_len)
5714{
5715 eir[eir_len++] = sizeof(type) + data_len;
5716 eir[eir_len++] = type;
5717 memcpy(&eir[eir_len], data, data_len);
5718 eir_len += data_len;
5719
5720 return eir_len;
5721}
5722
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005723void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5724 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5725 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005726{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005727 char buf[512];
5728 struct mgmt_ev_device_connected *ev = (void *) buf;
5729 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005730
Johan Hedbergb644ba32012-01-17 21:48:47 +02005731 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005732 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005733
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005734 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005735
Johan Hedbergb644ba32012-01-17 21:48:47 +02005736 if (name_len > 0)
5737 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005738 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005739
5740 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005741 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005742 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005743
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005744 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005745
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005746 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5747 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005748}
5749
Johan Hedberg8962ee72011-01-20 12:40:27 +02005750static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5751{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005752 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005753 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005754 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005755
Johan Hedberg88c3df12012-02-09 14:27:38 +02005756 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5757 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005758
Johan Hedbergaee9b212012-02-18 15:07:59 +02005759 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005760 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005761
5762 *sk = cmd->sk;
5763 sock_hold(*sk);
5764
Johan Hedberga664b5b2011-02-19 12:06:02 -03005765 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005766}
5767
Johan Hedberg124f6e32012-02-09 13:50:12 +02005768static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005769{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005770 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005771 struct mgmt_cp_unpair_device *cp = cmd->param;
5772 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005773
5774 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005775 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5776 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005777
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005778 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5779
Johan Hedbergaee9b212012-02-18 15:07:59 +02005780 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005781
5782 mgmt_pending_remove(cmd);
5783}
5784
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005785void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005786 u8 link_type, u8 addr_type, u8 reason,
5787 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005788{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005789 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005790 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005791 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005792
Johan Hedberg8b064a32014-02-24 14:52:22 +02005793 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5794 if (power_off) {
5795 struct mgmt_mode *cp = power_off->param;
5796
5797 /* The connection is still in hci_conn_hash so test for 1
5798 * instead of 0 to know if this is the last one.
5799 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005800 if (!cp->val && hci_conn_count(hdev) == 1) {
5801 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005802 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005803 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005804 }
5805
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005806 if (!mgmt_connected)
5807 return;
5808
Andre Guedes57eb7762013-10-30 19:01:41 -03005809 if (link_type != ACL_LINK && link_type != LE_LINK)
5810 return;
5811
Johan Hedberg744cf192011-11-08 20:40:14 +02005812 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005813
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005814 bacpy(&ev.addr.bdaddr, bdaddr);
5815 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5816 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005817
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005818 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005819
5820 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005821 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005822
Johan Hedberg124f6e32012-02-09 13:50:12 +02005823 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005824 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005825}
5826
Marcel Holtmann78929242013-10-06 23:55:47 -07005827void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5828 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005829{
Andre Guedes3655bba2013-10-30 19:01:40 -03005830 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5831 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005832 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005833 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005834
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005835 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5836 hdev);
5837
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005838 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005839 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005840 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005841
Andre Guedes3655bba2013-10-30 19:01:40 -03005842 cp = cmd->param;
5843
5844 if (bacmp(bdaddr, &cp->addr.bdaddr))
5845 return;
5846
5847 if (cp->addr.type != bdaddr_type)
5848 return;
5849
Johan Hedberg88c3df12012-02-09 14:27:38 +02005850 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005851 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005852
Marcel Holtmann78929242013-10-06 23:55:47 -07005853 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5854 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005855
Johan Hedberga664b5b2011-02-19 12:06:02 -03005856 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005857}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005858
Marcel Holtmann445608d2013-10-06 23:55:48 -07005859void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5860 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005861{
5862 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005863 struct pending_cmd *power_off;
5864
5865 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5866 if (power_off) {
5867 struct mgmt_mode *cp = power_off->param;
5868
5869 /* The connection is still in hci_conn_hash so test for 1
5870 * instead of 0 to know if this is the last one.
5871 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005872 if (!cp->val && hci_conn_count(hdev) == 1) {
5873 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005874 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005875 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005876 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005877
Johan Hedberg4c659c32011-11-07 23:13:39 +02005878 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005879 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005880 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005881
Marcel Holtmann445608d2013-10-06 23:55:48 -07005882 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005883}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005884
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005885void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005886{
5887 struct mgmt_ev_pin_code_request ev;
5888
Johan Hedbergd8457692012-02-17 14:24:57 +02005889 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005890 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005891 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005892
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005893 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005894}
5895
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005896void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5897 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005898{
5899 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005900 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005901
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005902 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005903 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005904 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005905
Johan Hedbergd8457692012-02-17 14:24:57 +02005906 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005907 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005908
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005909 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5910 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005911
Johan Hedberga664b5b2011-02-19 12:06:02 -03005912 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005913}
5914
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005915void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5916 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005917{
5918 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005919 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005920
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005921 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005922 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005923 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005924
Johan Hedbergd8457692012-02-17 14:24:57 +02005925 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005926 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005927
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005928 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5929 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005930
Johan Hedberga664b5b2011-02-19 12:06:02 -03005931 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005932}
Johan Hedberga5c29682011-02-19 12:05:57 -03005933
Johan Hedberg744cf192011-11-08 20:40:14 +02005934int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005935 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005936 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005937{
5938 struct mgmt_ev_user_confirm_request ev;
5939
Johan Hedberg744cf192011-11-08 20:40:14 +02005940 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005941
Johan Hedberg272d90d2012-02-09 15:26:12 +02005942 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005943 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005944 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005945 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005946
Johan Hedberg744cf192011-11-08 20:40:14 +02005947 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005948 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005949}
5950
Johan Hedberg272d90d2012-02-09 15:26:12 +02005951int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005952 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005953{
5954 struct mgmt_ev_user_passkey_request ev;
5955
5956 BT_DBG("%s", hdev->name);
5957
Johan Hedberg272d90d2012-02-09 15:26:12 +02005958 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005959 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005960
5961 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005962 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005963}
5964
Brian Gix0df4c182011-11-16 13:53:13 -08005965static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005966 u8 link_type, u8 addr_type, u8 status,
5967 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005968{
5969 struct pending_cmd *cmd;
5970 struct mgmt_rp_user_confirm_reply rp;
5971 int err;
5972
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005973 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005974 if (!cmd)
5975 return -ENOENT;
5976
Johan Hedberg272d90d2012-02-09 15:26:12 +02005977 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005978 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005979 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005980 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005981
Johan Hedberga664b5b2011-02-19 12:06:02 -03005982 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005983
5984 return err;
5985}
5986
Johan Hedberg744cf192011-11-08 20:40:14 +02005987int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005988 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005989{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005990 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005991 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005992}
5993
Johan Hedberg272d90d2012-02-09 15:26:12 +02005994int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005995 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005996{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005997 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005998 status,
5999 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006000}
Johan Hedberg2a611692011-02-19 12:06:00 -03006001
Brian Gix604086b2011-11-23 08:28:33 -08006002int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006003 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006004{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006005 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006006 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006007}
6008
Johan Hedberg272d90d2012-02-09 15:26:12 +02006009int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006010 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006011{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006012 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006013 status,
6014 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006015}
6016
Johan Hedberg92a25252012-09-06 18:39:26 +03006017int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6018 u8 link_type, u8 addr_type, u32 passkey,
6019 u8 entered)
6020{
6021 struct mgmt_ev_passkey_notify ev;
6022
6023 BT_DBG("%s", hdev->name);
6024
6025 bacpy(&ev.addr.bdaddr, bdaddr);
6026 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6027 ev.passkey = __cpu_to_le32(passkey);
6028 ev.entered = entered;
6029
6030 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6031}
6032
Marcel Holtmanne5460992013-10-15 14:26:23 -07006033void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6034 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006035{
6036 struct mgmt_ev_auth_failed ev;
6037
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006038 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006039 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006040 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006041
Marcel Holtmanne5460992013-10-15 14:26:23 -07006042 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006043}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006044
Marcel Holtmann464996a2013-10-15 14:26:24 -07006045void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006046{
6047 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006048 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006049
6050 if (status) {
6051 u8 mgmt_err = mgmt_status(status);
6052 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006053 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006054 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006055 }
6056
Marcel Holtmann464996a2013-10-15 14:26:24 -07006057 if (test_bit(HCI_AUTH, &hdev->flags))
6058 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6059 &hdev->dev_flags);
6060 else
6061 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6062 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006063
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006064 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006065 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006066
Johan Hedberg47990ea2012-02-22 11:58:37 +02006067 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006068 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006069
6070 if (match.sk)
6071 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006072}
6073
Johan Hedberg890ea892013-03-15 17:06:52 -05006074static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006075{
Johan Hedberg890ea892013-03-15 17:06:52 -05006076 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006077 struct hci_cp_write_eir cp;
6078
Johan Hedberg976eb202012-10-24 21:12:01 +03006079 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006080 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006081
Johan Hedbergc80da272012-02-22 15:38:48 +02006082 memset(hdev->eir, 0, sizeof(hdev->eir));
6083
Johan Hedbergcacaf522012-02-21 00:52:42 +02006084 memset(&cp, 0, sizeof(cp));
6085
Johan Hedberg890ea892013-03-15 17:06:52 -05006086 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006087}
6088
Marcel Holtmann3e248562013-10-15 14:26:25 -07006089void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006090{
6091 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006092 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006093 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006094
6095 if (status) {
6096 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006097
6098 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006099 &hdev->dev_flags)) {
6100 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006101 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006102 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006103
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006104 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6105 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006106 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006107 }
6108
6109 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006110 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006111 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006112 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6113 if (!changed)
6114 changed = test_and_clear_bit(HCI_HS_ENABLED,
6115 &hdev->dev_flags);
6116 else
6117 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006118 }
6119
6120 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6121
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006122 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006123 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006124
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006125 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006126 sock_put(match.sk);
6127
Johan Hedberg890ea892013-03-15 17:06:52 -05006128 hci_req_init(&req, hdev);
6129
Johan Hedberg37699722014-06-24 14:00:27 +03006130 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6131 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6132 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6133 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006134 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006135 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006136 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006137 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006138
6139 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006140}
6141
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006142void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6143{
6144 struct cmd_lookup match = { NULL, hdev };
6145 bool changed = false;
6146
6147 if (status) {
6148 u8 mgmt_err = mgmt_status(status);
6149
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006150 if (enable) {
6151 if (test_and_clear_bit(HCI_SC_ENABLED,
6152 &hdev->dev_flags))
6153 new_settings(hdev, NULL);
6154 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6155 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006156
6157 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6158 cmd_status_rsp, &mgmt_err);
6159 return;
6160 }
6161
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006162 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006163 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006164 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006165 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006166 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6167 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006168
6169 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6170 settings_rsp, &match);
6171
6172 if (changed)
6173 new_settings(hdev, match.sk);
6174
6175 if (match.sk)
6176 sock_put(match.sk);
6177}
6178
Johan Hedberg92da6092013-03-15 17:06:55 -05006179static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006180{
6181 struct cmd_lookup *match = data;
6182
Johan Hedberg90e70452012-02-23 23:09:40 +02006183 if (match->sk == NULL) {
6184 match->sk = cmd->sk;
6185 sock_hold(match->sk);
6186 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006187}
6188
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006189void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6190 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006191{
Johan Hedberg90e70452012-02-23 23:09:40 +02006192 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006193
Johan Hedberg92da6092013-03-15 17:06:55 -05006194 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6195 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6196 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006197
6198 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006199 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6200 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006201
6202 if (match.sk)
6203 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006204}
6205
Marcel Holtmann7667da32013-10-15 14:26:27 -07006206void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006207{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006208 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006209 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006210
Johan Hedberg13928972013-03-15 17:07:00 -05006211 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006212 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006213
6214 memset(&ev, 0, sizeof(ev));
6215 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006216 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006217
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006218 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006219 if (!cmd) {
6220 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006221
Johan Hedberg13928972013-03-15 17:07:00 -05006222 /* If this is a HCI command related to powering on the
6223 * HCI dev don't send any mgmt signals.
6224 */
6225 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006226 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006227 }
6228
Marcel Holtmann7667da32013-10-15 14:26:27 -07006229 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6230 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006231}
Szymon Jancc35938b2011-03-22 13:12:21 +01006232
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006233void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6234 u8 *randomizer192, u8 *hash256,
6235 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006236{
6237 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006238
Johan Hedberg744cf192011-11-08 20:40:14 +02006239 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006240
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006241 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006242 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006243 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006244
6245 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006246 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6247 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006248 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006249 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6250 hash256 && randomizer256) {
6251 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006252
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006253 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6254 memcpy(rp.randomizer192, randomizer192,
6255 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006256
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006257 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6258 memcpy(rp.randomizer256, randomizer256,
6259 sizeof(rp.randomizer256));
6260
6261 cmd_complete(cmd->sk, hdev->id,
6262 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6263 &rp, sizeof(rp));
6264 } else {
6265 struct mgmt_rp_read_local_oob_data rp;
6266
6267 memcpy(rp.hash, hash192, sizeof(rp.hash));
6268 memcpy(rp.randomizer, randomizer192,
6269 sizeof(rp.randomizer));
6270
6271 cmd_complete(cmd->sk, hdev->id,
6272 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6273 &rp, sizeof(rp));
6274 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006275 }
6276
6277 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006278}
Johan Hedberge17acd42011-03-30 23:57:16 +03006279
Marcel Holtmann901801b2013-10-06 23:55:51 -07006280void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006281 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6282 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006283{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006284 char buf[512];
6285 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006286 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006287 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006288
Andre Guedes12602d02013-04-30 15:29:40 -03006289 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006290 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006291
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006292 /* Make sure that the buffer is big enough. The 5 extra bytes
6293 * are for the potential CoD field.
6294 */
6295 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006296 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006297
Johan Hedberg1dc06092012-01-15 21:01:23 +02006298 memset(buf, 0, sizeof(buf));
6299
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006300 irk = hci_get_irk(hdev, bdaddr, addr_type);
6301 if (irk) {
6302 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6303 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6304 } else {
6305 bacpy(&ev->addr.bdaddr, bdaddr);
6306 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6307 }
6308
Johan Hedberge319d2e2012-01-15 19:51:59 +02006309 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006310 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006311
Johan Hedberg1dc06092012-01-15 21:01:23 +02006312 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006313 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006314
Johan Hedberg1dc06092012-01-15 21:01:23 +02006315 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6316 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006317 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006318
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006319 if (scan_rsp_len > 0)
6320 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6321
6322 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6323 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006324
Marcel Holtmann901801b2013-10-06 23:55:51 -07006325 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006326}
Johan Hedberga88a9652011-03-30 13:18:12 +03006327
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006328void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6329 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006330{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006331 struct mgmt_ev_device_found *ev;
6332 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6333 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006334
Johan Hedbergb644ba32012-01-17 21:48:47 +02006335 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006336
Johan Hedbergb644ba32012-01-17 21:48:47 +02006337 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006338
Johan Hedbergb644ba32012-01-17 21:48:47 +02006339 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006340 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006341 ev->rssi = rssi;
6342
6343 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006344 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006345
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006346 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006347
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006348 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006349}
Johan Hedberg314b2382011-04-27 10:29:57 -04006350
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006351void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006352{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006353 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006354 struct pending_cmd *cmd;
6355
Andre Guedes343fb142011-11-22 17:14:19 -03006356 BT_DBG("%s discovering %u", hdev->name, discovering);
6357
Johan Hedberg164a6e72011-11-01 17:06:44 +02006358 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006359 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006360 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006361 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006362
6363 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006364 u8 type = hdev->discovery.type;
6365
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006366 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6367 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006368 mgmt_pending_remove(cmd);
6369 }
6370
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006371 memset(&ev, 0, sizeof(ev));
6372 ev.type = hdev->discovery.type;
6373 ev.discovering = discovering;
6374
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006375 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006376}
Antti Julku5e762442011-08-25 16:48:02 +03006377
Marcel Holtmann5976e602013-10-06 04:08:14 -07006378static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6379{
6380 BT_DBG("%s status %u", hdev->name, status);
6381
6382 /* Clear the advertising mgmt setting if we failed to re-enable it */
6383 if (status) {
6384 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006385 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006386 }
6387}
6388
6389void mgmt_reenable_advertising(struct hci_dev *hdev)
6390{
6391 struct hci_request req;
6392
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006393 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006394 return;
6395
6396 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6397 return;
6398
6399 hci_req_init(&req, hdev);
6400 enable_advertising(&req);
6401
6402 /* If this fails we have no option but to let user space know
6403 * that we've disabled advertising.
6404 */
6405 if (hci_req_run(&req, adv_enable_complete) < 0) {
6406 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006407 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006408 }
6409}