blob: f3e4a16fb1570e665a5c4177ffa69de10df4dbbe [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,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200132struct pending_cmd {
133 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200134 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100136 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300138 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139};
140
Johan Hedbergca69b792011-11-11 18:10:00 +0200141/* HCI to MGMT error code conversion table */
142static u8 mgmt_status_table[] = {
143 MGMT_STATUS_SUCCESS,
144 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
145 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
146 MGMT_STATUS_FAILED, /* Hardware Failure */
147 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
148 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200149 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200150 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
151 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
152 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
153 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
154 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
155 MGMT_STATUS_BUSY, /* Command Disallowed */
156 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
157 MGMT_STATUS_REJECTED, /* Rejected Security */
158 MGMT_STATUS_REJECTED, /* Rejected Personal */
159 MGMT_STATUS_TIMEOUT, /* Host Timeout */
160 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
161 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
162 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
163 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
164 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
165 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
166 MGMT_STATUS_BUSY, /* Repeated Attempts */
167 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
168 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
169 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
170 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
171 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
172 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
173 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
174 MGMT_STATUS_FAILED, /* Unspecified Error */
175 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
176 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
177 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
178 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
179 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
180 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
181 MGMT_STATUS_FAILED, /* Unit Link Key Used */
182 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
183 MGMT_STATUS_TIMEOUT, /* Instant Passed */
184 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
185 MGMT_STATUS_FAILED, /* Transaction Collision */
186 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
187 MGMT_STATUS_REJECTED, /* QoS Rejected */
188 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
189 MGMT_STATUS_REJECTED, /* Insufficient Security */
190 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
191 MGMT_STATUS_BUSY, /* Role Switch Pending */
192 MGMT_STATUS_FAILED, /* Slot Violation */
193 MGMT_STATUS_FAILED, /* Role Switch Failed */
194 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
195 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
196 MGMT_STATUS_BUSY, /* Host Busy Pairing */
197 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
198 MGMT_STATUS_BUSY, /* Controller Busy */
199 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
200 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
201 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
202 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
203 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
204};
205
206static u8 mgmt_status(u8 hci_status)
207{
208 if (hci_status < ARRAY_SIZE(mgmt_status_table))
209 return mgmt_status_table[hci_status];
210
211 return MGMT_STATUS_FAILED;
212}
213
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200214static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
215 struct sock *skip_sk)
216{
217 struct sk_buff *skb;
218 struct mgmt_hdr *hdr;
219
220 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
221 if (!skb)
222 return -ENOMEM;
223
224 hdr = (void *) skb_put(skb, sizeof(*hdr));
225 hdr->opcode = cpu_to_le16(event);
226 if (hdev)
227 hdr->index = cpu_to_le16(hdev->id);
228 else
229 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
230 hdr->len = cpu_to_le16(data_len);
231
232 if (data)
233 memcpy(skb_put(skb, data_len), data, data_len);
234
235 /* Time stamp */
236 __net_timestamp(skb);
237
238 hci_send_to_control(skb, skip_sk);
239 kfree_skb(skb);
240
241 return 0;
242}
243
Szymon Janc4e51eae2011-02-25 19:05:48 +0100244static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200245{
246 struct sk_buff *skb;
247 struct mgmt_hdr *hdr;
248 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300249 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200250
Szymon Janc34eb5252011-02-28 14:10:08 +0100251 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200252
Andre Guedes790eff42012-06-07 19:05:46 -0300253 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200254 if (!skb)
255 return -ENOMEM;
256
257 hdr = (void *) skb_put(skb, sizeof(*hdr));
258
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700259 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100260 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200261 hdr->len = cpu_to_le16(sizeof(*ev));
262
263 ev = (void *) skb_put(skb, sizeof(*ev));
264 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200265 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200266
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300267 err = sock_queue_rcv_skb(sk, skb);
268 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269 kfree_skb(skb);
270
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300271 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272}
273
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200274static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300275 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200276{
277 struct sk_buff *skb;
278 struct mgmt_hdr *hdr;
279 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300280 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200281
282 BT_DBG("sock %p", sk);
283
Andre Guedes790eff42012-06-07 19:05:46 -0300284 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200285 if (!skb)
286 return -ENOMEM;
287
288 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200289
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700290 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100291 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200292 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200293
Johan Hedberga38528f2011-01-22 06:46:43 +0200294 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200295 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200296 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100297
298 if (rp)
299 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200300
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300301 err = sock_queue_rcv_skb(sk, skb);
302 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200303 kfree_skb(skb);
304
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100305 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200306}
307
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300308static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
309 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200310{
311 struct mgmt_rp_read_version rp;
312
313 BT_DBG("sock %p", sk);
314
315 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700316 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200317
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200318 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300319 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200320}
321
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
323 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200324{
325 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200326 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
327 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200328 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200329 size_t rp_size;
330 int i, err;
331
332 BT_DBG("sock %p", sk);
333
334 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
335
336 rp = kmalloc(rp_size, GFP_KERNEL);
337 if (!rp)
338 return -ENOMEM;
339
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700340 rp->num_commands = cpu_to_le16(num_commands);
341 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200342
343 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
344 put_unaligned_le16(mgmt_commands[i], opcode);
345
346 for (i = 0; i < num_events; i++, opcode++)
347 put_unaligned_le16(mgmt_events[i], opcode);
348
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200349 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300350 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200351 kfree(rp);
352
353 return err;
354}
355
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300356static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
357 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200358{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200359 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200360 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200361 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300363 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200364
365 BT_DBG("sock %p", sk);
366
367 read_lock(&hci_dev_list_lock);
368
369 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300370 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200371 if (d->dev_type == HCI_BREDR &&
372 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700373 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374 }
375
Johan Hedberga38528f2011-01-22 06:46:43 +0200376 rp_len = sizeof(*rp) + (2 * count);
377 rp = kmalloc(rp_len, GFP_ATOMIC);
378 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100379 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200380 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100381 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382
Johan Hedberg476e44c2012-10-19 20:10:46 +0300383 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200384 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200385 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200386 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200387 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200388 continue;
389
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 /* Devices marked as raw-only are neither configured
391 * nor unconfigured controllers.
392 */
393 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700394 continue;
395
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200396 if (d->dev_type == HCI_BREDR &&
397 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700398 rp->index[count++] = cpu_to_le16(d->id);
399 BT_DBG("Added hci%u", d->id);
400 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200401 }
402
Johan Hedberg476e44c2012-10-19 20:10:46 +0300403 rp->num_controllers = cpu_to_le16(count);
404 rp_len = sizeof(*rp) + (2 * count);
405
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200406 read_unlock(&hci_dev_list_lock);
407
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200408 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300409 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200410
Johan Hedberga38528f2011-01-22 06:46:43 +0200411 kfree(rp);
412
413 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200414}
415
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200416static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
417 void *data, u16 data_len)
418{
419 struct mgmt_rp_read_unconf_index_list *rp;
420 struct hci_dev *d;
421 size_t rp_len;
422 u16 count;
423 int err;
424
425 BT_DBG("sock %p", sk);
426
427 read_lock(&hci_dev_list_lock);
428
429 count = 0;
430 list_for_each_entry(d, &hci_dev_list, list) {
431 if (d->dev_type == HCI_BREDR &&
432 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
433 count++;
434 }
435
436 rp_len = sizeof(*rp) + (2 * count);
437 rp = kmalloc(rp_len, GFP_ATOMIC);
438 if (!rp) {
439 read_unlock(&hci_dev_list_lock);
440 return -ENOMEM;
441 }
442
443 count = 0;
444 list_for_each_entry(d, &hci_dev_list, list) {
445 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200446 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200447 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
448 continue;
449
450 /* Devices marked as raw-only are neither configured
451 * nor unconfigured controllers.
452 */
453 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
454 continue;
455
456 if (d->dev_type == HCI_BREDR &&
457 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
458 rp->index[count++] = cpu_to_le16(d->id);
459 BT_DBG("Added hci%u", d->id);
460 }
461 }
462
463 rp->num_controllers = cpu_to_le16(count);
464 rp_len = sizeof(*rp) + (2 * count);
465
466 read_unlock(&hci_dev_list_lock);
467
468 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
469 0, rp, rp_len);
470
471 kfree(rp);
472
473 return err;
474}
475
Marcel Holtmanndbece372014-07-04 18:11:55 +0200476static bool is_configured(struct hci_dev *hdev)
477{
478 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
479 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
480 return false;
481
482 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
483 !bacmp(&hdev->public_addr, BDADDR_ANY))
484 return false;
485
486 return true;
487}
488
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200489static __le32 get_missing_options(struct hci_dev *hdev)
490{
491 u32 options = 0;
492
Marcel Holtmanndbece372014-07-04 18:11:55 +0200493 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
494 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200495 options |= MGMT_OPTION_EXTERNAL_CONFIG;
496
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200497 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
498 !bacmp(&hdev->public_addr, BDADDR_ANY))
499 options |= MGMT_OPTION_PUBLIC_ADDRESS;
500
501 return cpu_to_le32(options);
502}
503
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200504static int new_options(struct hci_dev *hdev, struct sock *skip)
505{
506 __le32 options = get_missing_options(hdev);
507
508 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
509 sizeof(options), skip);
510}
511
Marcel Holtmanndbece372014-07-04 18:11:55 +0200512static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
513{
514 __le32 options = get_missing_options(hdev);
515
516 return cmd_complete(sk, hdev->id, opcode, 0, &options,
517 sizeof(options));
518}
519
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200520static int read_config_info(struct sock *sk, struct hci_dev *hdev,
521 void *data, u16 data_len)
522{
523 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200524 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200525
526 BT_DBG("sock %p %s", sk, hdev->name);
527
528 hci_dev_lock(hdev);
529
530 memset(&rp, 0, sizeof(rp));
531 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200532
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200533 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
534 options |= MGMT_OPTION_EXTERNAL_CONFIG;
535
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200536 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200537 options |= MGMT_OPTION_PUBLIC_ADDRESS;
538
539 rp.supported_options = cpu_to_le32(options);
540 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200541
542 hci_dev_unlock(hdev);
543
544 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
545 sizeof(rp));
546}
547
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200548static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200549{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200550 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200551
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200552 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300553 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800554 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300555 settings |= MGMT_SETTING_CONNECTABLE;
556 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200557
Andre Guedesed3fa312012-07-24 15:03:46 -0300558 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500559 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
560 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200561 settings |= MGMT_SETTING_BREDR;
562 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700563
564 if (lmp_ssp_capable(hdev)) {
565 settings |= MGMT_SETTING_SSP;
566 settings |= MGMT_SETTING_HS;
567 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800568
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800569 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200570 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700572 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100573
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300574 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200575 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300576 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200577 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300578 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200579
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200580 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
581 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200582 settings |= MGMT_SETTING_CONFIGURATION;
583
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200584 return settings;
585}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587static u32 get_current_settings(struct hci_dev *hdev)
588{
589 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200590
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200591 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100592 settings |= MGMT_SETTING_POWERED;
593
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200594 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200595 settings |= MGMT_SETTING_CONNECTABLE;
596
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500597 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
598 settings |= MGMT_SETTING_FAST_CONNECTABLE;
599
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200600 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200601 settings |= MGMT_SETTING_DISCOVERABLE;
602
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300603 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300604 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605
Johan Hedberg56f87902013-10-02 13:43:13 +0300606 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_BREDR;
608
Johan Hedberg06199cf2012-02-22 16:37:11 +0200609 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200611
Johan Hedberg47990ea2012-02-22 11:58:37 +0200612 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200614
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200615 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200617
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200618 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
619 settings |= MGMT_SETTING_HS;
620
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200621 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300622 settings |= MGMT_SETTING_ADVERTISING;
623
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800624 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
625 settings |= MGMT_SETTING_SECURE_CONN;
626
Johan Hedberg0663b292014-06-24 13:15:50 +0300627 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800628 settings |= MGMT_SETTING_DEBUG_KEYS;
629
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200630 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
631 settings |= MGMT_SETTING_PRIVACY;
632
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200633 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200634}
635
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300636#define PNP_INFO_SVCLASS_ID 0x1200
637
Johan Hedberg213202e2013-01-27 00:31:33 +0200638static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
639{
640 u8 *ptr = data, *uuids_start = NULL;
641 struct bt_uuid *uuid;
642
643 if (len < 4)
644 return ptr;
645
646 list_for_each_entry(uuid, &hdev->uuids, list) {
647 u16 uuid16;
648
649 if (uuid->size != 16)
650 continue;
651
652 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
653 if (uuid16 < 0x1100)
654 continue;
655
656 if (uuid16 == PNP_INFO_SVCLASS_ID)
657 continue;
658
659 if (!uuids_start) {
660 uuids_start = ptr;
661 uuids_start[0] = 1;
662 uuids_start[1] = EIR_UUID16_ALL;
663 ptr += 2;
664 }
665
666 /* Stop if not enough space to put next UUID */
667 if ((ptr - data) + sizeof(u16) > len) {
668 uuids_start[1] = EIR_UUID16_SOME;
669 break;
670 }
671
672 *ptr++ = (uuid16 & 0x00ff);
673 *ptr++ = (uuid16 & 0xff00) >> 8;
674 uuids_start[0] += sizeof(uuid16);
675 }
676
677 return ptr;
678}
679
Johan Hedbergcdf19632013-01-27 00:31:34 +0200680static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
681{
682 u8 *ptr = data, *uuids_start = NULL;
683 struct bt_uuid *uuid;
684
685 if (len < 6)
686 return ptr;
687
688 list_for_each_entry(uuid, &hdev->uuids, list) {
689 if (uuid->size != 32)
690 continue;
691
692 if (!uuids_start) {
693 uuids_start = ptr;
694 uuids_start[0] = 1;
695 uuids_start[1] = EIR_UUID32_ALL;
696 ptr += 2;
697 }
698
699 /* Stop if not enough space to put next UUID */
700 if ((ptr - data) + sizeof(u32) > len) {
701 uuids_start[1] = EIR_UUID32_SOME;
702 break;
703 }
704
705 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
706 ptr += sizeof(u32);
707 uuids_start[0] += sizeof(u32);
708 }
709
710 return ptr;
711}
712
Johan Hedbergc00d5752013-01-27 00:31:35 +0200713static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
714{
715 u8 *ptr = data, *uuids_start = NULL;
716 struct bt_uuid *uuid;
717
718 if (len < 18)
719 return ptr;
720
721 list_for_each_entry(uuid, &hdev->uuids, list) {
722 if (uuid->size != 128)
723 continue;
724
725 if (!uuids_start) {
726 uuids_start = ptr;
727 uuids_start[0] = 1;
728 uuids_start[1] = EIR_UUID128_ALL;
729 ptr += 2;
730 }
731
732 /* Stop if not enough space to put next UUID */
733 if ((ptr - data) + 16 > len) {
734 uuids_start[1] = EIR_UUID128_SOME;
735 break;
736 }
737
738 memcpy(ptr, uuid->uuid, 16);
739 ptr += 16;
740 uuids_start[0] += 16;
741 }
742
743 return ptr;
744}
745
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300746static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
747{
748 struct pending_cmd *cmd;
749
750 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
751 if (cmd->opcode == opcode)
752 return cmd;
753 }
754
755 return NULL;
756}
757
Johan Hedberg95868422014-06-28 17:54:07 +0300758static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
759 struct hci_dev *hdev,
760 const void *data)
761{
762 struct pending_cmd *cmd;
763
764 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
765 if (cmd->user_data != data)
766 continue;
767 if (cmd->opcode == opcode)
768 return cmd;
769 }
770
771 return NULL;
772}
773
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700774static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
775{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700776 u8 ad_len = 0;
777 size_t name_len;
778
779 name_len = strlen(hdev->dev_name);
780 if (name_len > 0) {
781 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
782
783 if (name_len > max_len) {
784 name_len = max_len;
785 ptr[1] = EIR_NAME_SHORT;
786 } else
787 ptr[1] = EIR_NAME_COMPLETE;
788
789 ptr[0] = name_len + 1;
790
791 memcpy(ptr + 2, hdev->dev_name, name_len);
792
793 ad_len += (name_len + 2);
794 ptr += (name_len + 2);
795 }
796
797 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700798}
799
800static void update_scan_rsp_data(struct hci_request *req)
801{
802 struct hci_dev *hdev = req->hdev;
803 struct hci_cp_le_set_scan_rsp_data cp;
804 u8 len;
805
Johan Hedberg7751ef12013-10-19 23:38:15 +0300806 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700807 return;
808
809 memset(&cp, 0, sizeof(cp));
810
811 len = create_scan_rsp_data(hdev, cp.data);
812
Johan Hedbergeb438b52013-10-16 15:31:07 +0300813 if (hdev->scan_rsp_data_len == len &&
814 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700815 return;
816
Johan Hedbergeb438b52013-10-16 15:31:07 +0300817 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
818 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700819
820 cp.length = len;
821
822 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
823}
824
Johan Hedberg9a43e252013-10-20 19:00:07 +0300825static u8 get_adv_discov_flags(struct hci_dev *hdev)
826{
827 struct pending_cmd *cmd;
828
829 /* If there's a pending mgmt command the flags will not yet have
830 * their final values, so check for this first.
831 */
832 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
833 if (cmd) {
834 struct mgmt_mode *cp = cmd->param;
835 if (cp->val == 0x01)
836 return LE_AD_GENERAL;
837 else if (cp->val == 0x02)
838 return LE_AD_LIMITED;
839 } else {
840 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
841 return LE_AD_LIMITED;
842 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
843 return LE_AD_GENERAL;
844 }
845
846 return 0;
847}
848
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700849static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700850{
851 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700852
Johan Hedberg9a43e252013-10-20 19:00:07 +0300853 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854
Johan Hedberge8340042014-01-30 11:16:50 -0800855 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
858 if (flags) {
859 BT_DBG("adv flags 0x%02x", flags);
860
861 ptr[0] = 2;
862 ptr[1] = EIR_FLAGS;
863 ptr[2] = flags;
864
865 ad_len += 3;
866 ptr += 3;
867 }
868
869 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
870 ptr[0] = 2;
871 ptr[1] = EIR_TX_POWER;
872 ptr[2] = (u8) hdev->adv_tx_power;
873
874 ad_len += 3;
875 ptr += 3;
876 }
877
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700878 return ad_len;
879}
880
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700881static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882{
883 struct hci_dev *hdev = req->hdev;
884 struct hci_cp_le_set_adv_data cp;
885 u8 len;
886
Johan Hedberg10994ce2013-10-19 23:38:16 +0300887 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700888 return;
889
890 memset(&cp, 0, sizeof(cp));
891
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700892 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700893
894 if (hdev->adv_data_len == len &&
895 memcmp(cp.data, hdev->adv_data, len) == 0)
896 return;
897
898 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
899 hdev->adv_data_len = len;
900
901 cp.length = len;
902
903 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
904}
905
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300906int mgmt_update_adv_data(struct hci_dev *hdev)
907{
908 struct hci_request req;
909
910 hci_req_init(&req, hdev);
911 update_adv_data(&req);
912
913 return hci_req_run(&req, NULL);
914}
915
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300916static void create_eir(struct hci_dev *hdev, u8 *data)
917{
918 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300919 size_t name_len;
920
921 name_len = strlen(hdev->dev_name);
922
923 if (name_len > 0) {
924 /* EIR Data type */
925 if (name_len > 48) {
926 name_len = 48;
927 ptr[1] = EIR_NAME_SHORT;
928 } else
929 ptr[1] = EIR_NAME_COMPLETE;
930
931 /* EIR Data length */
932 ptr[0] = name_len + 1;
933
934 memcpy(ptr + 2, hdev->dev_name, name_len);
935
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300936 ptr += (name_len + 2);
937 }
938
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100939 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700940 ptr[0] = 2;
941 ptr[1] = EIR_TX_POWER;
942 ptr[2] = (u8) hdev->inq_tx_power;
943
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700944 ptr += 3;
945 }
946
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700947 if (hdev->devid_source > 0) {
948 ptr[0] = 9;
949 ptr[1] = EIR_DEVICE_ID;
950
951 put_unaligned_le16(hdev->devid_source, ptr + 2);
952 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
953 put_unaligned_le16(hdev->devid_product, ptr + 6);
954 put_unaligned_le16(hdev->devid_version, ptr + 8);
955
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700956 ptr += 10;
957 }
958
Johan Hedberg213202e2013-01-27 00:31:33 +0200959 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200960 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200961 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300962}
963
Johan Hedberg890ea892013-03-15 17:06:52 -0500964static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300965{
Johan Hedberg890ea892013-03-15 17:06:52 -0500966 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967 struct hci_cp_write_eir cp;
968
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200969 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500970 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200971
Johan Hedberg976eb202012-10-24 21:12:01 +0300972 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500973 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300974
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200975 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500976 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300977
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200978 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
981 memset(&cp, 0, sizeof(cp));
982
983 create_eir(hdev, cp.data);
984
985 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500986 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300987
988 memcpy(hdev->eir, cp.data, sizeof(cp.data));
989
Johan Hedberg890ea892013-03-15 17:06:52 -0500990 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300991}
992
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200993static u8 get_service_classes(struct hci_dev *hdev)
994{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300995 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200996 u8 val = 0;
997
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300998 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200999 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000
1001 return val;
1002}
1003
Johan Hedberg890ea892013-03-15 17:06:52 -05001004static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001005{
Johan Hedberg890ea892013-03-15 17:06:52 -05001006 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001007 u8 cod[3];
1008
1009 BT_DBG("%s", hdev->name);
1010
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001011 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001012 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001013
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001014 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1015 return;
1016
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001017 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001018 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001019
1020 cod[0] = hdev->minor_class;
1021 cod[1] = hdev->major_class;
1022 cod[2] = get_service_classes(hdev);
1023
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001024 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1025 cod[1] |= 0x20;
1026
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001027 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001028 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001029
Johan Hedberg890ea892013-03-15 17:06:52 -05001030 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001031}
1032
Johan Hedberga4858cb2014-02-25 19:56:31 +02001033static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001034{
1035 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001036
1037 /* If there's a pending mgmt command the flag will not yet have
1038 * it's final value, so check for this first.
1039 */
1040 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1041 if (cmd) {
1042 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001043 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001044 }
1045
Johan Hedberga4858cb2014-02-25 19:56:31 +02001046 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001047}
1048
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001049static void disable_advertising(struct hci_request *req)
1050{
1051 u8 enable = 0x00;
1052
1053 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1054}
1055
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001056static void enable_advertising(struct hci_request *req)
1057{
1058 struct hci_dev *hdev = req->hdev;
1059 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001060 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001061 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001062
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001063 if (hci_conn_num(hdev, LE_LINK) > 0)
1064 return;
1065
1066 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1067 disable_advertising(req);
1068
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001069 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001070 * hci_update_random_address knows that it's safe to go ahead
1071 * and write a new random address. The flag will be set back on
1072 * as soon as the SET_ADV_ENABLE HCI command completes.
1073 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001074 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001075
Johan Hedberga4858cb2014-02-25 19:56:31 +02001076 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001077
Johan Hedberga4858cb2014-02-25 19:56:31 +02001078 /* Set require_privacy to true only when non-connectable
1079 * advertising is used. In that case it is fine to use a
1080 * non-resolvable private address.
1081 */
1082 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001083 return;
1084
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001085 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001086 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1087 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001088 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001089 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001090 cp.channel_map = hdev->le_adv_channel_map;
1091
1092 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1093
1094 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1095}
1096
Johan Hedberg7d785252011-12-15 00:47:39 +02001097static void service_cache_off(struct work_struct *work)
1098{
1099 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001100 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001101 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001102
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001103 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001104 return;
1105
Johan Hedberg890ea892013-03-15 17:06:52 -05001106 hci_req_init(&req, hdev);
1107
Johan Hedberg7d785252011-12-15 00:47:39 +02001108 hci_dev_lock(hdev);
1109
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 update_eir(&req);
1111 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001112
1113 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001114
1115 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001116}
1117
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001118static void rpa_expired(struct work_struct *work)
1119{
1120 struct hci_dev *hdev = container_of(work, struct hci_dev,
1121 rpa_expired.work);
1122 struct hci_request req;
1123
1124 BT_DBG("");
1125
1126 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1127
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001128 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001129 return;
1130
1131 /* The generation of a new RPA and programming it into the
1132 * controller happens in the enable_advertising() function.
1133 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001134 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001135 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001136 hci_req_run(&req, NULL);
1137}
1138
Johan Hedberg6a919082012-02-28 06:17:26 +02001139static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001140{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001141 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001142 return;
1143
Johan Hedberg4f87da82012-03-02 19:55:56 +02001144 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001145 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001146
Johan Hedberg4f87da82012-03-02 19:55:56 +02001147 /* Non-mgmt controlled devices get this bit set
1148 * implicitly so that pairing works for them, however
1149 * for mgmt we require user-space to explicitly enable
1150 * it
1151 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001152 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001153}
1154
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001155static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001156 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001157{
1158 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001160 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001161
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001162 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Johan Hedberg03811012010-12-08 00:21:06 +02001164 memset(&rp, 0, sizeof(rp));
1165
Johan Hedberg03811012010-12-08 00:21:06 +02001166 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001167
1168 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001169 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001170
1171 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1172 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1173
1174 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001175
1176 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001177 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001178
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001179 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001181 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001182 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001183}
1184
1185static void mgmt_pending_free(struct pending_cmd *cmd)
1186{
1187 sock_put(cmd->sk);
1188 kfree(cmd->param);
1189 kfree(cmd);
1190}
1191
1192static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001193 struct hci_dev *hdev, void *data,
1194 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001195{
1196 struct pending_cmd *cmd;
1197
Johan Hedbergfca20012014-06-28 17:54:05 +03001198 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001199 if (!cmd)
1200 return NULL;
1201
1202 cmd->opcode = opcode;
1203 cmd->index = hdev->id;
1204
Andre Guedes12b94562012-06-07 19:05:45 -03001205 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001206 if (!cmd->param) {
1207 kfree(cmd);
1208 return NULL;
1209 }
1210
1211 if (data)
1212 memcpy(cmd->param, data, len);
1213
1214 cmd->sk = sk;
1215 sock_hold(sk);
1216
1217 list_add(&cmd->list, &hdev->mgmt_pending);
1218
1219 return cmd;
1220}
1221
1222static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001223 void (*cb)(struct pending_cmd *cmd,
1224 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001225 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001226{
Andre Guedesa3d09352013-02-01 11:21:30 -03001227 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001228
Andre Guedesa3d09352013-02-01 11:21:30 -03001229 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001230 if (opcode > 0 && cmd->opcode != opcode)
1231 continue;
1232
1233 cb(cmd, data);
1234 }
1235}
1236
Johan Hedberg03811012010-12-08 00:21:06 +02001237static void mgmt_pending_remove(struct pending_cmd *cmd)
1238{
1239 list_del(&cmd->list);
1240 mgmt_pending_free(cmd);
1241}
1242
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001243static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001244{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001245 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001246
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001247 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001248 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001249}
1250
Johan Hedberg8b064a32014-02-24 14:52:22 +02001251static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1252{
1253 BT_DBG("%s status 0x%02x", hdev->name, status);
1254
Johan Hedberga3172b72014-02-28 09:33:44 +02001255 if (hci_conn_count(hdev) == 0) {
1256 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001257 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001259}
1260
Johan Hedberg23a48092014-07-08 16:05:06 +03001261static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001262{
1263 struct hci_dev *hdev = req->hdev;
1264 struct hci_cp_remote_name_req_cancel cp;
1265 struct inquiry_entry *e;
1266
1267 switch (hdev->discovery.state) {
1268 case DISCOVERY_FINDING:
1269 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1270 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1271 } else {
1272 cancel_delayed_work(&hdev->le_scan_disable);
1273 hci_req_add_le_scan_disable(req);
1274 }
1275
Johan Hedberg23a48092014-07-08 16:05:06 +03001276 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001277
1278 case DISCOVERY_RESOLVING:
1279 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1280 NAME_PENDING);
1281 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001282 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001283
1284 bacpy(&cp.bdaddr, &e->data.bdaddr);
1285 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1286 &cp);
1287
Johan Hedberg23a48092014-07-08 16:05:06 +03001288 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001289
1290 default:
1291 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001292 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001293 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001294 return true;
1295 }
1296
Johan Hedberg21a60d32014-06-10 14:05:58 +03001297 break;
1298 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001299
1300 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001301}
1302
Johan Hedberg8b064a32014-02-24 14:52:22 +02001303static int clean_up_hci_state(struct hci_dev *hdev)
1304{
1305 struct hci_request req;
1306 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001307 bool discov_stopped;
1308 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001309
1310 hci_req_init(&req, hdev);
1311
1312 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1313 test_bit(HCI_PSCAN, &hdev->flags)) {
1314 u8 scan = 0x00;
1315 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1316 }
1317
Johan Hedberg73e082f2014-07-08 15:07:51 +03001318 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001319 disable_advertising(&req);
1320
Johan Hedberg23a48092014-07-08 16:05:06 +03001321 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322
1323 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1324 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001325 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001326
Johan Hedbergc9910d02014-02-27 14:35:12 +02001327 switch (conn->state) {
1328 case BT_CONNECTED:
1329 case BT_CONFIG:
1330 dc.handle = cpu_to_le16(conn->handle);
1331 dc.reason = 0x15; /* Terminated due to Power Off */
1332 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1333 break;
1334 case BT_CONNECT:
1335 if (conn->type == LE_LINK)
1336 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1337 0, NULL);
1338 else if (conn->type == ACL_LINK)
1339 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1340 6, &conn->dst);
1341 break;
1342 case BT_CONNECT2:
1343 bacpy(&rej.bdaddr, &conn->dst);
1344 rej.reason = 0x15; /* Terminated due to Power Off */
1345 if (conn->type == ACL_LINK)
1346 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1347 sizeof(rej), &rej);
1348 else if (conn->type == SCO_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1350 sizeof(rej), &rej);
1351 break;
1352 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001353 }
1354
Johan Hedberg23a48092014-07-08 16:05:06 +03001355 err = hci_req_run(&req, clean_up_hci_complete);
1356 if (!err && discov_stopped)
1357 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1358
1359 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001360}
1361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001362static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001363 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001364{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001365 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001366 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001367 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001368
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001369 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001370
Johan Hedberga7e80f22013-01-09 16:05:19 +02001371 if (cp->val != 0x00 && cp->val != 0x01)
1372 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1373 MGMT_STATUS_INVALID_PARAMS);
1374
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001375 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001376
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001377 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1378 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1379 MGMT_STATUS_BUSY);
1380 goto failed;
1381 }
1382
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001383 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1384 cancel_delayed_work(&hdev->power_off);
1385
1386 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001387 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1388 data, len);
1389 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001390 goto failed;
1391 }
1392 }
1393
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001394 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001395 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001396 goto failed;
1397 }
1398
Johan Hedberg03811012010-12-08 00:21:06 +02001399 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1400 if (!cmd) {
1401 err = -ENOMEM;
1402 goto failed;
1403 }
1404
Johan Hedberg8b064a32014-02-24 14:52:22 +02001405 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001406 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001407 err = 0;
1408 } else {
1409 /* Disconnect connections, stop scans, etc */
1410 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001411 if (!err)
1412 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1413 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001414
Johan Hedberg8b064a32014-02-24 14:52:22 +02001415 /* ENODATA means there were no HCI commands queued */
1416 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001417 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1419 err = 0;
1420 }
1421 }
Johan Hedberg03811012010-12-08 00:21:06 +02001422
1423failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001424 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001425 return err;
1426}
1427
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001428static int new_settings(struct hci_dev *hdev, struct sock *skip)
1429{
1430 __le32 ev;
1431
1432 ev = cpu_to_le32(get_current_settings(hdev));
1433
1434 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1435}
1436
Johan Hedberg91a668b2014-07-09 13:28:26 +03001437int mgmt_new_settings(struct hci_dev *hdev)
1438{
1439 return new_settings(hdev, NULL);
1440}
1441
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001442struct cmd_lookup {
1443 struct sock *sk;
1444 struct hci_dev *hdev;
1445 u8 mgmt_status;
1446};
1447
1448static void settings_rsp(struct pending_cmd *cmd, void *data)
1449{
1450 struct cmd_lookup *match = data;
1451
1452 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1453
1454 list_del(&cmd->list);
1455
1456 if (match->sk == NULL) {
1457 match->sk = cmd->sk;
1458 sock_hold(match->sk);
1459 }
1460
1461 mgmt_pending_free(cmd);
1462}
1463
1464static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1465{
1466 u8 *status = data;
1467
1468 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1469 mgmt_pending_remove(cmd);
1470}
1471
Johan Hedberge6fe7982013-10-02 15:45:22 +03001472static u8 mgmt_bredr_support(struct hci_dev *hdev)
1473{
1474 if (!lmp_bredr_capable(hdev))
1475 return MGMT_STATUS_NOT_SUPPORTED;
1476 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1477 return MGMT_STATUS_REJECTED;
1478 else
1479 return MGMT_STATUS_SUCCESS;
1480}
1481
1482static u8 mgmt_le_support(struct hci_dev *hdev)
1483{
1484 if (!lmp_le_capable(hdev))
1485 return MGMT_STATUS_NOT_SUPPORTED;
1486 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1487 return MGMT_STATUS_REJECTED;
1488 else
1489 return MGMT_STATUS_SUCCESS;
1490}
1491
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001492static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1493{
1494 struct pending_cmd *cmd;
1495 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001496 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001497 bool changed;
1498
1499 BT_DBG("status 0x%02x", status);
1500
1501 hci_dev_lock(hdev);
1502
1503 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1504 if (!cmd)
1505 goto unlock;
1506
1507 if (status) {
1508 u8 mgmt_err = mgmt_status(status);
1509 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001510 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001511 goto remove_cmd;
1512 }
1513
1514 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001515 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001516 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1517 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001518
1519 if (hdev->discov_timeout > 0) {
1520 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1521 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1522 to);
1523 }
1524 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001525 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1526 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001527 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001528
1529 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1530
1531 if (changed)
1532 new_settings(hdev, cmd->sk);
1533
Marcel Holtmann970ba522013-10-15 06:33:57 -07001534 /* When the discoverable mode gets changed, make sure
1535 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001536 * bit correctly set. Also update page scan based on whitelist
1537 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001538 */
1539 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001540 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001541 update_class(&req);
1542 hci_req_run(&req, NULL);
1543
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001544remove_cmd:
1545 mgmt_pending_remove(cmd);
1546
1547unlock:
1548 hci_dev_unlock(hdev);
1549}
1550
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001551static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001552 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001553{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001554 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001555 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001556 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001557 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001558 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001559 int err;
1560
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001561 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001562
Johan Hedberg9a43e252013-10-20 19:00:07 +03001563 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1564 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001565 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001566 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001567
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001568 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001569 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1570 MGMT_STATUS_INVALID_PARAMS);
1571
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001572 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001573
1574 /* Disabling discoverable requires that no timeout is set,
1575 * and enabling limited discoverable requires a timeout.
1576 */
1577 if ((cp->val == 0x00 && timeout > 0) ||
1578 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001579 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001580 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001581
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001582 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001583
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001584 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001585 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001586 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001587 goto failed;
1588 }
1589
1590 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001591 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001592 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001593 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001594 goto failed;
1595 }
1596
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001597 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001598 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001599 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001600 goto failed;
1601 }
1602
1603 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001604 bool changed = false;
1605
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001606 /* Setting limited discoverable when powered off is
1607 * not a valid operation since it requires a timeout
1608 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1609 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001610 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1611 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1612 changed = true;
1613 }
1614
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001615 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001616 if (err < 0)
1617 goto failed;
1618
1619 if (changed)
1620 err = new_settings(hdev, sk);
1621
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001622 goto failed;
1623 }
1624
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001625 /* If the current mode is the same, then just update the timeout
1626 * value with the new value. And if only the timeout gets updated,
1627 * then no need for any HCI transactions.
1628 */
1629 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1630 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1631 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001632 cancel_delayed_work(&hdev->discov_off);
1633 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001634
Marcel Holtmann36261542013-10-15 08:28:51 -07001635 if (cp->val && hdev->discov_timeout > 0) {
1636 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001637 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001638 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001639 }
1640
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001641 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001642 goto failed;
1643 }
1644
1645 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1646 if (!cmd) {
1647 err = -ENOMEM;
1648 goto failed;
1649 }
1650
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001651 /* Cancel any potential discoverable timeout that might be
1652 * still active and store new timeout value. The arming of
1653 * the timeout happens in the complete handler.
1654 */
1655 cancel_delayed_work(&hdev->discov_off);
1656 hdev->discov_timeout = timeout;
1657
Johan Hedbergb456f872013-10-19 23:38:22 +03001658 /* Limited discoverable mode */
1659 if (cp->val == 0x02)
1660 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1661 else
1662 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1663
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001664 hci_req_init(&req, hdev);
1665
Johan Hedberg9a43e252013-10-20 19:00:07 +03001666 /* The procedure for LE-only controllers is much simpler - just
1667 * update the advertising data.
1668 */
1669 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1670 goto update_ad;
1671
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001672 scan = SCAN_PAGE;
1673
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001674 if (cp->val) {
1675 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001676
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001677 if (cp->val == 0x02) {
1678 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001679 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001680 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1681 hci_cp.iac_lap[1] = 0x8b;
1682 hci_cp.iac_lap[2] = 0x9e;
1683 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1684 hci_cp.iac_lap[4] = 0x8b;
1685 hci_cp.iac_lap[5] = 0x9e;
1686 } else {
1687 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001688 hci_cp.num_iac = 1;
1689 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1690 hci_cp.iac_lap[1] = 0x8b;
1691 hci_cp.iac_lap[2] = 0x9e;
1692 }
1693
1694 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1695 (hci_cp.num_iac * 3) + 1, &hci_cp);
1696
1697 scan |= SCAN_INQUIRY;
1698 } else {
1699 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1700 }
1701
1702 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001703
Johan Hedberg9a43e252013-10-20 19:00:07 +03001704update_ad:
1705 update_adv_data(&req);
1706
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001707 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001708 if (err < 0)
1709 mgmt_pending_remove(cmd);
1710
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001711failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001712 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001713 return err;
1714}
1715
Johan Hedberg406d7802013-03-15 17:07:09 -05001716static void write_fast_connectable(struct hci_request *req, bool enable)
1717{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001718 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001719 struct hci_cp_write_page_scan_activity acp;
1720 u8 type;
1721
Johan Hedberg547003b2013-10-21 16:51:53 +03001722 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1723 return;
1724
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001725 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1726 return;
1727
Johan Hedberg406d7802013-03-15 17:07:09 -05001728 if (enable) {
1729 type = PAGE_SCAN_TYPE_INTERLACED;
1730
1731 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001732 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001733 } else {
1734 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1735
1736 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001737 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001738 }
1739
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001740 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001741
Johan Hedbergbd98b992013-03-15 17:07:13 -05001742 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1743 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1744 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1745 sizeof(acp), &acp);
1746
1747 if (hdev->page_scan_type != type)
1748 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001749}
1750
Johan Hedberg2b76f452013-03-15 17:07:04 -05001751static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1752{
1753 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001754 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001755 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001756
1757 BT_DBG("status 0x%02x", status);
1758
1759 hci_dev_lock(hdev);
1760
1761 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1762 if (!cmd)
1763 goto unlock;
1764
Johan Hedberg37438c12013-10-14 16:20:05 +03001765 if (status) {
1766 u8 mgmt_err = mgmt_status(status);
1767 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1768 goto remove_cmd;
1769 }
1770
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001771 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001772 if (cp->val) {
1773 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1774 &hdev->dev_flags);
1775 discov_changed = false;
1776 } else {
1777 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1778 &hdev->dev_flags);
1779 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1780 &hdev->dev_flags);
1781 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001782
Johan Hedberg2b76f452013-03-15 17:07:04 -05001783 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1784
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001785 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001786 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001787 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001788 if (discov_changed)
1789 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001790 hci_update_background_scan(hdev);
1791 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001792
Johan Hedberg37438c12013-10-14 16:20:05 +03001793remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001794 mgmt_pending_remove(cmd);
1795
1796unlock:
1797 hci_dev_unlock(hdev);
1798}
1799
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001800static int set_connectable_update_settings(struct hci_dev *hdev,
1801 struct sock *sk, u8 val)
1802{
1803 bool changed = false;
1804 int err;
1805
1806 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1807 changed = true;
1808
1809 if (val) {
1810 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1811 } else {
1812 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1813 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1814 }
1815
1816 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1817 if (err < 0)
1818 return err;
1819
Johan Hedberg562064e2014-07-08 16:35:34 +03001820 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001821 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001822 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001823 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001824 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001825
1826 return 0;
1827}
1828
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001829static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001830 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001831{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001832 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001833 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001834 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001835 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001836 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001837
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001838 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001839
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001840 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1841 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001842 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001843 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001844
Johan Hedberga7e80f22013-01-09 16:05:19 +02001845 if (cp->val != 0x00 && cp->val != 0x01)
1846 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1847 MGMT_STATUS_INVALID_PARAMS);
1848
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001849 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001850
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001851 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001852 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001853 goto failed;
1854 }
1855
1856 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001857 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001859 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001860 goto failed;
1861 }
1862
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001863 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1864 if (!cmd) {
1865 err = -ENOMEM;
1866 goto failed;
1867 }
1868
Johan Hedberg2b76f452013-03-15 17:07:04 -05001869 hci_req_init(&req, hdev);
1870
Johan Hedberg9a43e252013-10-20 19:00:07 +03001871 /* If BR/EDR is not enabled and we disable advertising as a
1872 * by-product of disabling connectable, we need to update the
1873 * advertising flags.
1874 */
1875 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1876 if (!cp->val) {
1877 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1878 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1879 }
1880 update_adv_data(&req);
1881 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001882 if (cp->val) {
1883 scan = SCAN_PAGE;
1884 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001885 /* If we don't have any whitelist entries just
1886 * disable all scanning. If there are entries
1887 * and we had both page and inquiry scanning
1888 * enabled then fall back to only page scanning.
1889 * Otherwise no changes are needed.
1890 */
1891 if (list_empty(&hdev->whitelist))
1892 scan = SCAN_DISABLED;
1893 else if (test_bit(HCI_ISCAN, &hdev->flags))
1894 scan = SCAN_PAGE;
1895 else
1896 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001897
1898 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001899 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001900 cancel_delayed_work(&hdev->discov_off);
1901 }
1902
1903 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1904 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001905
Johan Hedberg3bd27242014-07-28 20:53:58 +03001906no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001907 /* If we're going from non-connectable to connectable or
1908 * vice-versa when fast connectable is enabled ensure that fast
1909 * connectable gets disabled. write_fast_connectable won't do
1910 * anything if the page scan parameters are already what they
1911 * should be.
1912 */
1913 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001914 write_fast_connectable(&req, false);
1915
Johan Hedberge8b12022014-07-10 10:51:27 +03001916 /* Update the advertising parameters if necessary */
1917 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001918 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001919
Johan Hedberg2b76f452013-03-15 17:07:04 -05001920 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001921 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001922 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001923 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001924 err = set_connectable_update_settings(hdev, sk,
1925 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001926 goto failed;
1927 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001928
1929failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001930 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001931 return err;
1932}
1933
Johan Hedbergb2939472014-07-30 09:22:23 +03001934static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001935 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001936{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001937 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001938 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001939 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001940
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001941 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001942
Johan Hedberga7e80f22013-01-09 16:05:19 +02001943 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001944 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001945 MGMT_STATUS_INVALID_PARAMS);
1946
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001947 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001948
1949 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001950 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001952 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001953
Johan Hedbergb2939472014-07-30 09:22:23 +03001954 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001955 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001956 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
Marcel Holtmann55594352013-10-06 16:11:57 -07001958 if (changed)
1959 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001960
Marcel Holtmann55594352013-10-06 16:11:57 -07001961unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001962 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001963 return err;
1964}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001965
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001966static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1967 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001968{
1969 struct mgmt_mode *cp = data;
1970 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001971 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001972 int err;
1973
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001974 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001975
Johan Hedberge6fe7982013-10-02 15:45:22 +03001976 status = mgmt_bredr_support(hdev);
1977 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001978 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001979 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001980
Johan Hedberga7e80f22013-01-09 16:05:19 +02001981 if (cp->val != 0x00 && cp->val != 0x01)
1982 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1983 MGMT_STATUS_INVALID_PARAMS);
1984
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001985 hci_dev_lock(hdev);
1986
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001987 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001988 bool changed = false;
1989
1990 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001991 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001992 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1993 changed = true;
1994 }
1995
1996 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1997 if (err < 0)
1998 goto failed;
1999
2000 if (changed)
2001 err = new_settings(hdev, sk);
2002
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002003 goto failed;
2004 }
2005
2006 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002007 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002008 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002009 goto failed;
2010 }
2011
2012 val = !!cp->val;
2013
2014 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2015 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2016 goto failed;
2017 }
2018
2019 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2020 if (!cmd) {
2021 err = -ENOMEM;
2022 goto failed;
2023 }
2024
2025 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2026 if (err < 0) {
2027 mgmt_pending_remove(cmd);
2028 goto failed;
2029 }
2030
2031failed:
2032 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002033 return err;
2034}
2035
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002037{
2038 struct mgmt_mode *cp = data;
2039 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002040 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002041 int err;
2042
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002043 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002044
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002045 status = mgmt_bredr_support(hdev);
2046 if (status)
2047 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2048
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002049 if (!lmp_ssp_capable(hdev))
2050 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2051 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002052
Johan Hedberga7e80f22013-01-09 16:05:19 +02002053 if (cp->val != 0x00 && cp->val != 0x01)
2054 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2055 MGMT_STATUS_INVALID_PARAMS);
2056
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002057 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002058
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002059 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002060 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002061
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002062 if (cp->val) {
2063 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2064 &hdev->dev_flags);
2065 } else {
2066 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2067 &hdev->dev_flags);
2068 if (!changed)
2069 changed = test_and_clear_bit(HCI_HS_ENABLED,
2070 &hdev->dev_flags);
2071 else
2072 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002073 }
2074
2075 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2076 if (err < 0)
2077 goto failed;
2078
2079 if (changed)
2080 err = new_settings(hdev, sk);
2081
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002082 goto failed;
2083 }
2084
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002085 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2086 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002087 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2088 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002089 goto failed;
2090 }
2091
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002092 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002093 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2094 goto failed;
2095 }
2096
2097 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2098 if (!cmd) {
2099 err = -ENOMEM;
2100 goto failed;
2101 }
2102
Johan Hedberg37699722014-06-24 14:00:27 +03002103 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2104 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2105 sizeof(cp->val), &cp->val);
2106
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002107 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002108 if (err < 0) {
2109 mgmt_pending_remove(cmd);
2110 goto failed;
2111 }
2112
2113failed:
2114 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002115 return err;
2116}
2117
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002118static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002119{
2120 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002121 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002122 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002123 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002124
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002125 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002126
Johan Hedberge6fe7982013-10-02 15:45:22 +03002127 status = mgmt_bredr_support(hdev);
2128 if (status)
2129 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002130
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002131 if (!lmp_ssp_capable(hdev))
2132 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2133 MGMT_STATUS_NOT_SUPPORTED);
2134
2135 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2136 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2137 MGMT_STATUS_REJECTED);
2138
Johan Hedberga7e80f22013-01-09 16:05:19 +02002139 if (cp->val != 0x00 && cp->val != 0x01)
2140 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2141 MGMT_STATUS_INVALID_PARAMS);
2142
Marcel Holtmannee392692013-10-01 22:59:23 -07002143 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002144
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002145 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002146 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002147 } else {
2148 if (hdev_is_powered(hdev)) {
2149 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2150 MGMT_STATUS_REJECTED);
2151 goto unlock;
2152 }
2153
Marcel Holtmannee392692013-10-01 22:59:23 -07002154 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002155 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002156
2157 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2158 if (err < 0)
2159 goto unlock;
2160
2161 if (changed)
2162 err = new_settings(hdev, sk);
2163
2164unlock:
2165 hci_dev_unlock(hdev);
2166 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002167}
2168
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002169static void le_enable_complete(struct hci_dev *hdev, u8 status)
2170{
2171 struct cmd_lookup match = { NULL, hdev };
2172
2173 if (status) {
2174 u8 mgmt_err = mgmt_status(status);
2175
2176 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2177 &mgmt_err);
2178 return;
2179 }
2180
2181 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2182
2183 new_settings(hdev, match.sk);
2184
2185 if (match.sk)
2186 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002187
2188 /* Make sure the controller has a good default for
2189 * advertising data. Restrict the update to when LE
2190 * has actually been enabled. During power on, the
2191 * update in powered_update_hci will take care of it.
2192 */
2193 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2194 struct hci_request req;
2195
2196 hci_dev_lock(hdev);
2197
2198 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002199 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002200 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002201 hci_req_run(&req, NULL);
2202
Johan Hedberga70f4b52014-07-07 15:19:50 +03002203 hci_update_background_scan(hdev);
2204
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002205 hci_dev_unlock(hdev);
2206 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002207}
2208
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002209static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002210{
2211 struct mgmt_mode *cp = data;
2212 struct hci_cp_write_le_host_supported hci_cp;
2213 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002214 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002215 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002216 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002217
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002218 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002219
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002220 if (!lmp_le_capable(hdev))
2221 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2222 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002223
Johan Hedberga7e80f22013-01-09 16:05:19 +02002224 if (cp->val != 0x00 && cp->val != 0x01)
2225 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2226 MGMT_STATUS_INVALID_PARAMS);
2227
Johan Hedbergc73eee92013-04-19 18:35:21 +03002228 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002229 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002230 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2231 MGMT_STATUS_REJECTED);
2232
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002233 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002234
2235 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002236 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002237
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002238 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239 bool changed = false;
2240
2241 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2242 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2243 changed = true;
2244 }
2245
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002246 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2247 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002248 changed = true;
2249 }
2250
Johan Hedberg06199cf2012-02-22 16:37:11 +02002251 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2252 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002253 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002254
2255 if (changed)
2256 err = new_settings(hdev, sk);
2257
Johan Hedberg1de028c2012-02-29 19:55:35 -08002258 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002259 }
2260
Johan Hedberg4375f102013-09-25 13:26:10 +03002261 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2262 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002263 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002264 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002265 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002266 }
2267
2268 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2269 if (!cmd) {
2270 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002271 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002272 }
2273
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002274 hci_req_init(&req, hdev);
2275
Johan Hedberg06199cf2012-02-22 16:37:11 +02002276 memset(&hci_cp, 0, sizeof(hci_cp));
2277
2278 if (val) {
2279 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002280 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002281 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002282 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002283 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002284 }
2285
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002286 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2287 &hci_cp);
2288
2289 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302290 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002291 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002292
Johan Hedberg1de028c2012-02-29 19:55:35 -08002293unlock:
2294 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295 return err;
2296}
2297
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002298/* This is a helper function to test for pending mgmt commands that can
2299 * cause CoD or EIR HCI commands. We can only allow one such pending
2300 * mgmt command at a time since otherwise we cannot easily track what
2301 * the current values are, will be, and based on that calculate if a new
2302 * HCI command needs to be sent and if yes with what value.
2303 */
2304static bool pending_eir_or_class(struct hci_dev *hdev)
2305{
2306 struct pending_cmd *cmd;
2307
2308 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2309 switch (cmd->opcode) {
2310 case MGMT_OP_ADD_UUID:
2311 case MGMT_OP_REMOVE_UUID:
2312 case MGMT_OP_SET_DEV_CLASS:
2313 case MGMT_OP_SET_POWERED:
2314 return true;
2315 }
2316 }
2317
2318 return false;
2319}
2320
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002321static const u8 bluetooth_base_uuid[] = {
2322 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2323 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2324};
2325
2326static u8 get_uuid_size(const u8 *uuid)
2327{
2328 u32 val;
2329
2330 if (memcmp(uuid, bluetooth_base_uuid, 12))
2331 return 128;
2332
2333 val = get_unaligned_le32(&uuid[12]);
2334 if (val > 0xffff)
2335 return 32;
2336
2337 return 16;
2338}
2339
Johan Hedberg92da6092013-03-15 17:06:55 -05002340static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2341{
2342 struct pending_cmd *cmd;
2343
2344 hci_dev_lock(hdev);
2345
2346 cmd = mgmt_pending_find(mgmt_op, hdev);
2347 if (!cmd)
2348 goto unlock;
2349
2350 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2351 hdev->dev_class, 3);
2352
2353 mgmt_pending_remove(cmd);
2354
2355unlock:
2356 hci_dev_unlock(hdev);
2357}
2358
2359static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2360{
2361 BT_DBG("status 0x%02x", status);
2362
2363 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2364}
2365
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002366static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002368 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002369 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002370 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002371 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002372 int err;
2373
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002374 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002375
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002376 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002377
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002378 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002379 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002380 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002381 goto failed;
2382 }
2383
Andre Guedes92c4c202012-06-07 19:05:44 -03002384 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002385 if (!uuid) {
2386 err = -ENOMEM;
2387 goto failed;
2388 }
2389
2390 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002391 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002392 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002393
Johan Hedbergde66aa62013-01-27 00:31:27 +02002394 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002395
Johan Hedberg890ea892013-03-15 17:06:52 -05002396 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002397
Johan Hedberg890ea892013-03-15 17:06:52 -05002398 update_class(&req);
2399 update_eir(&req);
2400
Johan Hedberg92da6092013-03-15 17:06:55 -05002401 err = hci_req_run(&req, add_uuid_complete);
2402 if (err < 0) {
2403 if (err != -ENODATA)
2404 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002405
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002406 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002407 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002408 goto failed;
2409 }
2410
2411 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002412 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002413 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002414 goto failed;
2415 }
2416
2417 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002418
2419failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002420 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002421 return err;
2422}
2423
Johan Hedberg24b78d02012-02-23 23:24:30 +02002424static bool enable_service_cache(struct hci_dev *hdev)
2425{
2426 if (!hdev_is_powered(hdev))
2427 return false;
2428
2429 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002430 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2431 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002432 return true;
2433 }
2434
2435 return false;
2436}
2437
Johan Hedberg92da6092013-03-15 17:06:55 -05002438static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2439{
2440 BT_DBG("status 0x%02x", status);
2441
2442 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2443}
2444
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002445static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002446 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002448 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002449 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002450 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002451 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 -05002452 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002453 int err, found;
2454
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002455 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002456
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002457 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002458
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002459 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002460 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002461 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002462 goto unlock;
2463 }
2464
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002465 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002466 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002467
Johan Hedberg24b78d02012-02-23 23:24:30 +02002468 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002469 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002470 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002471 goto unlock;
2472 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002473
Johan Hedberg9246a862012-02-23 21:33:16 +02002474 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002475 }
2476
2477 found = 0;
2478
Johan Hedberg056341c2013-01-27 00:31:30 +02002479 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2481 continue;
2482
2483 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002484 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002485 found++;
2486 }
2487
2488 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002491 goto unlock;
2492 }
2493
Johan Hedberg9246a862012-02-23 21:33:16 +02002494update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002495 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002496
Johan Hedberg890ea892013-03-15 17:06:52 -05002497 update_class(&req);
2498 update_eir(&req);
2499
Johan Hedberg92da6092013-03-15 17:06:55 -05002500 err = hci_req_run(&req, remove_uuid_complete);
2501 if (err < 0) {
2502 if (err != -ENODATA)
2503 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002504
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002505 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002506 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002507 goto unlock;
2508 }
2509
2510 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002511 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002512 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002513 goto unlock;
2514 }
2515
2516 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002517
2518unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002519 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 return err;
2521}
2522
Johan Hedberg92da6092013-03-15 17:06:55 -05002523static void set_class_complete(struct hci_dev *hdev, u8 status)
2524{
2525 BT_DBG("status 0x%02x", status);
2526
2527 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2528}
2529
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002530static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002531 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002532{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002533 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002534 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002535 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002536 int err;
2537
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002538 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002539
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002540 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002541 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2542 MGMT_STATUS_NOT_SUPPORTED);
2543
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002544 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002545
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002546 if (pending_eir_or_class(hdev)) {
2547 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2548 MGMT_STATUS_BUSY);
2549 goto unlock;
2550 }
2551
2552 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2553 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2554 MGMT_STATUS_INVALID_PARAMS);
2555 goto unlock;
2556 }
2557
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002558 hdev->major_class = cp->major;
2559 hdev->minor_class = cp->minor;
2560
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002561 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002562 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002563 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002564 goto unlock;
2565 }
2566
Johan Hedberg890ea892013-03-15 17:06:52 -05002567 hci_req_init(&req, hdev);
2568
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002569 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002570 hci_dev_unlock(hdev);
2571 cancel_delayed_work_sync(&hdev->service_cache);
2572 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002573 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002574 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002575
Johan Hedberg890ea892013-03-15 17:06:52 -05002576 update_class(&req);
2577
Johan Hedberg92da6092013-03-15 17:06:55 -05002578 err = hci_req_run(&req, set_class_complete);
2579 if (err < 0) {
2580 if (err != -ENODATA)
2581 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002582
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002583 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002584 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002585 goto unlock;
2586 }
2587
2588 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002589 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002590 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002591 goto unlock;
2592 }
2593
2594 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002595
Johan Hedbergb5235a62012-02-21 14:32:24 +02002596unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002597 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002598 return err;
2599}
2600
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002601static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002602 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002603{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002604 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002605 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2606 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002607 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002608 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002609 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002610
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002611 BT_DBG("request for %s", hdev->name);
2612
2613 if (!lmp_bredr_capable(hdev))
2614 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2615 MGMT_STATUS_NOT_SUPPORTED);
2616
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002617 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002618 if (key_count > max_key_count) {
2619 BT_ERR("load_link_keys: too big key_count value %u",
2620 key_count);
2621 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2622 MGMT_STATUS_INVALID_PARAMS);
2623 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002624
Johan Hedberg86742e12011-11-07 23:13:38 +02002625 expected_len = sizeof(*cp) + key_count *
2626 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002627 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002628 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002629 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002630 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002631 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632 }
2633
Johan Hedberg4ae14302013-01-20 14:27:13 +02002634 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2635 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2636 MGMT_STATUS_INVALID_PARAMS);
2637
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002638 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002639 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002640
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002641 for (i = 0; i < key_count; i++) {
2642 struct mgmt_link_key_info *key = &cp->keys[i];
2643
Marcel Holtmann8e991132014-01-10 02:07:25 -08002644 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002645 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2646 MGMT_STATUS_INVALID_PARAMS);
2647 }
2648
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002649 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002650
2651 hci_link_keys_clear(hdev);
2652
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002654 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2655 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002656 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002657 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2658 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002659
2660 if (changed)
2661 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002662
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002663 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002664 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002665
Johan Hedberg58e92932014-06-24 14:00:26 +03002666 /* Always ignore debug keys and require a new pairing if
2667 * the user wants to use them.
2668 */
2669 if (key->type == HCI_LK_DEBUG_COMBINATION)
2670 continue;
2671
Johan Hedberg7652ff62014-06-24 13:15:49 +03002672 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2673 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002674 }
2675
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002676 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002677
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002678 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002680 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002681}
2682
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002683static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002684 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002685{
2686 struct mgmt_ev_device_unpaired ev;
2687
2688 bacpy(&ev.addr.bdaddr, bdaddr);
2689 ev.addr.type = addr_type;
2690
2691 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002692 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002693}
2694
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002695static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002696 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002697{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002698 struct mgmt_cp_unpair_device *cp = data;
2699 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002700 struct hci_cp_disconnect dc;
2701 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703 int err;
2704
Johan Hedberga8a1d192011-11-10 15:54:38 +02002705 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002706 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2707 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002708
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002709 if (!bdaddr_type_is_valid(cp->addr.type))
2710 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2711 MGMT_STATUS_INVALID_PARAMS,
2712 &rp, sizeof(rp));
2713
Johan Hedberg118da702013-01-20 14:27:20 +02002714 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2715 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2716 MGMT_STATUS_INVALID_PARAMS,
2717 &rp, sizeof(rp));
2718
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002719 hci_dev_lock(hdev);
2720
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002721 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002722 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002723 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002724 goto unlock;
2725 }
2726
Johan Hedberge0b2b272014-02-18 17:14:31 +02002727 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002728 /* If disconnection is requested, then look up the
2729 * connection. If the remote device is connected, it
2730 * will be later used to terminate the link.
2731 *
2732 * Setting it to NULL explicitly will cause no
2733 * termination of the link.
2734 */
2735 if (cp->disconnect)
2736 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2737 &cp->addr.bdaddr);
2738 else
2739 conn = NULL;
2740
Johan Hedberg124f6e32012-02-09 13:50:12 +02002741 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002742 } else {
2743 u8 addr_type;
2744
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002745 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2746 &cp->addr.bdaddr);
2747 if (conn) {
2748 /* Defer clearing up the connection parameters
2749 * until closing to give a chance of keeping
2750 * them if a repairing happens.
2751 */
2752 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2753
2754 /* If disconnection is not requested, then
2755 * clear the connection variable so that the
2756 * link is not terminated.
2757 */
2758 if (!cp->disconnect)
2759 conn = NULL;
2760 }
2761
Johan Hedberge0b2b272014-02-18 17:14:31 +02002762 if (cp->addr.type == BDADDR_LE_PUBLIC)
2763 addr_type = ADDR_LE_DEV_PUBLIC;
2764 else
2765 addr_type = ADDR_LE_DEV_RANDOM;
2766
Johan Hedberga7ec7332014-02-18 17:14:35 +02002767 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2768
Johan Hedberge0b2b272014-02-18 17:14:31 +02002769 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2770 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002771
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002772 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002773 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002774 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002775 goto unlock;
2776 }
2777
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002778 /* If the connection variable is set, then termination of the
2779 * link is requested.
2780 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002781 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002782 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002783 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002784 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002785 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002786 }
2787
Johan Hedberg124f6e32012-02-09 13:50:12 +02002788 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002789 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002790 if (!cmd) {
2791 err = -ENOMEM;
2792 goto unlock;
2793 }
2794
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002795 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002796 dc.reason = 0x13; /* Remote User Terminated Connection */
2797 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2798 if (err < 0)
2799 mgmt_pending_remove(cmd);
2800
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002801unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002802 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002803 return err;
2804}
2805
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002806static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002807 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002808{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002809 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002810 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002811 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002812 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002813 int err;
2814
2815 BT_DBG("");
2816
Johan Hedberg06a63b12013-01-20 14:27:21 +02002817 memset(&rp, 0, sizeof(rp));
2818 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2819 rp.addr.type = cp->addr.type;
2820
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002821 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002822 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2823 MGMT_STATUS_INVALID_PARAMS,
2824 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002825
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002826 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002827
2828 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002829 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2830 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002831 goto failed;
2832 }
2833
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002834 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002835 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2836 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002837 goto failed;
2838 }
2839
Andre Guedes591f47f2012-04-24 21:02:49 -03002840 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002841 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2842 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002843 else
2844 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002845
Vishal Agarwalf9607272012-06-13 05:32:43 +05302846 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002847 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2848 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002849 goto failed;
2850 }
2851
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002852 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002853 if (!cmd) {
2854 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002855 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002856 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002857
Johan Hedberge3f2f922014-08-18 20:33:33 +03002858 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002859 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002860 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002861
2862failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002863 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002864 return err;
2865}
2866
Andre Guedes57c14772012-04-24 21:02:50 -03002867static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002868{
2869 switch (link_type) {
2870 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002871 switch (addr_type) {
2872 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002873 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002874
Johan Hedberg48264f02011-11-09 13:58:58 +02002875 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002876 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002877 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002878 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002879
Johan Hedberg4c659c32011-11-07 23:13:39 +02002880 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002881 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002882 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002883 }
2884}
2885
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002886static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2887 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002888{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002889 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002890 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002891 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002892 int err;
2893 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002894
2895 BT_DBG("");
2896
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002897 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002898
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002899 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002900 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002901 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002902 goto unlock;
2903 }
2904
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002905 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002906 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2907 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002908 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002909 }
2910
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002911 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002912 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002913 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002914 err = -ENOMEM;
2915 goto unlock;
2916 }
2917
Johan Hedberg2784eb42011-01-21 13:56:35 +02002918 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002919 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002920 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2921 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002922 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002923 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002924 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002925 continue;
2926 i++;
2927 }
2928
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002929 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002930
Johan Hedberg4c659c32011-11-07 23:13:39 +02002931 /* Recalculate length in case of filtered SCO connections, etc */
2932 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002933
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002934 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002935 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002936
Johan Hedberga38528f2011-01-22 06:46:43 +02002937 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002938
2939unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002940 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002941 return err;
2942}
2943
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002944static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002945 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002946{
2947 struct pending_cmd *cmd;
2948 int err;
2949
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002950 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002951 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002952 if (!cmd)
2953 return -ENOMEM;
2954
Johan Hedbergd8457692012-02-17 14:24:57 +02002955 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002956 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002957 if (err < 0)
2958 mgmt_pending_remove(cmd);
2959
2960 return err;
2961}
2962
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002963static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002964 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002965{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002966 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002967 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002968 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002969 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002970 int err;
2971
2972 BT_DBG("");
2973
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002974 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002975
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002976 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002977 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002979 goto failed;
2980 }
2981
Johan Hedbergd8457692012-02-17 14:24:57 +02002982 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002983 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002984 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002985 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002986 goto failed;
2987 }
2988
2989 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002990 struct mgmt_cp_pin_code_neg_reply ncp;
2991
2992 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002993
2994 BT_ERR("PIN code is not 16 bytes long");
2995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002996 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002997 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002998 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002999 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003000
3001 goto failed;
3002 }
3003
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003004 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003005 if (!cmd) {
3006 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003007 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003008 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003009
Johan Hedbergd8457692012-02-17 14:24:57 +02003010 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003011 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003012 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003013
3014 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3015 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003016 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003017
3018failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003019 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003020 return err;
3021}
3022
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003023static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3024 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003025{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003026 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003027
3028 BT_DBG("");
3029
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003030 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3031 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3032 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3033
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003034 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003035
3036 hdev->io_capability = cp->io_capability;
3037
3038 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003039 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003040
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003041 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003042
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003043 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3044 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003045}
3046
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003047static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003048{
3049 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003050 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003051
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003052 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003053 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3054 continue;
3055
Johan Hedberge9a416b2011-02-19 12:05:56 -03003056 if (cmd->user_data != conn)
3057 continue;
3058
3059 return cmd;
3060 }
3061
3062 return NULL;
3063}
3064
3065static void pairing_complete(struct pending_cmd *cmd, u8 status)
3066{
3067 struct mgmt_rp_pair_device rp;
3068 struct hci_conn *conn = cmd->user_data;
3069
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003070 bacpy(&rp.addr.bdaddr, &conn->dst);
3071 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003072
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003073 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003074 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003075
3076 /* So we don't get further callbacks for this connection */
3077 conn->connect_cfm_cb = NULL;
3078 conn->security_cfm_cb = NULL;
3079 conn->disconn_cfm_cb = NULL;
3080
David Herrmann76a68ba2013-04-06 20:28:37 +02003081 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003082 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003083
Johan Hedberga664b5b2011-02-19 12:06:02 -03003084 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003085
3086 /* The device is paired so there is no need to remove
3087 * its connection parameters anymore.
3088 */
3089 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003090}
3091
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003092void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3093{
3094 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3095 struct pending_cmd *cmd;
3096
3097 cmd = find_pairing(conn);
3098 if (cmd)
3099 pairing_complete(cmd, status);
3100}
3101
Johan Hedberge9a416b2011-02-19 12:05:56 -03003102static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3103{
3104 struct pending_cmd *cmd;
3105
3106 BT_DBG("status %u", status);
3107
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003108 cmd = find_pairing(conn);
3109 if (!cmd)
3110 BT_DBG("Unable to find a pending command");
3111 else
Johan Hedberge2113262012-02-18 15:20:03 +02003112 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003113}
3114
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003115static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303116{
3117 struct pending_cmd *cmd;
3118
3119 BT_DBG("status %u", status);
3120
3121 if (!status)
3122 return;
3123
3124 cmd = find_pairing(conn);
3125 if (!cmd)
3126 BT_DBG("Unable to find a pending command");
3127 else
3128 pairing_complete(cmd, mgmt_status(status));
3129}
3130
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003131static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003132 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003133{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003134 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003135 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003136 struct pending_cmd *cmd;
3137 u8 sec_level, auth_type;
3138 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003139 int err;
3140
3141 BT_DBG("");
3142
Szymon Jancf950a30e2013-01-18 12:48:07 +01003143 memset(&rp, 0, sizeof(rp));
3144 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3145 rp.addr.type = cp->addr.type;
3146
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003147 if (!bdaddr_type_is_valid(cp->addr.type))
3148 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3149 MGMT_STATUS_INVALID_PARAMS,
3150 &rp, sizeof(rp));
3151
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003152 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3153 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3154 MGMT_STATUS_INVALID_PARAMS,
3155 &rp, sizeof(rp));
3156
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003157 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003158
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003159 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003160 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3161 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003162 goto unlock;
3163 }
3164
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003165 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003166 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003167
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003168 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003169 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3170 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003171 } else {
3172 u8 addr_type;
3173
3174 /* Convert from L2CAP channel address type to HCI address type
3175 */
3176 if (cp->addr.type == BDADDR_LE_PUBLIC)
3177 addr_type = ADDR_LE_DEV_PUBLIC;
3178 else
3179 addr_type = ADDR_LE_DEV_RANDOM;
3180
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003181 /* When pairing a new device, it is expected to remember
3182 * this device for future connections. Adding the connection
3183 * parameter information ahead of time allows tracking
3184 * of the slave preferred values and will speed up any
3185 * further connection establishment.
3186 *
3187 * If connection parameters already exist, then they
3188 * will be kept and this function does nothing.
3189 */
3190 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3191
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003192 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003193 sec_level, HCI_LE_CONN_TIMEOUT,
3194 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003195 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003196
Ville Tervo30e76272011-02-22 16:10:53 -03003197 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003198 int status;
3199
3200 if (PTR_ERR(conn) == -EBUSY)
3201 status = MGMT_STATUS_BUSY;
3202 else
3203 status = MGMT_STATUS_CONNECT_FAILED;
3204
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003205 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003206 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003207 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003208 goto unlock;
3209 }
3210
3211 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003212 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003213 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003214 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003215 goto unlock;
3216 }
3217
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003218 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003219 if (!cmd) {
3220 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003221 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003222 goto unlock;
3223 }
3224
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003225 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003226 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003227 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003228 conn->security_cfm_cb = pairing_complete_cb;
3229 conn->disconn_cfm_cb = pairing_complete_cb;
3230 } else {
3231 conn->connect_cfm_cb = le_pairing_complete_cb;
3232 conn->security_cfm_cb = le_pairing_complete_cb;
3233 conn->disconn_cfm_cb = le_pairing_complete_cb;
3234 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003235
Johan Hedberge9a416b2011-02-19 12:05:56 -03003236 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003237 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003238
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003239 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003240 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003241 pairing_complete(cmd, 0);
3242
3243 err = 0;
3244
3245unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003246 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003247 return err;
3248}
3249
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003250static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3251 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003252{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003253 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003254 struct pending_cmd *cmd;
3255 struct hci_conn *conn;
3256 int err;
3257
3258 BT_DBG("");
3259
Johan Hedberg28424702012-02-02 04:02:29 +02003260 hci_dev_lock(hdev);
3261
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003262 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003263 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003264 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003265 goto unlock;
3266 }
3267
Johan Hedberg28424702012-02-02 04:02:29 +02003268 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3269 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003270 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003271 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003272 goto unlock;
3273 }
3274
3275 conn = cmd->user_data;
3276
3277 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003278 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003279 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003280 goto unlock;
3281 }
3282
3283 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3284
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003285 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003286 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003287unlock:
3288 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003289 return err;
3290}
3291
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003292static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003293 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003294 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003295{
Johan Hedberga5c29682011-02-19 12:05:57 -03003296 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003297 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003298 int err;
3299
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003300 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003301
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003302 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003303 err = cmd_complete(sk, hdev->id, mgmt_op,
3304 MGMT_STATUS_NOT_POWERED, addr,
3305 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003306 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003307 }
3308
Johan Hedberg1707c602013-03-15 17:07:15 -05003309 if (addr->type == BDADDR_BREDR)
3310 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003311 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003312 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003313
Johan Hedberg272d90d2012-02-09 15:26:12 +02003314 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003315 err = cmd_complete(sk, hdev->id, mgmt_op,
3316 MGMT_STATUS_NOT_CONNECTED, addr,
3317 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003318 goto done;
3319 }
3320
Johan Hedberg1707c602013-03-15 17:07:15 -05003321 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003322 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003323 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003324 err = cmd_complete(sk, hdev->id, mgmt_op,
3325 MGMT_STATUS_SUCCESS, addr,
3326 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003327 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003328 err = cmd_complete(sk, hdev->id, mgmt_op,
3329 MGMT_STATUS_FAILED, addr,
3330 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003331
Brian Gix47c15e22011-11-16 13:53:14 -08003332 goto done;
3333 }
3334
Johan Hedberg1707c602013-03-15 17:07:15 -05003335 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003336 if (!cmd) {
3337 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003338 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003339 }
3340
Brian Gix0df4c182011-11-16 13:53:13 -08003341 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003342 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3343 struct hci_cp_user_passkey_reply cp;
3344
Johan Hedberg1707c602013-03-15 17:07:15 -05003345 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003346 cp.passkey = passkey;
3347 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3348 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003349 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3350 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003351
Johan Hedberga664b5b2011-02-19 12:06:02 -03003352 if (err < 0)
3353 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003354
Brian Gix0df4c182011-11-16 13:53:13 -08003355done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003356 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003357 return err;
3358}
3359
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303360static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3361 void *data, u16 len)
3362{
3363 struct mgmt_cp_pin_code_neg_reply *cp = data;
3364
3365 BT_DBG("");
3366
Johan Hedberg1707c602013-03-15 17:07:15 -05003367 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303368 MGMT_OP_PIN_CODE_NEG_REPLY,
3369 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3370}
3371
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003372static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3373 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003374{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003375 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003376
3377 BT_DBG("");
3378
3379 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003380 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003381 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003382
Johan Hedberg1707c602013-03-15 17:07:15 -05003383 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003384 MGMT_OP_USER_CONFIRM_REPLY,
3385 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003386}
3387
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003388static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003389 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003390{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003391 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003392
3393 BT_DBG("");
3394
Johan Hedberg1707c602013-03-15 17:07:15 -05003395 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003396 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3397 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003398}
3399
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003400static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3401 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003402{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003403 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003404
3405 BT_DBG("");
3406
Johan Hedberg1707c602013-03-15 17:07:15 -05003407 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003408 MGMT_OP_USER_PASSKEY_REPLY,
3409 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003410}
3411
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003412static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003413 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003414{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003415 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003416
3417 BT_DBG("");
3418
Johan Hedberg1707c602013-03-15 17:07:15 -05003419 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003420 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3421 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003422}
3423
Johan Hedberg13928972013-03-15 17:07:00 -05003424static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003425{
Johan Hedberg13928972013-03-15 17:07:00 -05003426 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003427 struct hci_cp_write_local_name cp;
3428
Johan Hedberg13928972013-03-15 17:07:00 -05003429 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003430
Johan Hedberg890ea892013-03-15 17:06:52 -05003431 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003432}
3433
Johan Hedberg13928972013-03-15 17:07:00 -05003434static void set_name_complete(struct hci_dev *hdev, u8 status)
3435{
3436 struct mgmt_cp_set_local_name *cp;
3437 struct pending_cmd *cmd;
3438
3439 BT_DBG("status 0x%02x", status);
3440
3441 hci_dev_lock(hdev);
3442
3443 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3444 if (!cmd)
3445 goto unlock;
3446
3447 cp = cmd->param;
3448
3449 if (status)
3450 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3451 mgmt_status(status));
3452 else
3453 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3454 cp, sizeof(*cp));
3455
3456 mgmt_pending_remove(cmd);
3457
3458unlock:
3459 hci_dev_unlock(hdev);
3460}
3461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003462static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003463 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003464{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003465 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003466 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003467 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003468 int err;
3469
3470 BT_DBG("");
3471
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003472 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003473
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003474 /* If the old values are the same as the new ones just return a
3475 * direct command complete event.
3476 */
3477 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3478 !memcmp(hdev->short_name, cp->short_name,
3479 sizeof(hdev->short_name))) {
3480 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3481 data, len);
3482 goto failed;
3483 }
3484
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003485 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003486
Johan Hedbergb5235a62012-02-21 14:32:24 +02003487 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003488 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003489
3490 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003491 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003492 if (err < 0)
3493 goto failed;
3494
3495 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003496 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003497
Johan Hedbergb5235a62012-02-21 14:32:24 +02003498 goto failed;
3499 }
3500
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003501 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003502 if (!cmd) {
3503 err = -ENOMEM;
3504 goto failed;
3505 }
3506
Johan Hedberg13928972013-03-15 17:07:00 -05003507 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3508
Johan Hedberg890ea892013-03-15 17:06:52 -05003509 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003510
3511 if (lmp_bredr_capable(hdev)) {
3512 update_name(&req);
3513 update_eir(&req);
3514 }
3515
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003516 /* The name is stored in the scan response data and so
3517 * no need to udpate the advertising data here.
3518 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003519 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003520 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003521
Johan Hedberg13928972013-03-15 17:07:00 -05003522 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003523 if (err < 0)
3524 mgmt_pending_remove(cmd);
3525
3526failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003527 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003528 return err;
3529}
3530
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003531static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003532 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003533{
Szymon Jancc35938b2011-03-22 13:12:21 +01003534 struct pending_cmd *cmd;
3535 int err;
3536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003537 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003538
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003539 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003540
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003541 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003542 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003543 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003544 goto unlock;
3545 }
3546
Andre Guedes9a1a1992012-07-24 15:03:48 -03003547 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003548 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003549 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003550 goto unlock;
3551 }
3552
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003553 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003554 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003555 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003556 goto unlock;
3557 }
3558
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003559 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003560 if (!cmd) {
3561 err = -ENOMEM;
3562 goto unlock;
3563 }
3564
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003565 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3566 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3567 0, NULL);
3568 else
3569 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3570
Szymon Jancc35938b2011-03-22 13:12:21 +01003571 if (err < 0)
3572 mgmt_pending_remove(cmd);
3573
3574unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003575 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003576 return err;
3577}
3578
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003579static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003580 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003581{
Szymon Janc2763eda2011-03-22 13:12:22 +01003582 int err;
3583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003584 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003585
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003586 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003587
Marcel Holtmannec109112014-01-10 02:07:30 -08003588 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3589 struct mgmt_cp_add_remote_oob_data *cp = data;
3590 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003591
Johan Hedbergc19a4952014-11-17 20:52:19 +02003592 if (cp->addr.type != BDADDR_BREDR) {
3593 err = cmd_complete(sk, hdev->id,
3594 MGMT_OP_ADD_REMOTE_OOB_DATA,
3595 MGMT_STATUS_INVALID_PARAMS,
3596 &cp->addr, sizeof(cp->addr));
3597 goto unlock;
3598 }
3599
Marcel Holtmannec109112014-01-10 02:07:30 -08003600 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg38da1702014-11-17 20:52:20 +02003601 cp->hash, cp->rand);
Marcel Holtmannec109112014-01-10 02:07:30 -08003602 if (err < 0)
3603 status = MGMT_STATUS_FAILED;
3604 else
3605 status = MGMT_STATUS_SUCCESS;
3606
3607 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3608 status, &cp->addr, sizeof(cp->addr));
3609 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3610 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3611 u8 status;
3612
Johan Hedbergc19a4952014-11-17 20:52:19 +02003613 if (cp->addr.type != BDADDR_BREDR) {
3614 err = cmd_complete(sk, hdev->id,
3615 MGMT_OP_ADD_REMOTE_OOB_DATA,
3616 MGMT_STATUS_INVALID_PARAMS,
3617 &cp->addr, sizeof(cp->addr));
3618 goto unlock;
3619 }
3620
Marcel Holtmannec109112014-01-10 02:07:30 -08003621 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
Johan Hedberg38da1702014-11-17 20:52:20 +02003622 cp->hash192, cp->rand192,
3623 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003624 if (err < 0)
3625 status = MGMT_STATUS_FAILED;
3626 else
3627 status = MGMT_STATUS_SUCCESS;
3628
3629 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3630 status, &cp->addr, sizeof(cp->addr));
3631 } else {
3632 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3633 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3634 MGMT_STATUS_INVALID_PARAMS);
3635 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003636
Johan Hedbergc19a4952014-11-17 20:52:19 +02003637unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003638 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003639 return err;
3640}
3641
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003642static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003643 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003644{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003645 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003646 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003647 int err;
3648
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003649 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003650
Johan Hedbergc19a4952014-11-17 20:52:19 +02003651 if (cp->addr.type != BDADDR_BREDR)
3652 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3653 MGMT_STATUS_INVALID_PARAMS,
3654 &cp->addr, sizeof(cp->addr));
3655
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003656 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003657
Johan Hedbergeedbd582014-11-15 09:34:23 +02003658 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3659 hci_remote_oob_data_clear(hdev);
3660 status = MGMT_STATUS_SUCCESS;
3661 goto done;
3662 }
3663
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003664 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003665 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003666 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003667 else
Szymon Janca6785be2012-12-13 15:11:21 +01003668 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003669
Johan Hedbergeedbd582014-11-15 09:34:23 +02003670done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003671 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003672 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003673
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003674 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003675 return err;
3676}
3677
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003678static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3679{
3680 struct pending_cmd *cmd;
3681 u8 type;
3682 int err;
3683
3684 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3685
3686 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3687 if (!cmd)
3688 return -ENOENT;
3689
3690 type = hdev->discovery.type;
3691
3692 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3693 &type, sizeof(type));
3694 mgmt_pending_remove(cmd);
3695
3696 return err;
3697}
3698
Andre Guedes7c307722013-04-30 15:29:28 -03003699static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3700{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003701 unsigned long timeout = 0;
3702
Andre Guedes7c307722013-04-30 15:29:28 -03003703 BT_DBG("status %d", status);
3704
3705 if (status) {
3706 hci_dev_lock(hdev);
3707 mgmt_start_discovery_failed(hdev, status);
3708 hci_dev_unlock(hdev);
3709 return;
3710 }
3711
3712 hci_dev_lock(hdev);
3713 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3714 hci_dev_unlock(hdev);
3715
3716 switch (hdev->discovery.type) {
3717 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003718 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003719 break;
3720
3721 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003722 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003723 break;
3724
3725 case DISCOV_TYPE_BREDR:
3726 break;
3727
3728 default:
3729 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3730 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003731
3732 if (!timeout)
3733 return;
3734
3735 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003736}
3737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003738static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003739 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003740{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003741 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003742 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003743 struct hci_cp_le_set_scan_param param_cp;
3744 struct hci_cp_le_set_scan_enable enable_cp;
3745 struct hci_cp_inquiry inq_cp;
3746 struct hci_request req;
3747 /* General inquiry access code (GIAC) */
3748 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003749 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003750 int err;
3751
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003752 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003753
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003754 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003755
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003756 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003757 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3758 MGMT_STATUS_NOT_POWERED,
3759 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003760 goto failed;
3761 }
3762
Andre Guedes642be6c2012-03-21 00:03:37 -03003763 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003764 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3765 MGMT_STATUS_BUSY, &cp->type,
3766 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003767 goto failed;
3768 }
3769
Johan Hedbergff9ef572012-01-04 14:23:45 +02003770 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Szymon Janca736abc2014-11-03 14:20:56 +01003771 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3772 MGMT_STATUS_BUSY, &cp->type,
3773 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003774 goto failed;
3775 }
3776
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003777 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003778 if (!cmd) {
3779 err = -ENOMEM;
3780 goto failed;
3781 }
3782
Andre Guedes4aab14e2012-02-17 20:39:36 -03003783 hdev->discovery.type = cp->type;
3784
Andre Guedes7c307722013-04-30 15:29:28 -03003785 hci_req_init(&req, hdev);
3786
Andre Guedes4aab14e2012-02-17 20:39:36 -03003787 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003788 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003789 status = mgmt_bredr_support(hdev);
3790 if (status) {
Szymon Janca736abc2014-11-03 14:20:56 +01003791 err = cmd_complete(sk, hdev->id,
3792 MGMT_OP_START_DISCOVERY, status,
3793 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003794 mgmt_pending_remove(cmd);
3795 goto failed;
3796 }
3797
Andre Guedes7c307722013-04-30 15:29:28 -03003798 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003799 err = cmd_complete(sk, hdev->id,
3800 MGMT_OP_START_DISCOVERY,
3801 MGMT_STATUS_BUSY, &cp->type,
3802 sizeof(cp->type));
Andre Guedes7c307722013-04-30 15:29:28 -03003803 mgmt_pending_remove(cmd);
3804 goto failed;
3805 }
3806
3807 hci_inquiry_cache_flush(hdev);
3808
3809 memset(&inq_cp, 0, sizeof(inq_cp));
3810 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003811 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003812 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003813 break;
3814
3815 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003816 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003817 status = mgmt_le_support(hdev);
3818 if (status) {
Szymon Janca736abc2014-11-03 14:20:56 +01003819 err = cmd_complete(sk, hdev->id,
3820 MGMT_OP_START_DISCOVERY, status,
3821 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003822 mgmt_pending_remove(cmd);
3823 goto failed;
3824 }
3825
Andre Guedes7c307722013-04-30 15:29:28 -03003826 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003827 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003828 err = cmd_complete(sk, hdev->id,
3829 MGMT_OP_START_DISCOVERY,
3830 MGMT_STATUS_NOT_SUPPORTED,
3831 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003832 mgmt_pending_remove(cmd);
3833 goto failed;
3834 }
3835
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003836 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3837 /* Don't let discovery abort an outgoing
3838 * connection attempt that's using directed
3839 * advertising.
3840 */
3841 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3842 BT_CONNECT)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003843 err = cmd_complete(sk, hdev->id,
3844 MGMT_OP_START_DISCOVERY,
3845 MGMT_STATUS_REJECTED,
3846 &cp->type,
3847 sizeof(cp->type));
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003848 mgmt_pending_remove(cmd);
3849 goto failed;
3850 }
3851
3852 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003853 }
3854
Andre Guedesc54c3862014-02-26 20:21:50 -03003855 /* If controller is scanning, it means the background scanning
3856 * is running. Thus, we should temporarily stop it in order to
3857 * set the discovery scanning parameters.
3858 */
3859 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3860 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003861
3862 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003863
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003864 /* All active scans will be done with either a resolvable
3865 * private address (when privacy feature has been enabled)
3866 * or unresolvable private address.
3867 */
3868 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003869 if (err < 0) {
Szymon Janca736abc2014-11-03 14:20:56 +01003870 err = cmd_complete(sk, hdev->id,
3871 MGMT_OP_START_DISCOVERY,
3872 MGMT_STATUS_FAILED,
3873 &cp->type, sizeof(cp->type));
Johan Hedbergd9483942014-02-23 19:42:24 +02003874 mgmt_pending_remove(cmd);
3875 goto failed;
3876 }
3877
Andre Guedes7c307722013-04-30 15:29:28 -03003878 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003879 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3880 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003881 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003882 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3883 &param_cp);
3884
3885 memset(&enable_cp, 0, sizeof(enable_cp));
3886 enable_cp.enable = LE_SCAN_ENABLE;
3887 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3888 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3889 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003890 break;
3891
Andre Guedesf39799f2012-02-17 20:39:35 -03003892 default:
Szymon Janca736abc2014-11-03 14:20:56 +01003893 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3894 MGMT_STATUS_INVALID_PARAMS,
3895 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003896 mgmt_pending_remove(cmd);
3897 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003898 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003899
Andre Guedes7c307722013-04-30 15:29:28 -03003900 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003901 if (err < 0)
3902 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003903 else
3904 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003905
3906failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003907 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003908 return err;
3909}
3910
Andre Guedes1183fdc2013-04-30 15:29:35 -03003911static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3912{
3913 struct pending_cmd *cmd;
3914 int err;
3915
3916 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3917 if (!cmd)
3918 return -ENOENT;
3919
3920 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3921 &hdev->discovery.type, sizeof(hdev->discovery.type));
3922 mgmt_pending_remove(cmd);
3923
3924 return err;
3925}
3926
Andre Guedes0e05bba2013-04-30 15:29:33 -03003927static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3928{
3929 BT_DBG("status %d", status);
3930
3931 hci_dev_lock(hdev);
3932
3933 if (status) {
3934 mgmt_stop_discovery_failed(hdev, status);
3935 goto unlock;
3936 }
3937
3938 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3939
3940unlock:
3941 hci_dev_unlock(hdev);
3942}
3943
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003944static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003945 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003946{
Johan Hedbergd9306502012-02-20 23:25:18 +02003947 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003948 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003949 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003950 int err;
3951
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003952 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003953
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003954 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003955
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003956 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003957 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003958 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3959 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003960 goto unlock;
3961 }
3962
3963 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003964 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003965 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3966 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003967 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003968 }
3969
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003970 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003971 if (!cmd) {
3972 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003973 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003974 }
3975
Andre Guedes0e05bba2013-04-30 15:29:33 -03003976 hci_req_init(&req, hdev);
3977
Johan Hedberg21a60d32014-06-10 14:05:58 +03003978 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003979
Johan Hedberg21a60d32014-06-10 14:05:58 +03003980 err = hci_req_run(&req, stop_discovery_complete);
3981 if (!err) {
3982 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003983 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003984 }
3985
Johan Hedberg21a60d32014-06-10 14:05:58 +03003986 mgmt_pending_remove(cmd);
3987
3988 /* If no HCI commands were sent we're done */
3989 if (err == -ENODATA) {
3990 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3991 &mgmt_cp->type, sizeof(mgmt_cp->type));
3992 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3993 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003994
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003995unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003996 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003997 return err;
3998}
3999
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004000static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004001 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004002{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004003 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004004 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004005 int err;
4006
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004007 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004008
Johan Hedberg561aafb2012-01-04 13:31:59 +02004009 hci_dev_lock(hdev);
4010
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004011 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004012 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4013 MGMT_STATUS_FAILED, &cp->addr,
4014 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004015 goto failed;
4016 }
4017
Johan Hedberga198e7b2012-02-17 14:27:06 +02004018 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004019 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004020 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4021 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4022 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004023 goto failed;
4024 }
4025
4026 if (cp->name_known) {
4027 e->name_state = NAME_KNOWN;
4028 list_del(&e->list);
4029 } else {
4030 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004031 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004032 }
4033
Johan Hedberge3846622013-01-09 15:29:33 +02004034 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4035 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004036
4037failed:
4038 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004039 return err;
4040}
4041
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004042static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004043 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004044{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004045 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004046 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004047 int err;
4048
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004049 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004050
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004051 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004052 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4053 MGMT_STATUS_INVALID_PARAMS,
4054 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004055
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004056 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004057
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004058 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4059 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004060 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004061 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004062 goto done;
4063 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004064
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004065 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4066 sk);
4067 status = MGMT_STATUS_SUCCESS;
4068
4069done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004070 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004071 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004072
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004073 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004074
4075 return err;
4076}
4077
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004078static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004079 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004080{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004081 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004082 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004083 int err;
4084
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004085 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004086
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004087 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004088 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4089 MGMT_STATUS_INVALID_PARAMS,
4090 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004091
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004092 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004093
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004094 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4095 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004096 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004097 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004098 goto done;
4099 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004100
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004101 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4102 sk);
4103 status = MGMT_STATUS_SUCCESS;
4104
4105done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004106 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004107 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004108
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004109 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004110
4111 return err;
4112}
4113
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004114static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4115 u16 len)
4116{
4117 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004118 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004119 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004120 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004121
4122 BT_DBG("%s", hdev->name);
4123
Szymon Jancc72d4b82012-03-16 16:02:57 +01004124 source = __le16_to_cpu(cp->source);
4125
4126 if (source > 0x0002)
4127 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4128 MGMT_STATUS_INVALID_PARAMS);
4129
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004130 hci_dev_lock(hdev);
4131
Szymon Jancc72d4b82012-03-16 16:02:57 +01004132 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004133 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4134 hdev->devid_product = __le16_to_cpu(cp->product);
4135 hdev->devid_version = __le16_to_cpu(cp->version);
4136
4137 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4138
Johan Hedberg890ea892013-03-15 17:06:52 -05004139 hci_req_init(&req, hdev);
4140 update_eir(&req);
4141 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004142
4143 hci_dev_unlock(hdev);
4144
4145 return err;
4146}
4147
Johan Hedberg4375f102013-09-25 13:26:10 +03004148static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4149{
4150 struct cmd_lookup match = { NULL, hdev };
4151
4152 if (status) {
4153 u8 mgmt_err = mgmt_status(status);
4154
4155 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4156 cmd_status_rsp, &mgmt_err);
4157 return;
4158 }
4159
Johan Hedbergc93bd152014-07-08 15:07:48 +03004160 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4161 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4162 else
4163 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4164
Johan Hedberg4375f102013-09-25 13:26:10 +03004165 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4166 &match);
4167
4168 new_settings(hdev, match.sk);
4169
4170 if (match.sk)
4171 sock_put(match.sk);
4172}
4173
Marcel Holtmann21b51872013-10-10 09:47:53 -07004174static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4175 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004176{
4177 struct mgmt_mode *cp = data;
4178 struct pending_cmd *cmd;
4179 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004180 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004181 int err;
4182
4183 BT_DBG("request for %s", hdev->name);
4184
Johan Hedberge6fe7982013-10-02 15:45:22 +03004185 status = mgmt_le_support(hdev);
4186 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004187 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004188 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004189
4190 if (cp->val != 0x00 && cp->val != 0x01)
4191 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4192 MGMT_STATUS_INVALID_PARAMS);
4193
4194 hci_dev_lock(hdev);
4195
4196 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004197 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004198
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004199 /* The following conditions are ones which mean that we should
4200 * not do any HCI communication but directly send a mgmt
4201 * response to user space (after toggling the flag if
4202 * necessary).
4203 */
4204 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004205 hci_conn_num(hdev, LE_LINK) > 0 ||
4206 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4207 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004208 bool changed = false;
4209
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004210 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4211 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004212 changed = true;
4213 }
4214
4215 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4216 if (err < 0)
4217 goto unlock;
4218
4219 if (changed)
4220 err = new_settings(hdev, sk);
4221
4222 goto unlock;
4223 }
4224
4225 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4226 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4227 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4228 MGMT_STATUS_BUSY);
4229 goto unlock;
4230 }
4231
4232 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4233 if (!cmd) {
4234 err = -ENOMEM;
4235 goto unlock;
4236 }
4237
4238 hci_req_init(&req, hdev);
4239
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004240 if (val)
4241 enable_advertising(&req);
4242 else
4243 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004244
4245 err = hci_req_run(&req, set_advertising_complete);
4246 if (err < 0)
4247 mgmt_pending_remove(cmd);
4248
4249unlock:
4250 hci_dev_unlock(hdev);
4251 return err;
4252}
4253
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004254static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4255 void *data, u16 len)
4256{
4257 struct mgmt_cp_set_static_address *cp = data;
4258 int err;
4259
4260 BT_DBG("%s", hdev->name);
4261
Marcel Holtmann62af4442013-10-02 22:10:32 -07004262 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004263 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004264 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004265
4266 if (hdev_is_powered(hdev))
4267 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4268 MGMT_STATUS_REJECTED);
4269
4270 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4271 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4272 return cmd_status(sk, hdev->id,
4273 MGMT_OP_SET_STATIC_ADDRESS,
4274 MGMT_STATUS_INVALID_PARAMS);
4275
4276 /* Two most significant bits shall be set */
4277 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4278 return cmd_status(sk, hdev->id,
4279 MGMT_OP_SET_STATIC_ADDRESS,
4280 MGMT_STATUS_INVALID_PARAMS);
4281 }
4282
4283 hci_dev_lock(hdev);
4284
4285 bacpy(&hdev->static_addr, &cp->bdaddr);
4286
4287 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4288
4289 hci_dev_unlock(hdev);
4290
4291 return err;
4292}
4293
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004294static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4295 void *data, u16 len)
4296{
4297 struct mgmt_cp_set_scan_params *cp = data;
4298 __u16 interval, window;
4299 int err;
4300
4301 BT_DBG("%s", hdev->name);
4302
4303 if (!lmp_le_capable(hdev))
4304 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4305 MGMT_STATUS_NOT_SUPPORTED);
4306
4307 interval = __le16_to_cpu(cp->interval);
4308
4309 if (interval < 0x0004 || interval > 0x4000)
4310 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4311 MGMT_STATUS_INVALID_PARAMS);
4312
4313 window = __le16_to_cpu(cp->window);
4314
4315 if (window < 0x0004 || window > 0x4000)
4316 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4317 MGMT_STATUS_INVALID_PARAMS);
4318
Marcel Holtmann899e1072013-10-14 09:55:32 -07004319 if (window > interval)
4320 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4321 MGMT_STATUS_INVALID_PARAMS);
4322
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004323 hci_dev_lock(hdev);
4324
4325 hdev->le_scan_interval = interval;
4326 hdev->le_scan_window = window;
4327
4328 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4329
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004330 /* If background scan is running, restart it so new parameters are
4331 * loaded.
4332 */
4333 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4334 hdev->discovery.state == DISCOVERY_STOPPED) {
4335 struct hci_request req;
4336
4337 hci_req_init(&req, hdev);
4338
4339 hci_req_add_le_scan_disable(&req);
4340 hci_req_add_le_passive_scan(&req);
4341
4342 hci_req_run(&req, NULL);
4343 }
4344
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004345 hci_dev_unlock(hdev);
4346
4347 return err;
4348}
4349
Johan Hedberg33e38b32013-03-15 17:07:05 -05004350static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4351{
4352 struct pending_cmd *cmd;
4353
4354 BT_DBG("status 0x%02x", status);
4355
4356 hci_dev_lock(hdev);
4357
4358 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4359 if (!cmd)
4360 goto unlock;
4361
4362 if (status) {
4363 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4364 mgmt_status(status));
4365 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004366 struct mgmt_mode *cp = cmd->param;
4367
4368 if (cp->val)
4369 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4370 else
4371 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4372
Johan Hedberg33e38b32013-03-15 17:07:05 -05004373 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4374 new_settings(hdev, cmd->sk);
4375 }
4376
4377 mgmt_pending_remove(cmd);
4378
4379unlock:
4380 hci_dev_unlock(hdev);
4381}
4382
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004383static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004384 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004385{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004386 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004387 struct pending_cmd *cmd;
4388 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004389 int err;
4390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004391 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004392
Johan Hedberg56f87902013-10-02 13:43:13 +03004393 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4394 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004395 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4396 MGMT_STATUS_NOT_SUPPORTED);
4397
Johan Hedberga7e80f22013-01-09 16:05:19 +02004398 if (cp->val != 0x00 && cp->val != 0x01)
4399 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4400 MGMT_STATUS_INVALID_PARAMS);
4401
Johan Hedberg5400c042012-02-21 16:40:33 +02004402 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004403 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004404 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004405
4406 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004407 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004408 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004409
4410 hci_dev_lock(hdev);
4411
Johan Hedberg05cbf292013-03-15 17:07:07 -05004412 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4413 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4414 MGMT_STATUS_BUSY);
4415 goto unlock;
4416 }
4417
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004418 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4419 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4420 hdev);
4421 goto unlock;
4422 }
4423
Johan Hedberg33e38b32013-03-15 17:07:05 -05004424 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4425 data, len);
4426 if (!cmd) {
4427 err = -ENOMEM;
4428 goto unlock;
4429 }
4430
4431 hci_req_init(&req, hdev);
4432
Johan Hedberg406d7802013-03-15 17:07:09 -05004433 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004434
4435 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004436 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004437 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004438 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004439 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004440 }
4441
Johan Hedberg33e38b32013-03-15 17:07:05 -05004442unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004443 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004444
Antti Julkuf6422ec2011-06-22 13:11:56 +03004445 return err;
4446}
4447
Johan Hedberg0663ca22013-10-02 13:43:14 +03004448static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4449{
4450 struct pending_cmd *cmd;
4451
4452 BT_DBG("status 0x%02x", status);
4453
4454 hci_dev_lock(hdev);
4455
4456 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4457 if (!cmd)
4458 goto unlock;
4459
4460 if (status) {
4461 u8 mgmt_err = mgmt_status(status);
4462
4463 /* We need to restore the flag if related HCI commands
4464 * failed.
4465 */
4466 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4467
4468 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4469 } else {
4470 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4471 new_settings(hdev, cmd->sk);
4472 }
4473
4474 mgmt_pending_remove(cmd);
4475
4476unlock:
4477 hci_dev_unlock(hdev);
4478}
4479
4480static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4481{
4482 struct mgmt_mode *cp = data;
4483 struct pending_cmd *cmd;
4484 struct hci_request req;
4485 int err;
4486
4487 BT_DBG("request for %s", hdev->name);
4488
4489 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4490 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4491 MGMT_STATUS_NOT_SUPPORTED);
4492
4493 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4494 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4495 MGMT_STATUS_REJECTED);
4496
4497 if (cp->val != 0x00 && cp->val != 0x01)
4498 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4499 MGMT_STATUS_INVALID_PARAMS);
4500
4501 hci_dev_lock(hdev);
4502
4503 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4504 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4505 goto unlock;
4506 }
4507
4508 if (!hdev_is_powered(hdev)) {
4509 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004510 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4511 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4512 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4513 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4514 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4515 }
4516
4517 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4518
4519 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4520 if (err < 0)
4521 goto unlock;
4522
4523 err = new_settings(hdev, sk);
4524 goto unlock;
4525 }
4526
4527 /* Reject disabling when powered on */
4528 if (!cp->val) {
4529 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4530 MGMT_STATUS_REJECTED);
4531 goto unlock;
4532 }
4533
4534 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4535 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4536 MGMT_STATUS_BUSY);
4537 goto unlock;
4538 }
4539
4540 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4541 if (!cmd) {
4542 err = -ENOMEM;
4543 goto unlock;
4544 }
4545
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004546 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004547 * generates the correct flags.
4548 */
4549 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4550
4551 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004552
Johan Hedberg432df052014-08-01 11:13:31 +03004553 write_fast_connectable(&req, false);
4554 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004555
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004556 /* Since only the advertising data flags will change, there
4557 * is no need to update the scan response data.
4558 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004559 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004560
Johan Hedberg0663ca22013-10-02 13:43:14 +03004561 err = hci_req_run(&req, set_bredr_complete);
4562 if (err < 0)
4563 mgmt_pending_remove(cmd);
4564
4565unlock:
4566 hci_dev_unlock(hdev);
4567 return err;
4568}
4569
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004570static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4571 void *data, u16 len)
4572{
4573 struct mgmt_mode *cp = data;
4574 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004575 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004576 int err;
4577
4578 BT_DBG("request for %s", hdev->name);
4579
4580 status = mgmt_bredr_support(hdev);
4581 if (status)
4582 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4583 status);
4584
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004585 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004586 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004587 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4588 MGMT_STATUS_NOT_SUPPORTED);
4589
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004590 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004591 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4592 MGMT_STATUS_INVALID_PARAMS);
4593
4594 hci_dev_lock(hdev);
4595
4596 if (!hdev_is_powered(hdev)) {
4597 bool changed;
4598
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004599 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004600 changed = !test_and_set_bit(HCI_SC_ENABLED,
4601 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004602 if (cp->val == 0x02)
4603 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4604 else
4605 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4606 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004607 changed = test_and_clear_bit(HCI_SC_ENABLED,
4608 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004609 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4610 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004611
4612 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4613 if (err < 0)
4614 goto failed;
4615
4616 if (changed)
4617 err = new_settings(hdev, sk);
4618
4619 goto failed;
4620 }
4621
4622 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4623 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4624 MGMT_STATUS_BUSY);
4625 goto failed;
4626 }
4627
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004628 val = !!cp->val;
4629
4630 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4631 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004632 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4633 goto failed;
4634 }
4635
4636 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4637 if (!cmd) {
4638 err = -ENOMEM;
4639 goto failed;
4640 }
4641
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004642 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004643 if (err < 0) {
4644 mgmt_pending_remove(cmd);
4645 goto failed;
4646 }
4647
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004648 if (cp->val == 0x02)
4649 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4650 else
4651 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4652
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004653failed:
4654 hci_dev_unlock(hdev);
4655 return err;
4656}
4657
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004658static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4659 void *data, u16 len)
4660{
4661 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004662 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004663 int err;
4664
4665 BT_DBG("request for %s", hdev->name);
4666
Johan Hedbergb97109792014-06-24 14:00:28 +03004667 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004668 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4669 MGMT_STATUS_INVALID_PARAMS);
4670
4671 hci_dev_lock(hdev);
4672
4673 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004674 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4675 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004676 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004677 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4678 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004679
Johan Hedbergb97109792014-06-24 14:00:28 +03004680 if (cp->val == 0x02)
4681 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4682 &hdev->dev_flags);
4683 else
4684 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4685 &hdev->dev_flags);
4686
4687 if (hdev_is_powered(hdev) && use_changed &&
4688 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4689 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4690 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4691 sizeof(mode), &mode);
4692 }
4693
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004694 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4695 if (err < 0)
4696 goto unlock;
4697
4698 if (changed)
4699 err = new_settings(hdev, sk);
4700
4701unlock:
4702 hci_dev_unlock(hdev);
4703 return err;
4704}
4705
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004706static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4707 u16 len)
4708{
4709 struct mgmt_cp_set_privacy *cp = cp_data;
4710 bool changed;
4711 int err;
4712
4713 BT_DBG("request for %s", hdev->name);
4714
4715 if (!lmp_le_capable(hdev))
4716 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4717 MGMT_STATUS_NOT_SUPPORTED);
4718
4719 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4720 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4721 MGMT_STATUS_INVALID_PARAMS);
4722
4723 if (hdev_is_powered(hdev))
4724 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4725 MGMT_STATUS_REJECTED);
4726
4727 hci_dev_lock(hdev);
4728
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004729 /* If user space supports this command it is also expected to
4730 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4731 */
4732 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4733
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004734 if (cp->privacy) {
4735 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4736 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4737 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4738 } else {
4739 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4740 memset(hdev->irk, 0, sizeof(hdev->irk));
4741 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4742 }
4743
4744 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4745 if (err < 0)
4746 goto unlock;
4747
4748 if (changed)
4749 err = new_settings(hdev, sk);
4750
4751unlock:
4752 hci_dev_unlock(hdev);
4753 return err;
4754}
4755
Johan Hedberg41edf162014-02-18 10:19:35 +02004756static bool irk_is_valid(struct mgmt_irk_info *irk)
4757{
4758 switch (irk->addr.type) {
4759 case BDADDR_LE_PUBLIC:
4760 return true;
4761
4762 case BDADDR_LE_RANDOM:
4763 /* Two most significant bits shall be set */
4764 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4765 return false;
4766 return true;
4767 }
4768
4769 return false;
4770}
4771
4772static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4773 u16 len)
4774{
4775 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004776 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4777 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004778 u16 irk_count, expected_len;
4779 int i, err;
4780
4781 BT_DBG("request for %s", hdev->name);
4782
4783 if (!lmp_le_capable(hdev))
4784 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4785 MGMT_STATUS_NOT_SUPPORTED);
4786
4787 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004788 if (irk_count > max_irk_count) {
4789 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4790 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4791 MGMT_STATUS_INVALID_PARAMS);
4792 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004793
4794 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4795 if (expected_len != len) {
4796 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004797 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004798 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4799 MGMT_STATUS_INVALID_PARAMS);
4800 }
4801
4802 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4803
4804 for (i = 0; i < irk_count; i++) {
4805 struct mgmt_irk_info *key = &cp->irks[i];
4806
4807 if (!irk_is_valid(key))
4808 return cmd_status(sk, hdev->id,
4809 MGMT_OP_LOAD_IRKS,
4810 MGMT_STATUS_INVALID_PARAMS);
4811 }
4812
4813 hci_dev_lock(hdev);
4814
4815 hci_smp_irks_clear(hdev);
4816
4817 for (i = 0; i < irk_count; i++) {
4818 struct mgmt_irk_info *irk = &cp->irks[i];
4819 u8 addr_type;
4820
4821 if (irk->addr.type == BDADDR_LE_PUBLIC)
4822 addr_type = ADDR_LE_DEV_PUBLIC;
4823 else
4824 addr_type = ADDR_LE_DEV_RANDOM;
4825
4826 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4827 BDADDR_ANY);
4828 }
4829
4830 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4831
4832 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4833
4834 hci_dev_unlock(hdev);
4835
4836 return err;
4837}
4838
Johan Hedberg3f706b72013-01-20 14:27:16 +02004839static bool ltk_is_valid(struct mgmt_ltk_info *key)
4840{
4841 if (key->master != 0x00 && key->master != 0x01)
4842 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004843
4844 switch (key->addr.type) {
4845 case BDADDR_LE_PUBLIC:
4846 return true;
4847
4848 case BDADDR_LE_RANDOM:
4849 /* Two most significant bits shall be set */
4850 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4851 return false;
4852 return true;
4853 }
4854
4855 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004856}
4857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004858static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004859 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004860{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004861 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004862 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4863 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004864 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004865 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004866
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004867 BT_DBG("request for %s", hdev->name);
4868
4869 if (!lmp_le_capable(hdev))
4870 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4871 MGMT_STATUS_NOT_SUPPORTED);
4872
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004873 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004874 if (key_count > max_key_count) {
4875 BT_ERR("load_ltks: too big key_count value %u", key_count);
4876 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4877 MGMT_STATUS_INVALID_PARAMS);
4878 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004879
4880 expected_len = sizeof(*cp) + key_count *
4881 sizeof(struct mgmt_ltk_info);
4882 if (expected_len != len) {
4883 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004884 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004885 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004886 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004887 }
4888
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004889 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004890
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004891 for (i = 0; i < key_count; i++) {
4892 struct mgmt_ltk_info *key = &cp->keys[i];
4893
Johan Hedberg3f706b72013-01-20 14:27:16 +02004894 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004895 return cmd_status(sk, hdev->id,
4896 MGMT_OP_LOAD_LONG_TERM_KEYS,
4897 MGMT_STATUS_INVALID_PARAMS);
4898 }
4899
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004900 hci_dev_lock(hdev);
4901
4902 hci_smp_ltks_clear(hdev);
4903
4904 for (i = 0; i < key_count; i++) {
4905 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004906 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004907
4908 if (key->addr.type == BDADDR_LE_PUBLIC)
4909 addr_type = ADDR_LE_DEV_PUBLIC;
4910 else
4911 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004912
4913 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004914 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004915 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004916 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004917
Johan Hedberg61b43352014-05-29 19:36:53 +03004918 switch (key->type) {
4919 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004920 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004921 break;
4922 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004923 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004924 break;
4925 default:
4926 continue;
4927 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004928
Johan Hedberg35d70272014-02-19 14:57:47 +02004929 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004930 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004931 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004932 }
4933
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004934 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4935 NULL, 0);
4936
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004937 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004938
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004939 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004940}
4941
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004942struct cmd_conn_lookup {
4943 struct hci_conn *conn;
4944 bool valid_tx_power;
4945 u8 mgmt_status;
4946};
4947
4948static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4949{
4950 struct cmd_conn_lookup *match = data;
4951 struct mgmt_cp_get_conn_info *cp;
4952 struct mgmt_rp_get_conn_info rp;
4953 struct hci_conn *conn = cmd->user_data;
4954
4955 if (conn != match->conn)
4956 return;
4957
4958 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4959
4960 memset(&rp, 0, sizeof(rp));
4961 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4962 rp.addr.type = cp->addr.type;
4963
4964 if (!match->mgmt_status) {
4965 rp.rssi = conn->rssi;
4966
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004967 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004968 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004969 rp.max_tx_power = conn->max_tx_power;
4970 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004971 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004972 rp.max_tx_power = HCI_TX_POWER_INVALID;
4973 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004974 }
4975
4976 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4977 match->mgmt_status, &rp, sizeof(rp));
4978
4979 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03004980 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004981
4982 mgmt_pending_remove(cmd);
4983}
4984
4985static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4986{
4987 struct hci_cp_read_rssi *cp;
4988 struct hci_conn *conn;
4989 struct cmd_conn_lookup match;
4990 u16 handle;
4991
4992 BT_DBG("status 0x%02x", status);
4993
4994 hci_dev_lock(hdev);
4995
4996 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004997 * otherwise we assume it's not valid. At the moment we assume that
4998 * either both or none of current and max values are valid to keep code
4999 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005000 */
5001 match.valid_tx_power = !status;
5002
5003 /* Commands sent in request are either Read RSSI or Read Transmit Power
5004 * Level so we check which one was last sent to retrieve connection
5005 * handle. Both commands have handle as first parameter so it's safe to
5006 * cast data on the same command struct.
5007 *
5008 * First command sent is always Read RSSI and we fail only if it fails.
5009 * In other case we simply override error to indicate success as we
5010 * already remembered if TX power value is actually valid.
5011 */
5012 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5013 if (!cp) {
5014 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5015 status = 0;
5016 }
5017
5018 if (!cp) {
5019 BT_ERR("invalid sent_cmd in response");
5020 goto unlock;
5021 }
5022
5023 handle = __le16_to_cpu(cp->handle);
5024 conn = hci_conn_hash_lookup_handle(hdev, handle);
5025 if (!conn) {
5026 BT_ERR("unknown handle (%d) in response", handle);
5027 goto unlock;
5028 }
5029
5030 match.conn = conn;
5031 match.mgmt_status = mgmt_status(status);
5032
5033 /* Cache refresh is complete, now reply for mgmt request for given
5034 * connection only.
5035 */
5036 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5037 get_conn_info_complete, &match);
5038
5039unlock:
5040 hci_dev_unlock(hdev);
5041}
5042
5043static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5044 u16 len)
5045{
5046 struct mgmt_cp_get_conn_info *cp = data;
5047 struct mgmt_rp_get_conn_info rp;
5048 struct hci_conn *conn;
5049 unsigned long conn_info_age;
5050 int err = 0;
5051
5052 BT_DBG("%s", hdev->name);
5053
5054 memset(&rp, 0, sizeof(rp));
5055 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5056 rp.addr.type = cp->addr.type;
5057
5058 if (!bdaddr_type_is_valid(cp->addr.type))
5059 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5060 MGMT_STATUS_INVALID_PARAMS,
5061 &rp, sizeof(rp));
5062
5063 hci_dev_lock(hdev);
5064
5065 if (!hdev_is_powered(hdev)) {
5066 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5067 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5068 goto unlock;
5069 }
5070
5071 if (cp->addr.type == BDADDR_BREDR)
5072 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5073 &cp->addr.bdaddr);
5074 else
5075 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5076
5077 if (!conn || conn->state != BT_CONNECTED) {
5078 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5079 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5080 goto unlock;
5081 }
5082
5083 /* To avoid client trying to guess when to poll again for information we
5084 * calculate conn info age as random value between min/max set in hdev.
5085 */
5086 conn_info_age = hdev->conn_info_min_age +
5087 prandom_u32_max(hdev->conn_info_max_age -
5088 hdev->conn_info_min_age);
5089
5090 /* Query controller to refresh cached values if they are too old or were
5091 * never read.
5092 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005093 if (time_after(jiffies, conn->conn_info_timestamp +
5094 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005095 !conn->conn_info_timestamp) {
5096 struct hci_request req;
5097 struct hci_cp_read_tx_power req_txp_cp;
5098 struct hci_cp_read_rssi req_rssi_cp;
5099 struct pending_cmd *cmd;
5100
5101 hci_req_init(&req, hdev);
5102 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5103 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5104 &req_rssi_cp);
5105
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005106 /* For LE links TX power does not change thus we don't need to
5107 * query for it once value is known.
5108 */
5109 if (!bdaddr_type_is_le(cp->addr.type) ||
5110 conn->tx_power == HCI_TX_POWER_INVALID) {
5111 req_txp_cp.handle = cpu_to_le16(conn->handle);
5112 req_txp_cp.type = 0x00;
5113 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5114 sizeof(req_txp_cp), &req_txp_cp);
5115 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005116
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005117 /* Max TX power needs to be read only once per connection */
5118 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5119 req_txp_cp.handle = cpu_to_le16(conn->handle);
5120 req_txp_cp.type = 0x01;
5121 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5122 sizeof(req_txp_cp), &req_txp_cp);
5123 }
5124
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005125 err = hci_req_run(&req, conn_info_refresh_complete);
5126 if (err < 0)
5127 goto unlock;
5128
5129 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5130 data, len);
5131 if (!cmd) {
5132 err = -ENOMEM;
5133 goto unlock;
5134 }
5135
5136 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005137 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005138
5139 conn->conn_info_timestamp = jiffies;
5140 } else {
5141 /* Cache is valid, just reply with values cached in hci_conn */
5142 rp.rssi = conn->rssi;
5143 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005144 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005145
5146 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5147 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5148 }
5149
5150unlock:
5151 hci_dev_unlock(hdev);
5152 return err;
5153}
5154
Johan Hedberg95868422014-06-28 17:54:07 +03005155static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5156{
5157 struct mgmt_cp_get_clock_info *cp;
5158 struct mgmt_rp_get_clock_info rp;
5159 struct hci_cp_read_clock *hci_cp;
5160 struct pending_cmd *cmd;
5161 struct hci_conn *conn;
5162
5163 BT_DBG("%s status %u", hdev->name, status);
5164
5165 hci_dev_lock(hdev);
5166
5167 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5168 if (!hci_cp)
5169 goto unlock;
5170
5171 if (hci_cp->which) {
5172 u16 handle = __le16_to_cpu(hci_cp->handle);
5173 conn = hci_conn_hash_lookup_handle(hdev, handle);
5174 } else {
5175 conn = NULL;
5176 }
5177
5178 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5179 if (!cmd)
5180 goto unlock;
5181
5182 cp = cmd->param;
5183
5184 memset(&rp, 0, sizeof(rp));
5185 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5186
5187 if (status)
5188 goto send_rsp;
5189
5190 rp.local_clock = cpu_to_le32(hdev->clock);
5191
5192 if (conn) {
5193 rp.piconet_clock = cpu_to_le32(conn->clock);
5194 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5195 }
5196
5197send_rsp:
5198 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5199 &rp, sizeof(rp));
5200 mgmt_pending_remove(cmd);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005201 if (conn) {
Johan Hedberg95868422014-06-28 17:54:07 +03005202 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005203 hci_conn_put(conn);
5204 }
Johan Hedberg95868422014-06-28 17:54:07 +03005205
5206unlock:
5207 hci_dev_unlock(hdev);
5208}
5209
5210static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5211 u16 len)
5212{
5213 struct mgmt_cp_get_clock_info *cp = data;
5214 struct mgmt_rp_get_clock_info rp;
5215 struct hci_cp_read_clock hci_cp;
5216 struct pending_cmd *cmd;
5217 struct hci_request req;
5218 struct hci_conn *conn;
5219 int err;
5220
5221 BT_DBG("%s", hdev->name);
5222
5223 memset(&rp, 0, sizeof(rp));
5224 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5225 rp.addr.type = cp->addr.type;
5226
5227 if (cp->addr.type != BDADDR_BREDR)
5228 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5229 MGMT_STATUS_INVALID_PARAMS,
5230 &rp, sizeof(rp));
5231
5232 hci_dev_lock(hdev);
5233
5234 if (!hdev_is_powered(hdev)) {
5235 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5236 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5237 goto unlock;
5238 }
5239
5240 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5241 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5242 &cp->addr.bdaddr);
5243 if (!conn || conn->state != BT_CONNECTED) {
5244 err = cmd_complete(sk, hdev->id,
5245 MGMT_OP_GET_CLOCK_INFO,
5246 MGMT_STATUS_NOT_CONNECTED,
5247 &rp, sizeof(rp));
5248 goto unlock;
5249 }
5250 } else {
5251 conn = NULL;
5252 }
5253
5254 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5255 if (!cmd) {
5256 err = -ENOMEM;
5257 goto unlock;
5258 }
5259
5260 hci_req_init(&req, hdev);
5261
5262 memset(&hci_cp, 0, sizeof(hci_cp));
5263 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5264
5265 if (conn) {
5266 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005267 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005268
5269 hci_cp.handle = cpu_to_le16(conn->handle);
5270 hci_cp.which = 0x01; /* Piconet clock */
5271 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5272 }
5273
5274 err = hci_req_run(&req, get_clock_info_complete);
5275 if (err < 0)
5276 mgmt_pending_remove(cmd);
5277
5278unlock:
5279 hci_dev_unlock(hdev);
5280 return err;
5281}
5282
Marcel Holtmann8afef092014-06-29 22:28:34 +02005283static void device_added(struct sock *sk, struct hci_dev *hdev,
5284 bdaddr_t *bdaddr, u8 type, u8 action)
5285{
5286 struct mgmt_ev_device_added ev;
5287
5288 bacpy(&ev.addr.bdaddr, bdaddr);
5289 ev.addr.type = type;
5290 ev.action = action;
5291
5292 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5293}
5294
Marcel Holtmann2faade52014-06-29 19:44:03 +02005295static int add_device(struct sock *sk, struct hci_dev *hdev,
5296 void *data, u16 len)
5297{
5298 struct mgmt_cp_add_device *cp = data;
5299 u8 auto_conn, addr_type;
5300 int err;
5301
5302 BT_DBG("%s", hdev->name);
5303
Johan Hedberg66593582014-07-09 12:59:14 +03005304 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005305 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5306 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5307 MGMT_STATUS_INVALID_PARAMS,
5308 &cp->addr, sizeof(cp->addr));
5309
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005310 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005311 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5312 MGMT_STATUS_INVALID_PARAMS,
5313 &cp->addr, sizeof(cp->addr));
5314
5315 hci_dev_lock(hdev);
5316
Johan Hedberg66593582014-07-09 12:59:14 +03005317 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005318 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005319 if (cp->action != 0x01) {
5320 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5321 MGMT_STATUS_INVALID_PARAMS,
5322 &cp->addr, sizeof(cp->addr));
5323 goto unlock;
5324 }
5325
5326 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5327 cp->addr.type);
5328 if (err)
5329 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005330
Johan Hedberg432df052014-08-01 11:13:31 +03005331 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005332
Johan Hedberg66593582014-07-09 12:59:14 +03005333 goto added;
5334 }
5335
Marcel Holtmann2faade52014-06-29 19:44:03 +02005336 if (cp->addr.type == BDADDR_LE_PUBLIC)
5337 addr_type = ADDR_LE_DEV_PUBLIC;
5338 else
5339 addr_type = ADDR_LE_DEV_RANDOM;
5340
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005341 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005342 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005343 else if (cp->action == 0x01)
5344 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005345 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005346 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005347
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005348 /* If the connection parameters don't exist for this device,
5349 * they will be created and configured with defaults.
5350 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005351 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5352 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005353 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5354 MGMT_STATUS_FAILED,
5355 &cp->addr, sizeof(cp->addr));
5356 goto unlock;
5357 }
5358
Johan Hedberg66593582014-07-09 12:59:14 +03005359added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005360 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5361
Marcel Holtmann2faade52014-06-29 19:44:03 +02005362 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5363 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5364
5365unlock:
5366 hci_dev_unlock(hdev);
5367 return err;
5368}
5369
Marcel Holtmann8afef092014-06-29 22:28:34 +02005370static void device_removed(struct sock *sk, struct hci_dev *hdev,
5371 bdaddr_t *bdaddr, u8 type)
5372{
5373 struct mgmt_ev_device_removed ev;
5374
5375 bacpy(&ev.addr.bdaddr, bdaddr);
5376 ev.addr.type = type;
5377
5378 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5379}
5380
Marcel Holtmann2faade52014-06-29 19:44:03 +02005381static int remove_device(struct sock *sk, struct hci_dev *hdev,
5382 void *data, u16 len)
5383{
5384 struct mgmt_cp_remove_device *cp = data;
5385 int err;
5386
5387 BT_DBG("%s", hdev->name);
5388
5389 hci_dev_lock(hdev);
5390
5391 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005392 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005393 u8 addr_type;
5394
Johan Hedberg66593582014-07-09 12:59:14 +03005395 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005396 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5397 MGMT_STATUS_INVALID_PARAMS,
5398 &cp->addr, sizeof(cp->addr));
5399 goto unlock;
5400 }
5401
Johan Hedberg66593582014-07-09 12:59:14 +03005402 if (cp->addr.type == BDADDR_BREDR) {
5403 err = hci_bdaddr_list_del(&hdev->whitelist,
5404 &cp->addr.bdaddr,
5405 cp->addr.type);
5406 if (err) {
5407 err = cmd_complete(sk, hdev->id,
5408 MGMT_OP_REMOVE_DEVICE,
5409 MGMT_STATUS_INVALID_PARAMS,
5410 &cp->addr, sizeof(cp->addr));
5411 goto unlock;
5412 }
5413
Johan Hedberg432df052014-08-01 11:13:31 +03005414 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005415
Johan Hedberg66593582014-07-09 12:59:14 +03005416 device_removed(sk, hdev, &cp->addr.bdaddr,
5417 cp->addr.type);
5418 goto complete;
5419 }
5420
Marcel Holtmann2faade52014-06-29 19:44:03 +02005421 if (cp->addr.type == BDADDR_LE_PUBLIC)
5422 addr_type = ADDR_LE_DEV_PUBLIC;
5423 else
5424 addr_type = ADDR_LE_DEV_RANDOM;
5425
Johan Hedbergc71593d2014-07-02 17:37:28 +03005426 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5427 addr_type);
5428 if (!params) {
5429 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5430 MGMT_STATUS_INVALID_PARAMS,
5431 &cp->addr, sizeof(cp->addr));
5432 goto unlock;
5433 }
5434
5435 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5436 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5437 MGMT_STATUS_INVALID_PARAMS,
5438 &cp->addr, sizeof(cp->addr));
5439 goto unlock;
5440 }
5441
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005442 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005443 list_del(&params->list);
5444 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005445 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005446
5447 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005448 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005449 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005450 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005451
Marcel Holtmann2faade52014-06-29 19:44:03 +02005452 if (cp->addr.type) {
5453 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5454 MGMT_STATUS_INVALID_PARAMS,
5455 &cp->addr, sizeof(cp->addr));
5456 goto unlock;
5457 }
5458
Johan Hedberg66593582014-07-09 12:59:14 +03005459 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5460 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5461 list_del(&b->list);
5462 kfree(b);
5463 }
5464
Johan Hedberg432df052014-08-01 11:13:31 +03005465 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005466
Johan Hedberg19de0822014-07-06 13:06:51 +03005467 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5468 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5469 continue;
5470 device_removed(sk, hdev, &p->addr, p->addr_type);
5471 list_del(&p->action);
5472 list_del(&p->list);
5473 kfree(p);
5474 }
5475
5476 BT_DBG("All LE connection parameters were removed");
5477
5478 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005479 }
5480
Johan Hedberg66593582014-07-09 12:59:14 +03005481complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005482 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5483 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5484
5485unlock:
5486 hci_dev_unlock(hdev);
5487 return err;
5488}
5489
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005490static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5491 u16 len)
5492{
5493 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005494 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5495 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005496 u16 param_count, expected_len;
5497 int i;
5498
5499 if (!lmp_le_capable(hdev))
5500 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5501 MGMT_STATUS_NOT_SUPPORTED);
5502
5503 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005504 if (param_count > max_param_count) {
5505 BT_ERR("load_conn_param: too big param_count value %u",
5506 param_count);
5507 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5508 MGMT_STATUS_INVALID_PARAMS);
5509 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005510
5511 expected_len = sizeof(*cp) + param_count *
5512 sizeof(struct mgmt_conn_param);
5513 if (expected_len != len) {
5514 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5515 expected_len, len);
5516 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5517 MGMT_STATUS_INVALID_PARAMS);
5518 }
5519
5520 BT_DBG("%s param_count %u", hdev->name, param_count);
5521
5522 hci_dev_lock(hdev);
5523
5524 hci_conn_params_clear_disabled(hdev);
5525
5526 for (i = 0; i < param_count; i++) {
5527 struct mgmt_conn_param *param = &cp->params[i];
5528 struct hci_conn_params *hci_param;
5529 u16 min, max, latency, timeout;
5530 u8 addr_type;
5531
5532 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5533 param->addr.type);
5534
5535 if (param->addr.type == BDADDR_LE_PUBLIC) {
5536 addr_type = ADDR_LE_DEV_PUBLIC;
5537 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5538 addr_type = ADDR_LE_DEV_RANDOM;
5539 } else {
5540 BT_ERR("Ignoring invalid connection parameters");
5541 continue;
5542 }
5543
5544 min = le16_to_cpu(param->min_interval);
5545 max = le16_to_cpu(param->max_interval);
5546 latency = le16_to_cpu(param->latency);
5547 timeout = le16_to_cpu(param->timeout);
5548
5549 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5550 min, max, latency, timeout);
5551
5552 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5553 BT_ERR("Ignoring invalid connection parameters");
5554 continue;
5555 }
5556
5557 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5558 addr_type);
5559 if (!hci_param) {
5560 BT_ERR("Failed to add connection parameters");
5561 continue;
5562 }
5563
5564 hci_param->conn_min_interval = min;
5565 hci_param->conn_max_interval = max;
5566 hci_param->conn_latency = latency;
5567 hci_param->supervision_timeout = timeout;
5568 }
5569
5570 hci_dev_unlock(hdev);
5571
5572 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5573}
5574
Marcel Holtmanndbece372014-07-04 18:11:55 +02005575static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5576 void *data, u16 len)
5577{
5578 struct mgmt_cp_set_external_config *cp = data;
5579 bool changed;
5580 int err;
5581
5582 BT_DBG("%s", hdev->name);
5583
5584 if (hdev_is_powered(hdev))
5585 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5586 MGMT_STATUS_REJECTED);
5587
5588 if (cp->config != 0x00 && cp->config != 0x01)
5589 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5590 MGMT_STATUS_INVALID_PARAMS);
5591
5592 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5593 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5594 MGMT_STATUS_NOT_SUPPORTED);
5595
5596 hci_dev_lock(hdev);
5597
5598 if (cp->config)
5599 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5600 &hdev->dev_flags);
5601 else
5602 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5603 &hdev->dev_flags);
5604
5605 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5606 if (err < 0)
5607 goto unlock;
5608
5609 if (!changed)
5610 goto unlock;
5611
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005612 err = new_options(hdev, sk);
5613
Marcel Holtmanndbece372014-07-04 18:11:55 +02005614 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5615 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005616
5617 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5618 set_bit(HCI_CONFIG, &hdev->dev_flags);
5619 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5620
5621 queue_work(hdev->req_workqueue, &hdev->power_on);
5622 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005623 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005624 mgmt_index_added(hdev);
5625 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005626 }
5627
5628unlock:
5629 hci_dev_unlock(hdev);
5630 return err;
5631}
5632
Marcel Holtmann9713c172014-07-06 12:11:15 +02005633static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5634 void *data, u16 len)
5635{
5636 struct mgmt_cp_set_public_address *cp = data;
5637 bool changed;
5638 int err;
5639
5640 BT_DBG("%s", hdev->name);
5641
5642 if (hdev_is_powered(hdev))
5643 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5644 MGMT_STATUS_REJECTED);
5645
5646 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5647 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5648 MGMT_STATUS_INVALID_PARAMS);
5649
5650 if (!hdev->set_bdaddr)
5651 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5652 MGMT_STATUS_NOT_SUPPORTED);
5653
5654 hci_dev_lock(hdev);
5655
5656 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5657 bacpy(&hdev->public_addr, &cp->bdaddr);
5658
5659 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5660 if (err < 0)
5661 goto unlock;
5662
5663 if (!changed)
5664 goto unlock;
5665
5666 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5667 err = new_options(hdev, sk);
5668
5669 if (is_configured(hdev)) {
5670 mgmt_index_removed(hdev);
5671
5672 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5673
5674 set_bit(HCI_CONFIG, &hdev->dev_flags);
5675 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5676
5677 queue_work(hdev->req_workqueue, &hdev->power_on);
5678 }
5679
5680unlock:
5681 hci_dev_unlock(hdev);
5682 return err;
5683}
5684
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005685static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005686 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5687 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005688 bool var_len;
5689 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005690} mgmt_handlers[] = {
5691 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005692 { read_version, false, MGMT_READ_VERSION_SIZE },
5693 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5694 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5695 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5696 { set_powered, false, MGMT_SETTING_SIZE },
5697 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5698 { set_connectable, false, MGMT_SETTING_SIZE },
5699 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005700 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005701 { set_link_security, false, MGMT_SETTING_SIZE },
5702 { set_ssp, false, MGMT_SETTING_SIZE },
5703 { set_hs, false, MGMT_SETTING_SIZE },
5704 { set_le, false, MGMT_SETTING_SIZE },
5705 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5706 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5707 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5708 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5709 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5710 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5711 { disconnect, false, MGMT_DISCONNECT_SIZE },
5712 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5713 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5714 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5715 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5716 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5717 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5718 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5719 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5720 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5721 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5722 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5723 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005724 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005725 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5726 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5727 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5728 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5729 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5730 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005731 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005732 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005733 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005734 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005735 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005736 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005737 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005738 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005739 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005740 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005741 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005742 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5743 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005744 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5745 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005746 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005747 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005748 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005749};
5750
Johan Hedberg03811012010-12-08 00:21:06 +02005751int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5752{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005753 void *buf;
5754 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005755 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005756 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005757 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005758 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005759 int err;
5760
5761 BT_DBG("got %zu bytes", msglen);
5762
5763 if (msglen < sizeof(*hdr))
5764 return -EINVAL;
5765
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005766 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005767 if (!buf)
5768 return -ENOMEM;
5769
Al Viro6ce8e9c2014-04-06 21:25:44 -04005770 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02005771 err = -EFAULT;
5772 goto done;
5773 }
5774
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005775 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005776 opcode = __le16_to_cpu(hdr->opcode);
5777 index = __le16_to_cpu(hdr->index);
5778 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005779
5780 if (len != msglen - sizeof(*hdr)) {
5781 err = -EINVAL;
5782 goto done;
5783 }
5784
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005785 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005786 hdev = hci_dev_get(index);
5787 if (!hdev) {
5788 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005789 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005790 goto done;
5791 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005792
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005793 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005794 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005795 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005796 err = cmd_status(sk, index, opcode,
5797 MGMT_STATUS_INVALID_INDEX);
5798 goto done;
5799 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005800
5801 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005802 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005803 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5804 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005805 err = cmd_status(sk, index, opcode,
5806 MGMT_STATUS_INVALID_INDEX);
5807 goto done;
5808 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005809 }
5810
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005811 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005812 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005813 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005814 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005815 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005816 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005817 }
5818
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005819 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5820 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5821 err = cmd_status(sk, index, opcode,
5822 MGMT_STATUS_INVALID_INDEX);
5823 goto done;
5824 }
5825
5826 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5827 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005828 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005829 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005830 goto done;
5831 }
5832
Johan Hedbergbe22b542012-03-01 22:24:41 +02005833 handler = &mgmt_handlers[opcode];
5834
5835 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005836 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005837 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005838 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005839 goto done;
5840 }
5841
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005842 if (hdev)
5843 mgmt_init_hdev(sk, hdev);
5844
5845 cp = buf + sizeof(*hdr);
5846
Johan Hedbergbe22b542012-03-01 22:24:41 +02005847 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005848 if (err < 0)
5849 goto done;
5850
Johan Hedberg03811012010-12-08 00:21:06 +02005851 err = msglen;
5852
5853done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005854 if (hdev)
5855 hci_dev_put(hdev);
5856
Johan Hedberg03811012010-12-08 00:21:06 +02005857 kfree(buf);
5858 return err;
5859}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005860
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005861void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005862{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005863 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005864 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005865
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005866 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5867 return;
5868
5869 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5870 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5871 else
5872 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005873}
5874
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005875void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005876{
Johan Hedberg5f159032012-03-02 03:13:19 +02005877 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005878
Marcel Holtmann1514b892013-10-06 08:25:01 -07005879 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005880 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005881
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005882 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5883 return;
5884
Johan Hedberg744cf192011-11-08 20:40:14 +02005885 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005886
Marcel Holtmannedd38962014-07-02 21:30:55 +02005887 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5888 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5889 else
5890 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005891}
5892
Andre Guedes6046dc32014-02-26 20:21:51 -03005893/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005894static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005895{
5896 struct hci_conn_params *p;
5897
5898 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005899 /* Needed for AUTO_OFF case where might not "really"
5900 * have been powered off.
5901 */
5902 list_del_init(&p->action);
5903
5904 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005905 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03005906 case HCI_AUTO_CONN_ALWAYS:
5907 list_add(&p->action, &hdev->pend_le_conns);
5908 break;
5909 case HCI_AUTO_CONN_REPORT:
5910 list_add(&p->action, &hdev->pend_le_reports);
5911 break;
5912 default:
5913 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005914 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005915 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005916
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005917 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005918}
5919
Johan Hedberg229ab392013-03-15 17:06:53 -05005920static void powered_complete(struct hci_dev *hdev, u8 status)
5921{
5922 struct cmd_lookup match = { NULL, hdev };
5923
5924 BT_DBG("status 0x%02x", status);
5925
5926 hci_dev_lock(hdev);
5927
Johan Hedbergd7347f32014-07-04 12:37:23 +03005928 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005929
Johan Hedberg229ab392013-03-15 17:06:53 -05005930 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5931
5932 new_settings(hdev, match.sk);
5933
5934 hci_dev_unlock(hdev);
5935
5936 if (match.sk)
5937 sock_put(match.sk);
5938}
5939
Johan Hedberg70da6242013-03-15 17:06:51 -05005940static int powered_update_hci(struct hci_dev *hdev)
5941{
Johan Hedberg890ea892013-03-15 17:06:52 -05005942 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005943 u8 link_sec;
5944
Johan Hedberg890ea892013-03-15 17:06:52 -05005945 hci_req_init(&req, hdev);
5946
Johan Hedberg70da6242013-03-15 17:06:51 -05005947 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5948 !lmp_host_ssp_capable(hdev)) {
5949 u8 ssp = 1;
5950
Johan Hedberg890ea892013-03-15 17:06:52 -05005951 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005952 }
5953
Johan Hedbergc73eee92013-04-19 18:35:21 +03005954 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5955 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005956 struct hci_cp_write_le_host_supported cp;
5957
Marcel Holtmann32226e42014-07-24 20:04:16 +02005958 cp.le = 0x01;
5959 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05005960
5961 /* Check first if we already have the right
5962 * host state (host features set)
5963 */
5964 if (cp.le != lmp_host_le_capable(hdev) ||
5965 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005966 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5967 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005968 }
5969
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005970 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005971 /* Make sure the controller has a good default for
5972 * advertising data. This also applies to the case
5973 * where BR/EDR was toggled during the AUTO_OFF phase.
5974 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005975 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005976 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005977 update_scan_rsp_data(&req);
5978 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005979
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005980 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5981 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005982 }
5983
Johan Hedberg70da6242013-03-15 17:06:51 -05005984 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5985 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005986 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5987 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005988
5989 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03005990 write_fast_connectable(&req, false);
5991 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005992 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005993 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005994 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005995 }
5996
Johan Hedberg229ab392013-03-15 17:06:53 -05005997 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005998}
5999
Johan Hedberg744cf192011-11-08 20:40:14 +02006000int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006001{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006002 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006003 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6004 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006005 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006006
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006007 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6008 return 0;
6009
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006010 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006011 if (powered_update_hci(hdev) == 0)
6012 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006013
Johan Hedberg229ab392013-03-15 17:06:53 -05006014 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6015 &match);
6016 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006017 }
6018
Johan Hedberg229ab392013-03-15 17:06:53 -05006019 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6020 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
6021
6022 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6023 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6024 zero_cod, sizeof(zero_cod), NULL);
6025
6026new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006027 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006028
6029 if (match.sk)
6030 sock_put(match.sk);
6031
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006032 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006033}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006034
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006035void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006036{
6037 struct pending_cmd *cmd;
6038 u8 status;
6039
6040 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6041 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006042 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006043
6044 if (err == -ERFKILL)
6045 status = MGMT_STATUS_RFKILLED;
6046 else
6047 status = MGMT_STATUS_FAILED;
6048
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006049 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006050
6051 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006052}
6053
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006054void mgmt_discoverable_timeout(struct hci_dev *hdev)
6055{
6056 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006057
6058 hci_dev_lock(hdev);
6059
6060 /* When discoverable timeout triggers, then just make sure
6061 * the limited discoverable flag is cleared. Even in the case
6062 * of a timeout triggered from general discoverable, it is
6063 * safe to unconditionally clear the flag.
6064 */
6065 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006066 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006067
6068 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006069 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6070 u8 scan = SCAN_PAGE;
6071 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6072 sizeof(scan), &scan);
6073 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006074 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006075 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006076 hci_req_run(&req, NULL);
6077
6078 hdev->discov_timeout = 0;
6079
Johan Hedberg9a43e252013-10-20 19:00:07 +03006080 new_settings(hdev, NULL);
6081
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006082 hci_dev_unlock(hdev);
6083}
6084
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006085void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6086 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006087{
Johan Hedberg86742e12011-11-07 23:13:38 +02006088 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006089
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006090 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006091
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006092 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006093 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006094 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006095 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006096 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006097 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006098
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006099 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006100}
Johan Hedbergf7520542011-01-20 12:34:39 +02006101
Johan Hedbergd7b25452014-05-23 13:19:53 +03006102static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6103{
6104 if (ltk->authenticated)
6105 return MGMT_LTK_AUTHENTICATED;
6106
6107 return MGMT_LTK_UNAUTHENTICATED;
6108}
6109
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006110void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006111{
6112 struct mgmt_ev_new_long_term_key ev;
6113
6114 memset(&ev, 0, sizeof(ev));
6115
Marcel Holtmann5192d302014-02-19 17:11:58 -08006116 /* Devices using resolvable or non-resolvable random addresses
6117 * without providing an indentity resolving key don't require
6118 * to store long term keys. Their addresses will change the
6119 * next time around.
6120 *
6121 * Only when a remote device provides an identity address
6122 * make sure the long term key is stored. If the remote
6123 * identity is known, the long term keys are internally
6124 * mapped to the identity address. So allow static random
6125 * and public addresses here.
6126 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006127 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6128 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6129 ev.store_hint = 0x00;
6130 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006131 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006132
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006133 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006134 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006135 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006136 ev.key.enc_size = key->enc_size;
6137 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006138 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006139
Johan Hedberg2ceba532014-06-16 19:25:16 +03006140 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006141 ev.key.master = 1;
6142
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006143 memcpy(ev.key.val, key->val, sizeof(key->val));
6144
Marcel Holtmann083368f2013-10-15 14:26:29 -07006145 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006146}
6147
Johan Hedberg95fbac82014-02-19 15:18:31 +02006148void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6149{
6150 struct mgmt_ev_new_irk ev;
6151
6152 memset(&ev, 0, sizeof(ev));
6153
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006154 /* For identity resolving keys from devices that are already
6155 * using a public address or static random address, do not
6156 * ask for storing this key. The identity resolving key really
6157 * is only mandatory for devices using resovlable random
6158 * addresses.
6159 *
6160 * Storing all identity resolving keys has the downside that
6161 * they will be also loaded on next boot of they system. More
6162 * identity resolving keys, means more time during scanning is
6163 * needed to actually resolve these addresses.
6164 */
6165 if (bacmp(&irk->rpa, BDADDR_ANY))
6166 ev.store_hint = 0x01;
6167 else
6168 ev.store_hint = 0x00;
6169
Johan Hedberg95fbac82014-02-19 15:18:31 +02006170 bacpy(&ev.rpa, &irk->rpa);
6171 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6172 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6173 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6174
6175 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6176}
6177
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006178void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6179 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006180{
6181 struct mgmt_ev_new_csrk ev;
6182
6183 memset(&ev, 0, sizeof(ev));
6184
6185 /* Devices using resolvable or non-resolvable random addresses
6186 * without providing an indentity resolving key don't require
6187 * to store signature resolving keys. Their addresses will change
6188 * the next time around.
6189 *
6190 * Only when a remote device provides an identity address
6191 * make sure the signature resolving key is stored. So allow
6192 * static random and public addresses here.
6193 */
6194 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6195 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6196 ev.store_hint = 0x00;
6197 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006198 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006199
6200 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6201 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6202 ev.key.master = csrk->master;
6203 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6204
6205 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6206}
6207
Andre Guedesffb5a8272014-07-01 18:10:11 -03006208void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006209 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6210 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006211{
6212 struct mgmt_ev_new_conn_param ev;
6213
Johan Hedbergc103aea2014-07-02 17:37:34 +03006214 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6215 return;
6216
Andre Guedesffb5a8272014-07-01 18:10:11 -03006217 memset(&ev, 0, sizeof(ev));
6218 bacpy(&ev.addr.bdaddr, bdaddr);
6219 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006220 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006221 ev.min_interval = cpu_to_le16(min_interval);
6222 ev.max_interval = cpu_to_le16(max_interval);
6223 ev.latency = cpu_to_le16(latency);
6224 ev.timeout = cpu_to_le16(timeout);
6225
6226 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6227}
6228
Marcel Holtmann94933992013-10-15 10:26:39 -07006229static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6230 u8 data_len)
6231{
6232 eir[eir_len++] = sizeof(type) + data_len;
6233 eir[eir_len++] = type;
6234 memcpy(&eir[eir_len], data, data_len);
6235 eir_len += data_len;
6236
6237 return eir_len;
6238}
6239
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006240void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6241 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006242{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006243 char buf[512];
6244 struct mgmt_ev_device_connected *ev = (void *) buf;
6245 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006246
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006247 bacpy(&ev->addr.bdaddr, &conn->dst);
6248 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006249
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006250 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006251
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006252 /* We must ensure that the EIR Data fields are ordered and
6253 * unique. Keep it simple for now and avoid the problem by not
6254 * adding any BR/EDR data to the LE adv.
6255 */
6256 if (conn->le_adv_data_len > 0) {
6257 memcpy(&ev->eir[eir_len],
6258 conn->le_adv_data, conn->le_adv_data_len);
6259 eir_len = conn->le_adv_data_len;
6260 } else {
6261 if (name_len > 0)
6262 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6263 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006264
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006265 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006266 eir_len = eir_append_data(ev->eir, eir_len,
6267 EIR_CLASS_OF_DEV,
6268 conn->dev_class, 3);
6269 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006270
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006271 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006272
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006273 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6274 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006275}
6276
Johan Hedberg8962ee72011-01-20 12:40:27 +02006277static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6278{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006279 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006280 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006281 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006282
Johan Hedberg88c3df12012-02-09 14:27:38 +02006283 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6284 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006285
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006286 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006287 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006288
6289 *sk = cmd->sk;
6290 sock_hold(*sk);
6291
Johan Hedberga664b5b2011-02-19 12:06:02 -03006292 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006293}
6294
Johan Hedberg124f6e32012-02-09 13:50:12 +02006295static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006296{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006297 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006298 struct mgmt_cp_unpair_device *cp = cmd->param;
6299 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006300
6301 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006302 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6303 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006304
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006305 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6306
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006307 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006308
6309 mgmt_pending_remove(cmd);
6310}
6311
Johan Hedberg84c61d92014-08-01 11:13:30 +03006312bool mgmt_powering_down(struct hci_dev *hdev)
6313{
6314 struct pending_cmd *cmd;
6315 struct mgmt_mode *cp;
6316
6317 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6318 if (!cmd)
6319 return false;
6320
6321 cp = cmd->param;
6322 if (!cp->val)
6323 return true;
6324
6325 return false;
6326}
6327
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006328void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006329 u8 link_type, u8 addr_type, u8 reason,
6330 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006331{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006332 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006333 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006334
Johan Hedberg84c61d92014-08-01 11:13:30 +03006335 /* The connection is still in hci_conn_hash so test for 1
6336 * instead of 0 to know if this is the last one.
6337 */
6338 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6339 cancel_delayed_work(&hdev->power_off);
6340 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006341 }
6342
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006343 if (!mgmt_connected)
6344 return;
6345
Andre Guedes57eb7762013-10-30 19:01:41 -03006346 if (link_type != ACL_LINK && link_type != LE_LINK)
6347 return;
6348
Johan Hedberg744cf192011-11-08 20:40:14 +02006349 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006350
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006351 bacpy(&ev.addr.bdaddr, bdaddr);
6352 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6353 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006354
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006355 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006356
6357 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006358 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006359
Johan Hedberg124f6e32012-02-09 13:50:12 +02006360 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006361 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006362}
6363
Marcel Holtmann78929242013-10-06 23:55:47 -07006364void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6365 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006366{
Andre Guedes3655bba2013-10-30 19:01:40 -03006367 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6368 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006369 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006370 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006371
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006372 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6373 hdev);
6374
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006375 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006376 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006377 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006378
Andre Guedes3655bba2013-10-30 19:01:40 -03006379 cp = cmd->param;
6380
6381 if (bacmp(bdaddr, &cp->addr.bdaddr))
6382 return;
6383
6384 if (cp->addr.type != bdaddr_type)
6385 return;
6386
Johan Hedberg88c3df12012-02-09 14:27:38 +02006387 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006388 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006389
Marcel Holtmann78929242013-10-06 23:55:47 -07006390 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6391 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006392
Johan Hedberga664b5b2011-02-19 12:06:02 -03006393 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006394}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006395
Marcel Holtmann445608d2013-10-06 23:55:48 -07006396void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6397 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006398{
6399 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006400
Johan Hedberg84c61d92014-08-01 11:13:30 +03006401 /* The connection is still in hci_conn_hash so test for 1
6402 * instead of 0 to know if this is the last one.
6403 */
6404 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6405 cancel_delayed_work(&hdev->power_off);
6406 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006407 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006408
Johan Hedberg4c659c32011-11-07 23:13:39 +02006409 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006410 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006411 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006412
Marcel Holtmann445608d2013-10-06 23:55:48 -07006413 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006414}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006415
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006416void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006417{
6418 struct mgmt_ev_pin_code_request ev;
6419
Johan Hedbergd8457692012-02-17 14:24:57 +02006420 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006421 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006422 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006423
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006424 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006425}
6426
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006427void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6428 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006429{
6430 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006431 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006432
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006433 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006434 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006435 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006436
Johan Hedbergd8457692012-02-17 14:24:57 +02006437 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006438 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006439
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006440 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6441 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006442
Johan Hedberga664b5b2011-02-19 12:06:02 -03006443 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006444}
6445
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006446void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6447 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006448{
6449 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006450 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006451
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006452 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006453 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006454 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006455
Johan Hedbergd8457692012-02-17 14:24:57 +02006456 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006457 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006458
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006459 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6460 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006461
Johan Hedberga664b5b2011-02-19 12:06:02 -03006462 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006463}
Johan Hedberga5c29682011-02-19 12:05:57 -03006464
Johan Hedberg744cf192011-11-08 20:40:14 +02006465int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006466 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006467 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006468{
6469 struct mgmt_ev_user_confirm_request ev;
6470
Johan Hedberg744cf192011-11-08 20:40:14 +02006471 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006472
Johan Hedberg272d90d2012-02-09 15:26:12 +02006473 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006474 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006475 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006476 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006477
Johan Hedberg744cf192011-11-08 20:40:14 +02006478 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006479 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006480}
6481
Johan Hedberg272d90d2012-02-09 15:26:12 +02006482int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006483 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006484{
6485 struct mgmt_ev_user_passkey_request ev;
6486
6487 BT_DBG("%s", hdev->name);
6488
Johan Hedberg272d90d2012-02-09 15:26:12 +02006489 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006490 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006491
6492 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006493 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006494}
6495
Brian Gix0df4c182011-11-16 13:53:13 -08006496static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006497 u8 link_type, u8 addr_type, u8 status,
6498 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006499{
6500 struct pending_cmd *cmd;
6501 struct mgmt_rp_user_confirm_reply rp;
6502 int err;
6503
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006504 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006505 if (!cmd)
6506 return -ENOENT;
6507
Johan Hedberg272d90d2012-02-09 15:26:12 +02006508 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006509 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006510 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006511 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006512
Johan Hedberga664b5b2011-02-19 12:06:02 -03006513 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006514
6515 return err;
6516}
6517
Johan Hedberg744cf192011-11-08 20:40:14 +02006518int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006519 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006520{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006521 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006522 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006523}
6524
Johan Hedberg272d90d2012-02-09 15:26:12 +02006525int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006526 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006527{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006528 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006529 status,
6530 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006531}
Johan Hedberg2a611692011-02-19 12:06:00 -03006532
Brian Gix604086b2011-11-23 08:28:33 -08006533int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006534 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006535{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006536 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006537 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006538}
6539
Johan Hedberg272d90d2012-02-09 15:26:12 +02006540int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006541 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006542{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006543 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006544 status,
6545 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006546}
6547
Johan Hedberg92a25252012-09-06 18:39:26 +03006548int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6549 u8 link_type, u8 addr_type, u32 passkey,
6550 u8 entered)
6551{
6552 struct mgmt_ev_passkey_notify ev;
6553
6554 BT_DBG("%s", hdev->name);
6555
6556 bacpy(&ev.addr.bdaddr, bdaddr);
6557 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6558 ev.passkey = __cpu_to_le32(passkey);
6559 ev.entered = entered;
6560
6561 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6562}
6563
Johan Hedberge1e930f2014-09-08 17:09:49 -07006564void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006565{
6566 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006567 struct pending_cmd *cmd;
6568 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006569
Johan Hedberge1e930f2014-09-08 17:09:49 -07006570 bacpy(&ev.addr.bdaddr, &conn->dst);
6571 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6572 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006573
Johan Hedberge1e930f2014-09-08 17:09:49 -07006574 cmd = find_pairing(conn);
6575
6576 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6577 cmd ? cmd->sk : NULL);
6578
6579 if (cmd)
6580 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006581}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006582
Marcel Holtmann464996a2013-10-15 14:26:24 -07006583void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006584{
6585 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006586 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006587
6588 if (status) {
6589 u8 mgmt_err = mgmt_status(status);
6590 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006591 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006592 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006593 }
6594
Marcel Holtmann464996a2013-10-15 14:26:24 -07006595 if (test_bit(HCI_AUTH, &hdev->flags))
6596 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6597 &hdev->dev_flags);
6598 else
6599 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6600 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006601
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006602 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006603 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006604
Johan Hedberg47990ea2012-02-22 11:58:37 +02006605 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006606 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006607
6608 if (match.sk)
6609 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006610}
6611
Johan Hedberg890ea892013-03-15 17:06:52 -05006612static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006613{
Johan Hedberg890ea892013-03-15 17:06:52 -05006614 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006615 struct hci_cp_write_eir cp;
6616
Johan Hedberg976eb202012-10-24 21:12:01 +03006617 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006618 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006619
Johan Hedbergc80da272012-02-22 15:38:48 +02006620 memset(hdev->eir, 0, sizeof(hdev->eir));
6621
Johan Hedbergcacaf522012-02-21 00:52:42 +02006622 memset(&cp, 0, sizeof(cp));
6623
Johan Hedberg890ea892013-03-15 17:06:52 -05006624 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006625}
6626
Marcel Holtmann3e248562013-10-15 14:26:25 -07006627void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006628{
6629 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006630 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006631 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006632
6633 if (status) {
6634 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006635
6636 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006637 &hdev->dev_flags)) {
6638 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006639 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006640 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006641
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006642 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6643 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006644 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006645 }
6646
6647 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006648 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006649 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006650 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6651 if (!changed)
6652 changed = test_and_clear_bit(HCI_HS_ENABLED,
6653 &hdev->dev_flags);
6654 else
6655 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006656 }
6657
6658 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6659
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006660 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006661 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006662
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006663 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006664 sock_put(match.sk);
6665
Johan Hedberg890ea892013-03-15 17:06:52 -05006666 hci_req_init(&req, hdev);
6667
Johan Hedberg37699722014-06-24 14:00:27 +03006668 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6669 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6670 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6671 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006672 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006673 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006674 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006675 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006676
6677 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006678}
6679
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006680void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6681{
6682 struct cmd_lookup match = { NULL, hdev };
6683 bool changed = false;
6684
6685 if (status) {
6686 u8 mgmt_err = mgmt_status(status);
6687
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006688 if (enable) {
6689 if (test_and_clear_bit(HCI_SC_ENABLED,
6690 &hdev->dev_flags))
6691 new_settings(hdev, NULL);
6692 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6693 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006694
6695 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6696 cmd_status_rsp, &mgmt_err);
6697 return;
6698 }
6699
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006700 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006701 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006702 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006703 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006704 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6705 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006706
6707 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6708 settings_rsp, &match);
6709
6710 if (changed)
6711 new_settings(hdev, match.sk);
6712
6713 if (match.sk)
6714 sock_put(match.sk);
6715}
6716
Johan Hedberg92da6092013-03-15 17:06:55 -05006717static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006718{
6719 struct cmd_lookup *match = data;
6720
Johan Hedberg90e70452012-02-23 23:09:40 +02006721 if (match->sk == NULL) {
6722 match->sk = cmd->sk;
6723 sock_hold(match->sk);
6724 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006725}
6726
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006727void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6728 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006729{
Johan Hedberg90e70452012-02-23 23:09:40 +02006730 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006731
Johan Hedberg92da6092013-03-15 17:06:55 -05006732 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6733 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6734 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006735
6736 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006737 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6738 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006739
6740 if (match.sk)
6741 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006742}
6743
Marcel Holtmann7667da32013-10-15 14:26:27 -07006744void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006745{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006746 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006747 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006748
Johan Hedberg13928972013-03-15 17:07:00 -05006749 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006750 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006751
6752 memset(&ev, 0, sizeof(ev));
6753 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006754 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006755
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006756 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006757 if (!cmd) {
6758 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006759
Johan Hedberg13928972013-03-15 17:07:00 -05006760 /* If this is a HCI command related to powering on the
6761 * HCI dev don't send any mgmt signals.
6762 */
6763 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006764 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006765 }
6766
Marcel Holtmann7667da32013-10-15 14:26:27 -07006767 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6768 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006769}
Szymon Jancc35938b2011-03-22 13:12:21 +01006770
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006771void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006772 u8 *rand192, u8 *hash256, u8 *rand256,
6773 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006774{
6775 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006776
Johan Hedberg744cf192011-11-08 20:40:14 +02006777 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006778
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006779 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006780 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006781 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006782
6783 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006784 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6785 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006786 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006787 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
Johan Hedberg38da1702014-11-17 20:52:20 +02006788 hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006789 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006790
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006791 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006792 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006793
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006794 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006795 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006796
6797 cmd_complete(cmd->sk, hdev->id,
6798 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6799 &rp, sizeof(rp));
6800 } else {
6801 struct mgmt_rp_read_local_oob_data rp;
6802
6803 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006804 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006805
6806 cmd_complete(cmd->sk, hdev->id,
6807 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6808 &rp, sizeof(rp));
6809 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006810 }
6811
6812 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006813}
Johan Hedberge17acd42011-03-30 23:57:16 +03006814
Marcel Holtmann901801b2013-10-06 23:55:51 -07006815void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006816 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6817 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006818{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006819 char buf[512];
6820 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006821 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006822
Johan Hedberg75ce2082014-07-02 22:42:01 +03006823 /* Don't send events for a non-kernel initiated discovery. With
6824 * LE one exception is if we have pend_le_reports > 0 in which
6825 * case we're doing passive scanning and want these events.
6826 */
6827 if (!hci_discovery_active(hdev)) {
6828 if (link_type == ACL_LINK)
6829 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006830 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006831 return;
6832 }
Andre Guedes12602d02013-04-30 15:29:40 -03006833
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006834 /* Make sure that the buffer is big enough. The 5 extra bytes
6835 * are for the potential CoD field.
6836 */
6837 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006838 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006839
Johan Hedberg1dc06092012-01-15 21:01:23 +02006840 memset(buf, 0, sizeof(buf));
6841
Johan Hedberg841c5642014-07-07 12:45:54 +03006842 bacpy(&ev->addr.bdaddr, bdaddr);
6843 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006844 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006845 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006846
Johan Hedberg1dc06092012-01-15 21:01:23 +02006847 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006848 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006849
Johan Hedberg1dc06092012-01-15 21:01:23 +02006850 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6851 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006852 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006853
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006854 if (scan_rsp_len > 0)
6855 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6856
6857 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6858 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006859
Marcel Holtmann901801b2013-10-06 23:55:51 -07006860 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006861}
Johan Hedberga88a9652011-03-30 13:18:12 +03006862
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006863void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6864 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006865{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006866 struct mgmt_ev_device_found *ev;
6867 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6868 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006869
Johan Hedbergb644ba32012-01-17 21:48:47 +02006870 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006871
Johan Hedbergb644ba32012-01-17 21:48:47 +02006872 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006873
Johan Hedbergb644ba32012-01-17 21:48:47 +02006874 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006875 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006876 ev->rssi = rssi;
6877
6878 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006879 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006880
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006881 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006882
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006883 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006884}
Johan Hedberg314b2382011-04-27 10:29:57 -04006885
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006886void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006887{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006888 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006889 struct pending_cmd *cmd;
6890
Andre Guedes343fb142011-11-22 17:14:19 -03006891 BT_DBG("%s discovering %u", hdev->name, discovering);
6892
Johan Hedberg164a6e72011-11-01 17:06:44 +02006893 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006894 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006895 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006896 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006897
6898 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006899 u8 type = hdev->discovery.type;
6900
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006901 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6902 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006903 mgmt_pending_remove(cmd);
6904 }
6905
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006906 memset(&ev, 0, sizeof(ev));
6907 ev.type = hdev->discovery.type;
6908 ev.discovering = discovering;
6909
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006910 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006911}
Antti Julku5e762442011-08-25 16:48:02 +03006912
Marcel Holtmann5976e602013-10-06 04:08:14 -07006913static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6914{
6915 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006916}
6917
6918void mgmt_reenable_advertising(struct hci_dev *hdev)
6919{
6920 struct hci_request req;
6921
Marcel Holtmann5976e602013-10-06 04:08:14 -07006922 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6923 return;
6924
6925 hci_req_init(&req, hdev);
6926 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006927 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006928}