blob: 74571a4b85ec54204e86add24cc5fc08677efd2c [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 Holtmann854bda12014-12-03 19:52:43 +010038#define MGMT_REVISION 8
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,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010096 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020097};
98
99static const u16 mgmt_events[] = {
100 MGMT_EV_CONTROLLER_ERROR,
101 MGMT_EV_INDEX_ADDED,
102 MGMT_EV_INDEX_REMOVED,
103 MGMT_EV_NEW_SETTINGS,
104 MGMT_EV_CLASS_OF_DEV_CHANGED,
105 MGMT_EV_LOCAL_NAME_CHANGED,
106 MGMT_EV_NEW_LINK_KEY,
107 MGMT_EV_NEW_LONG_TERM_KEY,
108 MGMT_EV_DEVICE_CONNECTED,
109 MGMT_EV_DEVICE_DISCONNECTED,
110 MGMT_EV_CONNECT_FAILED,
111 MGMT_EV_PIN_CODE_REQUEST,
112 MGMT_EV_USER_CONFIRM_REQUEST,
113 MGMT_EV_USER_PASSKEY_REQUEST,
114 MGMT_EV_AUTH_FAILED,
115 MGMT_EV_DEVICE_FOUND,
116 MGMT_EV_DISCOVERING,
117 MGMT_EV_DEVICE_BLOCKED,
118 MGMT_EV_DEVICE_UNBLOCKED,
119 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300120 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800121 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700122 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200123 MGMT_EV_DEVICE_ADDED,
124 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300125 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200126 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200127 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200128 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200129};
130
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800131#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300139 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140};
141
Johan Hedbergca69b792011-11-11 18:10:00 +0200142/* HCI to MGMT error code conversion table */
143static u8 mgmt_status_table[] = {
144 MGMT_STATUS_SUCCESS,
145 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
146 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
147 MGMT_STATUS_FAILED, /* Hardware Failure */
148 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
149 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200150 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200151 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
152 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
153 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
154 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
155 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
156 MGMT_STATUS_BUSY, /* Command Disallowed */
157 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
158 MGMT_STATUS_REJECTED, /* Rejected Security */
159 MGMT_STATUS_REJECTED, /* Rejected Personal */
160 MGMT_STATUS_TIMEOUT, /* Host Timeout */
161 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
162 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
163 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
164 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
165 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
166 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
167 MGMT_STATUS_BUSY, /* Repeated Attempts */
168 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
169 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
170 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
171 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
172 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
173 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
174 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
175 MGMT_STATUS_FAILED, /* Unspecified Error */
176 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
177 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
178 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
179 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
180 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
181 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
182 MGMT_STATUS_FAILED, /* Unit Link Key Used */
183 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
184 MGMT_STATUS_TIMEOUT, /* Instant Passed */
185 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
186 MGMT_STATUS_FAILED, /* Transaction Collision */
187 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
188 MGMT_STATUS_REJECTED, /* QoS Rejected */
189 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
190 MGMT_STATUS_REJECTED, /* Insufficient Security */
191 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
192 MGMT_STATUS_BUSY, /* Role Switch Pending */
193 MGMT_STATUS_FAILED, /* Slot Violation */
194 MGMT_STATUS_FAILED, /* Role Switch Failed */
195 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
196 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
197 MGMT_STATUS_BUSY, /* Host Busy Pairing */
198 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
199 MGMT_STATUS_BUSY, /* Controller Busy */
200 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
201 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
202 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
203 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
204 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
205};
206
207static u8 mgmt_status(u8 hci_status)
208{
209 if (hci_status < ARRAY_SIZE(mgmt_status_table))
210 return mgmt_status_table[hci_status];
211
212 return MGMT_STATUS_FAILED;
213}
214
Marcel Holtmann04c60f02014-07-04 19:06:22 +0200215static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
216 struct sock *skip_sk)
217{
218 struct sk_buff *skb;
219 struct mgmt_hdr *hdr;
220
221 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
222 if (!skb)
223 return -ENOMEM;
224
225 hdr = (void *) skb_put(skb, sizeof(*hdr));
226 hdr->opcode = cpu_to_le16(event);
227 if (hdev)
228 hdr->index = cpu_to_le16(hdev->id);
229 else
230 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
231 hdr->len = cpu_to_le16(data_len);
232
233 if (data)
234 memcpy(skb_put(skb, data_len), data, data_len);
235
236 /* Time stamp */
237 __net_timestamp(skb);
238
239 hci_send_to_control(skb, skip_sk);
240 kfree_skb(skb);
241
242 return 0;
243}
244
Szymon Janc4e51eae2011-02-25 19:05:48 +0100245static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200246{
247 struct sk_buff *skb;
248 struct mgmt_hdr *hdr;
249 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300250 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200251
Szymon Janc34eb5252011-02-28 14:10:08 +0100252 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Andre Guedes790eff42012-06-07 19:05:46 -0300254 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255 if (!skb)
256 return -ENOMEM;
257
258 hdr = (void *) skb_put(skb, sizeof(*hdr));
259
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700260 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100261 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200262 hdr->len = cpu_to_le16(sizeof(*ev));
263
264 ev = (void *) skb_put(skb, sizeof(*ev));
265 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200266 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200267
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300268 err = sock_queue_rcv_skb(sk, skb);
269 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200270 kfree_skb(skb);
271
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300272 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200273}
274
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200275static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300276 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200277{
278 struct sk_buff *skb;
279 struct mgmt_hdr *hdr;
280 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300281 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200282
283 BT_DBG("sock %p", sk);
284
Andre Guedes790eff42012-06-07 19:05:46 -0300285 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200286 if (!skb)
287 return -ENOMEM;
288
289 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200290
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700291 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100292 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200293 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200294
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200296 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200297 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100298
299 if (rp)
300 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200301
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300302 err = sock_queue_rcv_skb(sk, skb);
303 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200304 kfree_skb(skb);
305
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100306 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200307}
308
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300309static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
310 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200311{
312 struct mgmt_rp_read_version rp;
313
314 BT_DBG("sock %p", sk);
315
316 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700317 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200318
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200319 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300320 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200321}
322
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300323static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
324 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200325{
326 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200327 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
328 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200329 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200330 size_t rp_size;
331 int i, err;
332
333 BT_DBG("sock %p", sk);
334
335 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
336
337 rp = kmalloc(rp_size, GFP_KERNEL);
338 if (!rp)
339 return -ENOMEM;
340
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700341 rp->num_commands = cpu_to_le16(num_commands);
342 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200343
344 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
345 put_unaligned_le16(mgmt_commands[i], opcode);
346
347 for (i = 0; i < num_events; i++, opcode++)
348 put_unaligned_le16(mgmt_events[i], opcode);
349
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200350 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300351 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200352 kfree(rp);
353
354 return err;
355}
356
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300357static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
358 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200359{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200360 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200361 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200362 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300364 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365
366 BT_DBG("sock %p", sk);
367
368 read_lock(&hci_dev_list_lock);
369
370 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300371 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200372 if (d->dev_type == HCI_BREDR &&
373 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700374 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375 }
376
Johan Hedberga38528f2011-01-22 06:46:43 +0200377 rp_len = sizeof(*rp) + (2 * count);
378 rp = kmalloc(rp_len, GFP_ATOMIC);
379 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100380 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200381 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383
Johan Hedberg476e44c2012-10-19 20:10:46 +0300384 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200385 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200386 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200387 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200389 continue;
390
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200391 /* Devices marked as raw-only are neither configured
392 * nor unconfigured controllers.
393 */
394 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700395 continue;
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397 if (d->dev_type == HCI_BREDR &&
398 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700399 rp->index[count++] = cpu_to_le16(d->id);
400 BT_DBG("Added hci%u", d->id);
401 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200402 }
403
Johan Hedberg476e44c2012-10-19 20:10:46 +0300404 rp->num_controllers = cpu_to_le16(count);
405 rp_len = sizeof(*rp) + (2 * count);
406
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200407 read_unlock(&hci_dev_list_lock);
408
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200409 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300410 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200411
Johan Hedberga38528f2011-01-22 06:46:43 +0200412 kfree(rp);
413
414 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200415}
416
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200417static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
418 void *data, u16 data_len)
419{
420 struct mgmt_rp_read_unconf_index_list *rp;
421 struct hci_dev *d;
422 size_t rp_len;
423 u16 count;
424 int err;
425
426 BT_DBG("sock %p", sk);
427
428 read_lock(&hci_dev_list_lock);
429
430 count = 0;
431 list_for_each_entry(d, &hci_dev_list, list) {
432 if (d->dev_type == HCI_BREDR &&
433 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
434 count++;
435 }
436
437 rp_len = sizeof(*rp) + (2 * count);
438 rp = kmalloc(rp_len, GFP_ATOMIC);
439 if (!rp) {
440 read_unlock(&hci_dev_list_lock);
441 return -ENOMEM;
442 }
443
444 count = 0;
445 list_for_each_entry(d, &hci_dev_list, list) {
446 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200447 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200448 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
449 continue;
450
451 /* Devices marked as raw-only are neither configured
452 * nor unconfigured controllers.
453 */
454 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
455 continue;
456
457 if (d->dev_type == HCI_BREDR &&
458 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
459 rp->index[count++] = cpu_to_le16(d->id);
460 BT_DBG("Added hci%u", d->id);
461 }
462 }
463
464 rp->num_controllers = cpu_to_le16(count);
465 rp_len = sizeof(*rp) + (2 * count);
466
467 read_unlock(&hci_dev_list_lock);
468
469 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
470 0, rp, rp_len);
471
472 kfree(rp);
473
474 return err;
475}
476
Marcel Holtmanndbece372014-07-04 18:11:55 +0200477static bool is_configured(struct hci_dev *hdev)
478{
479 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
480 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
481 return false;
482
483 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
484 !bacmp(&hdev->public_addr, BDADDR_ANY))
485 return false;
486
487 return true;
488}
489
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200490static __le32 get_missing_options(struct hci_dev *hdev)
491{
492 u32 options = 0;
493
Marcel Holtmanndbece372014-07-04 18:11:55 +0200494 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
495 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200496 options |= MGMT_OPTION_EXTERNAL_CONFIG;
497
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200498 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
499 !bacmp(&hdev->public_addr, BDADDR_ANY))
500 options |= MGMT_OPTION_PUBLIC_ADDRESS;
501
502 return cpu_to_le32(options);
503}
504
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200505static int new_options(struct hci_dev *hdev, struct sock *skip)
506{
507 __le32 options = get_missing_options(hdev);
508
509 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
510 sizeof(options), skip);
511}
512
Marcel Holtmanndbece372014-07-04 18:11:55 +0200513static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
514{
515 __le32 options = get_missing_options(hdev);
516
517 return cmd_complete(sk, hdev->id, opcode, 0, &options,
518 sizeof(options));
519}
520
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200521static int read_config_info(struct sock *sk, struct hci_dev *hdev,
522 void *data, u16 data_len)
523{
524 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200525 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200526
527 BT_DBG("sock %p %s", sk, hdev->name);
528
529 hci_dev_lock(hdev);
530
531 memset(&rp, 0, sizeof(rp));
532 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200533
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200534 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
535 options |= MGMT_OPTION_EXTERNAL_CONFIG;
536
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200537 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200538 options |= MGMT_OPTION_PUBLIC_ADDRESS;
539
540 rp.supported_options = cpu_to_le32(options);
541 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200542
543 hci_dev_unlock(hdev);
544
545 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
546 sizeof(rp));
547}
548
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200549static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200550{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200552
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300554 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800555 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300556 settings |= MGMT_SETTING_CONNECTABLE;
557 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200558
Andre Guedesed3fa312012-07-24 15:03:46 -0300559 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500560 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
561 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200562 settings |= MGMT_SETTING_BREDR;
563 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700564
565 if (lmp_ssp_capable(hdev)) {
566 settings |= MGMT_SETTING_SSP;
567 settings |= MGMT_SETTING_HS;
568 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800569
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800570 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200571 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800572 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700573 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100574
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300575 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200576 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300578 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200579 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300580 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200581
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200582 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
583 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200584 settings |= MGMT_SETTING_CONFIGURATION;
585
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200586 return settings;
587}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200588
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200589static u32 get_current_settings(struct hci_dev *hdev)
590{
591 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200592
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200593 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100594 settings |= MGMT_SETTING_POWERED;
595
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200596 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200597 settings |= MGMT_SETTING_CONNECTABLE;
598
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500599 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
600 settings |= MGMT_SETTING_FAST_CONNECTABLE;
601
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200602 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200603 settings |= MGMT_SETTING_DISCOVERABLE;
604
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300605 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300606 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607
Johan Hedberg56f87902013-10-02 13:43:13 +0300608 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609 settings |= MGMT_SETTING_BREDR;
610
Johan Hedberg06199cf2012-02-22 16:37:11 +0200611 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200612 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200613
Johan Hedberg47990ea2012-02-22 11:58:37 +0200614 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200615 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200616
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200617 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200619
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200620 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
621 settings |= MGMT_SETTING_HS;
622
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200623 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300624 settings |= MGMT_SETTING_ADVERTISING;
625
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800626 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
627 settings |= MGMT_SETTING_SECURE_CONN;
628
Johan Hedberg0663b292014-06-24 13:15:50 +0300629 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800630 settings |= MGMT_SETTING_DEBUG_KEYS;
631
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200632 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
633 settings |= MGMT_SETTING_PRIVACY;
634
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200635 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200636}
637
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300638#define PNP_INFO_SVCLASS_ID 0x1200
639
Johan Hedberg213202e2013-01-27 00:31:33 +0200640static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
641{
642 u8 *ptr = data, *uuids_start = NULL;
643 struct bt_uuid *uuid;
644
645 if (len < 4)
646 return ptr;
647
648 list_for_each_entry(uuid, &hdev->uuids, list) {
649 u16 uuid16;
650
651 if (uuid->size != 16)
652 continue;
653
654 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
655 if (uuid16 < 0x1100)
656 continue;
657
658 if (uuid16 == PNP_INFO_SVCLASS_ID)
659 continue;
660
661 if (!uuids_start) {
662 uuids_start = ptr;
663 uuids_start[0] = 1;
664 uuids_start[1] = EIR_UUID16_ALL;
665 ptr += 2;
666 }
667
668 /* Stop if not enough space to put next UUID */
669 if ((ptr - data) + sizeof(u16) > len) {
670 uuids_start[1] = EIR_UUID16_SOME;
671 break;
672 }
673
674 *ptr++ = (uuid16 & 0x00ff);
675 *ptr++ = (uuid16 & 0xff00) >> 8;
676 uuids_start[0] += sizeof(uuid16);
677 }
678
679 return ptr;
680}
681
Johan Hedbergcdf19632013-01-27 00:31:34 +0200682static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
683{
684 u8 *ptr = data, *uuids_start = NULL;
685 struct bt_uuid *uuid;
686
687 if (len < 6)
688 return ptr;
689
690 list_for_each_entry(uuid, &hdev->uuids, list) {
691 if (uuid->size != 32)
692 continue;
693
694 if (!uuids_start) {
695 uuids_start = ptr;
696 uuids_start[0] = 1;
697 uuids_start[1] = EIR_UUID32_ALL;
698 ptr += 2;
699 }
700
701 /* Stop if not enough space to put next UUID */
702 if ((ptr - data) + sizeof(u32) > len) {
703 uuids_start[1] = EIR_UUID32_SOME;
704 break;
705 }
706
707 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
708 ptr += sizeof(u32);
709 uuids_start[0] += sizeof(u32);
710 }
711
712 return ptr;
713}
714
Johan Hedbergc00d5752013-01-27 00:31:35 +0200715static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 18)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 if (uuid->size != 128)
725 continue;
726
727 if (!uuids_start) {
728 uuids_start = ptr;
729 uuids_start[0] = 1;
730 uuids_start[1] = EIR_UUID128_ALL;
731 ptr += 2;
732 }
733
734 /* Stop if not enough space to put next UUID */
735 if ((ptr - data) + 16 > len) {
736 uuids_start[1] = EIR_UUID128_SOME;
737 break;
738 }
739
740 memcpy(ptr, uuid->uuid, 16);
741 ptr += 16;
742 uuids_start[0] += 16;
743 }
744
745 return ptr;
746}
747
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300748static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
749{
750 struct pending_cmd *cmd;
751
752 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
753 if (cmd->opcode == opcode)
754 return cmd;
755 }
756
757 return NULL;
758}
759
Johan Hedberg95868422014-06-28 17:54:07 +0300760static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
761 struct hci_dev *hdev,
762 const void *data)
763{
764 struct pending_cmd *cmd;
765
766 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
767 if (cmd->user_data != data)
768 continue;
769 if (cmd->opcode == opcode)
770 return cmd;
771 }
772
773 return NULL;
774}
775
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700776static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
777{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700778 u8 ad_len = 0;
779 size_t name_len;
780
781 name_len = strlen(hdev->dev_name);
782 if (name_len > 0) {
783 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
784
785 if (name_len > max_len) {
786 name_len = max_len;
787 ptr[1] = EIR_NAME_SHORT;
788 } else
789 ptr[1] = EIR_NAME_COMPLETE;
790
791 ptr[0] = name_len + 1;
792
793 memcpy(ptr + 2, hdev->dev_name, name_len);
794
795 ad_len += (name_len + 2);
796 ptr += (name_len + 2);
797 }
798
799 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700800}
801
802static void update_scan_rsp_data(struct hci_request *req)
803{
804 struct hci_dev *hdev = req->hdev;
805 struct hci_cp_le_set_scan_rsp_data cp;
806 u8 len;
807
Johan Hedberg7751ef12013-10-19 23:38:15 +0300808 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700809 return;
810
811 memset(&cp, 0, sizeof(cp));
812
813 len = create_scan_rsp_data(hdev, cp.data);
814
Johan Hedbergeb438b52013-10-16 15:31:07 +0300815 if (hdev->scan_rsp_data_len == len &&
816 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700817 return;
818
Johan Hedbergeb438b52013-10-16 15:31:07 +0300819 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
820 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700821
822 cp.length = len;
823
824 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
825}
826
Johan Hedberg9a43e252013-10-20 19:00:07 +0300827static u8 get_adv_discov_flags(struct hci_dev *hdev)
828{
829 struct pending_cmd *cmd;
830
831 /* If there's a pending mgmt command the flags will not yet have
832 * their final values, so check for this first.
833 */
834 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
835 if (cmd) {
836 struct mgmt_mode *cp = cmd->param;
837 if (cp->val == 0x01)
838 return LE_AD_GENERAL;
839 else if (cp->val == 0x02)
840 return LE_AD_LIMITED;
841 } else {
842 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
843 return LE_AD_LIMITED;
844 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
845 return LE_AD_GENERAL;
846 }
847
848 return 0;
849}
850
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700851static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700852{
853 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854
Johan Hedberg9a43e252013-10-20 19:00:07 +0300855 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856
Johan Hedberge8340042014-01-30 11:16:50 -0800857 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859
860 if (flags) {
861 BT_DBG("adv flags 0x%02x", flags);
862
863 ptr[0] = 2;
864 ptr[1] = EIR_FLAGS;
865 ptr[2] = flags;
866
867 ad_len += 3;
868 ptr += 3;
869 }
870
871 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
872 ptr[0] = 2;
873 ptr[1] = EIR_TX_POWER;
874 ptr[2] = (u8) hdev->adv_tx_power;
875
876 ad_len += 3;
877 ptr += 3;
878 }
879
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700880 return ad_len;
881}
882
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700883static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700884{
885 struct hci_dev *hdev = req->hdev;
886 struct hci_cp_le_set_adv_data cp;
887 u8 len;
888
Johan Hedberg10994ce2013-10-19 23:38:16 +0300889 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700890 return;
891
892 memset(&cp, 0, sizeof(cp));
893
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700894 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700895
896 if (hdev->adv_data_len == len &&
897 memcmp(cp.data, hdev->adv_data, len) == 0)
898 return;
899
900 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
901 hdev->adv_data_len = len;
902
903 cp.length = len;
904
905 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
906}
907
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300908int mgmt_update_adv_data(struct hci_dev *hdev)
909{
910 struct hci_request req;
911
912 hci_req_init(&req, hdev);
913 update_adv_data(&req);
914
915 return hci_req_run(&req, NULL);
916}
917
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300918static void create_eir(struct hci_dev *hdev, u8 *data)
919{
920 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300921 size_t name_len;
922
923 name_len = strlen(hdev->dev_name);
924
925 if (name_len > 0) {
926 /* EIR Data type */
927 if (name_len > 48) {
928 name_len = 48;
929 ptr[1] = EIR_NAME_SHORT;
930 } else
931 ptr[1] = EIR_NAME_COMPLETE;
932
933 /* EIR Data length */
934 ptr[0] = name_len + 1;
935
936 memcpy(ptr + 2, hdev->dev_name, name_len);
937
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300938 ptr += (name_len + 2);
939 }
940
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100941 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700942 ptr[0] = 2;
943 ptr[1] = EIR_TX_POWER;
944 ptr[2] = (u8) hdev->inq_tx_power;
945
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700946 ptr += 3;
947 }
948
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700949 if (hdev->devid_source > 0) {
950 ptr[0] = 9;
951 ptr[1] = EIR_DEVICE_ID;
952
953 put_unaligned_le16(hdev->devid_source, ptr + 2);
954 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
955 put_unaligned_le16(hdev->devid_product, ptr + 6);
956 put_unaligned_le16(hdev->devid_version, ptr + 8);
957
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700958 ptr += 10;
959 }
960
Johan Hedberg213202e2013-01-27 00:31:33 +0200961 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200962 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200963 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300964}
965
Johan Hedberg890ea892013-03-15 17:06:52 -0500966static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967{
Johan Hedberg890ea892013-03-15 17:06:52 -0500968 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300969 struct hci_cp_write_eir cp;
970
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200971 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500972 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200973
Johan Hedberg976eb202012-10-24 21:12:01 +0300974 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500975 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300976
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200977 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500978 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300979
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200980 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500981 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300982
983 memset(&cp, 0, sizeof(cp));
984
985 create_eir(hdev, cp.data);
986
987 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500988 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300989
990 memcpy(hdev->eir, cp.data, sizeof(cp.data));
991
Johan Hedberg890ea892013-03-15 17:06:52 -0500992 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300993}
994
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200995static u8 get_service_classes(struct hci_dev *hdev)
996{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300997 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200998 u8 val = 0;
999
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001000 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001001 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001002
1003 return val;
1004}
1005
Johan Hedberg890ea892013-03-15 17:06:52 -05001006static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001007{
Johan Hedberg890ea892013-03-15 17:06:52 -05001008 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001009 u8 cod[3];
1010
1011 BT_DBG("%s", hdev->name);
1012
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001013 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001014 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001015
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001016 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1017 return;
1018
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001019 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001020 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001021
1022 cod[0] = hdev->minor_class;
1023 cod[1] = hdev->major_class;
1024 cod[2] = get_service_classes(hdev);
1025
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001026 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1027 cod[1] |= 0x20;
1028
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001029 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001030 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001031
Johan Hedberg890ea892013-03-15 17:06:52 -05001032 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033}
1034
Johan Hedberga4858cb2014-02-25 19:56:31 +02001035static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001036{
1037 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001038
1039 /* If there's a pending mgmt command the flag will not yet have
1040 * it's final value, so check for this first.
1041 */
1042 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1043 if (cmd) {
1044 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001045 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001046 }
1047
Johan Hedberga4858cb2014-02-25 19:56:31 +02001048 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001049}
1050
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001051static void disable_advertising(struct hci_request *req)
1052{
1053 u8 enable = 0x00;
1054
1055 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1056}
1057
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001058static void enable_advertising(struct hci_request *req)
1059{
1060 struct hci_dev *hdev = req->hdev;
1061 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001062 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001063 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001064
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001065 if (hci_conn_num(hdev, LE_LINK) > 0)
1066 return;
1067
1068 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1069 disable_advertising(req);
1070
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001071 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001072 * hci_update_random_address knows that it's safe to go ahead
1073 * and write a new random address. The flag will be set back on
1074 * as soon as the SET_ADV_ENABLE HCI command completes.
1075 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001076 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001077
Johan Hedberga4858cb2014-02-25 19:56:31 +02001078 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001079
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 /* Set require_privacy to true only when non-connectable
1081 * advertising is used. In that case it is fine to use a
1082 * non-resolvable private address.
1083 */
1084 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001085 return;
1086
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001087 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001088 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1089 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001090 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001091 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001092 cp.channel_map = hdev->le_adv_channel_map;
1093
1094 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1095
1096 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1097}
1098
Johan Hedberg7d785252011-12-15 00:47:39 +02001099static void service_cache_off(struct work_struct *work)
1100{
1101 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001102 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001103 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001104
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001105 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001106 return;
1107
Johan Hedberg890ea892013-03-15 17:06:52 -05001108 hci_req_init(&req, hdev);
1109
Johan Hedberg7d785252011-12-15 00:47:39 +02001110 hci_dev_lock(hdev);
1111
Johan Hedberg890ea892013-03-15 17:06:52 -05001112 update_eir(&req);
1113 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001114
1115 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001116
1117 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001118}
1119
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001120static void rpa_expired(struct work_struct *work)
1121{
1122 struct hci_dev *hdev = container_of(work, struct hci_dev,
1123 rpa_expired.work);
1124 struct hci_request req;
1125
1126 BT_DBG("");
1127
1128 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1129
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001130 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001131 return;
1132
1133 /* The generation of a new RPA and programming it into the
1134 * controller happens in the enable_advertising() function.
1135 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001136 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 hci_req_run(&req, NULL);
1139}
1140
Johan Hedberg6a919082012-02-28 06:17:26 +02001141static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001142{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001143 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001144 return;
1145
Johan Hedberg4f87da82012-03-02 19:55:56 +02001146 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001147 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001148
Johan Hedberg4f87da82012-03-02 19:55:56 +02001149 /* Non-mgmt controlled devices get this bit set
1150 * implicitly so that pairing works for them, however
1151 * for mgmt we require user-space to explicitly enable
1152 * it
1153 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001154 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001155}
1156
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001157static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001158 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001159{
1160 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001161
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001162 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001164 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001165
Johan Hedberg03811012010-12-08 00:21:06 +02001166 memset(&rp, 0, sizeof(rp));
1167
Johan Hedberg03811012010-12-08 00:21:06 +02001168 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001169
1170 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001171 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001172
1173 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1174 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1175
1176 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001177
1178 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001179 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001180
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001181 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001182
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001183 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001184 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001185}
1186
1187static void mgmt_pending_free(struct pending_cmd *cmd)
1188{
1189 sock_put(cmd->sk);
1190 kfree(cmd->param);
1191 kfree(cmd);
1192}
1193
1194static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001195 struct hci_dev *hdev, void *data,
1196 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001197{
1198 struct pending_cmd *cmd;
1199
Johan Hedbergfca20012014-06-28 17:54:05 +03001200 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001201 if (!cmd)
1202 return NULL;
1203
1204 cmd->opcode = opcode;
1205 cmd->index = hdev->id;
1206
Andre Guedes12b94562012-06-07 19:05:45 -03001207 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001208 if (!cmd->param) {
1209 kfree(cmd);
1210 return NULL;
1211 }
1212
1213 if (data)
1214 memcpy(cmd->param, data, len);
1215
1216 cmd->sk = sk;
1217 sock_hold(sk);
1218
1219 list_add(&cmd->list, &hdev->mgmt_pending);
1220
1221 return cmd;
1222}
1223
1224static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001225 void (*cb)(struct pending_cmd *cmd,
1226 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001227 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001228{
Andre Guedesa3d09352013-02-01 11:21:30 -03001229 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001230
Andre Guedesa3d09352013-02-01 11:21:30 -03001231 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001232 if (opcode > 0 && cmd->opcode != opcode)
1233 continue;
1234
1235 cb(cmd, data);
1236 }
1237}
1238
Johan Hedberg03811012010-12-08 00:21:06 +02001239static void mgmt_pending_remove(struct pending_cmd *cmd)
1240{
1241 list_del(&cmd->list);
1242 mgmt_pending_free(cmd);
1243}
1244
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001245static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001246{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001247 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001248
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001249 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001250 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001251}
1252
Johan Hedberg8b064a32014-02-24 14:52:22 +02001253static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1254{
1255 BT_DBG("%s status 0x%02x", hdev->name, status);
1256
Johan Hedberga3172b72014-02-28 09:33:44 +02001257 if (hci_conn_count(hdev) == 0) {
1258 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001259 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001260 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001261}
1262
Johan Hedberg23a48092014-07-08 16:05:06 +03001263static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001264{
1265 struct hci_dev *hdev = req->hdev;
1266 struct hci_cp_remote_name_req_cancel cp;
1267 struct inquiry_entry *e;
1268
1269 switch (hdev->discovery.state) {
1270 case DISCOVERY_FINDING:
1271 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1272 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1273 } else {
1274 cancel_delayed_work(&hdev->le_scan_disable);
1275 hci_req_add_le_scan_disable(req);
1276 }
1277
Johan Hedberg23a48092014-07-08 16:05:06 +03001278 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001279
1280 case DISCOVERY_RESOLVING:
1281 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1282 NAME_PENDING);
1283 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001284 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001285
1286 bacpy(&cp.bdaddr, &e->data.bdaddr);
1287 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1288 &cp);
1289
Johan Hedberg23a48092014-07-08 16:05:06 +03001290 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001291
1292 default:
1293 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001294 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001295 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001296 return true;
1297 }
1298
Johan Hedberg21a60d32014-06-10 14:05:58 +03001299 break;
1300 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001301
1302 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001303}
1304
Johan Hedberg8b064a32014-02-24 14:52:22 +02001305static int clean_up_hci_state(struct hci_dev *hdev)
1306{
1307 struct hci_request req;
1308 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001309 bool discov_stopped;
1310 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001311
1312 hci_req_init(&req, hdev);
1313
1314 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1315 test_bit(HCI_PSCAN, &hdev->flags)) {
1316 u8 scan = 0x00;
1317 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1318 }
1319
Johan Hedberg73e082f2014-07-08 15:07:51 +03001320 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001321 disable_advertising(&req);
1322
Johan Hedberg23a48092014-07-08 16:05:06 +03001323 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001324
1325 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1326 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001327 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001328
Johan Hedbergc9910d02014-02-27 14:35:12 +02001329 switch (conn->state) {
1330 case BT_CONNECTED:
1331 case BT_CONFIG:
1332 dc.handle = cpu_to_le16(conn->handle);
1333 dc.reason = 0x15; /* Terminated due to Power Off */
1334 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1335 break;
1336 case BT_CONNECT:
1337 if (conn->type == LE_LINK)
1338 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1339 0, NULL);
1340 else if (conn->type == ACL_LINK)
1341 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1342 6, &conn->dst);
1343 break;
1344 case BT_CONNECT2:
1345 bacpy(&rej.bdaddr, &conn->dst);
1346 rej.reason = 0x15; /* Terminated due to Power Off */
1347 if (conn->type == ACL_LINK)
1348 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1349 sizeof(rej), &rej);
1350 else if (conn->type == SCO_LINK)
1351 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1352 sizeof(rej), &rej);
1353 break;
1354 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001355 }
1356
Johan Hedberg23a48092014-07-08 16:05:06 +03001357 err = hci_req_run(&req, clean_up_hci_complete);
1358 if (!err && discov_stopped)
1359 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1360
1361 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001362}
1363
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001364static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001365 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001366{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001367 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001368 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001369 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001370
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001371 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001372
Johan Hedberga7e80f22013-01-09 16:05:19 +02001373 if (cp->val != 0x00 && cp->val != 0x01)
1374 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1375 MGMT_STATUS_INVALID_PARAMS);
1376
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001377 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001378
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001379 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1380 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1381 MGMT_STATUS_BUSY);
1382 goto failed;
1383 }
1384
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001385 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1386 cancel_delayed_work(&hdev->power_off);
1387
1388 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001389 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1390 data, len);
1391 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001392 goto failed;
1393 }
1394 }
1395
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001396 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001397 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001398 goto failed;
1399 }
1400
Johan Hedberg03811012010-12-08 00:21:06 +02001401 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1402 if (!cmd) {
1403 err = -ENOMEM;
1404 goto failed;
1405 }
1406
Johan Hedberg8b064a32014-02-24 14:52:22 +02001407 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001408 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001409 err = 0;
1410 } else {
1411 /* Disconnect connections, stop scans, etc */
1412 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001413 if (!err)
1414 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1415 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001416
Johan Hedberg8b064a32014-02-24 14:52:22 +02001417 /* ENODATA means there were no HCI commands queued */
1418 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001419 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001420 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1421 err = 0;
1422 }
1423 }
Johan Hedberg03811012010-12-08 00:21:06 +02001424
1425failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001426 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001427 return err;
1428}
1429
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001430static int new_settings(struct hci_dev *hdev, struct sock *skip)
1431{
1432 __le32 ev;
1433
1434 ev = cpu_to_le32(get_current_settings(hdev));
1435
1436 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1437}
1438
Johan Hedberg91a668b2014-07-09 13:28:26 +03001439int mgmt_new_settings(struct hci_dev *hdev)
1440{
1441 return new_settings(hdev, NULL);
1442}
1443
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001444struct cmd_lookup {
1445 struct sock *sk;
1446 struct hci_dev *hdev;
1447 u8 mgmt_status;
1448};
1449
1450static void settings_rsp(struct pending_cmd *cmd, void *data)
1451{
1452 struct cmd_lookup *match = data;
1453
1454 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1455
1456 list_del(&cmd->list);
1457
1458 if (match->sk == NULL) {
1459 match->sk = cmd->sk;
1460 sock_hold(match->sk);
1461 }
1462
1463 mgmt_pending_free(cmd);
1464}
1465
1466static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1467{
1468 u8 *status = data;
1469
1470 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1471 mgmt_pending_remove(cmd);
1472}
1473
Johan Hedberge6fe7982013-10-02 15:45:22 +03001474static u8 mgmt_bredr_support(struct hci_dev *hdev)
1475{
1476 if (!lmp_bredr_capable(hdev))
1477 return MGMT_STATUS_NOT_SUPPORTED;
1478 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1479 return MGMT_STATUS_REJECTED;
1480 else
1481 return MGMT_STATUS_SUCCESS;
1482}
1483
1484static u8 mgmt_le_support(struct hci_dev *hdev)
1485{
1486 if (!lmp_le_capable(hdev))
1487 return MGMT_STATUS_NOT_SUPPORTED;
1488 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1489 return MGMT_STATUS_REJECTED;
1490 else
1491 return MGMT_STATUS_SUCCESS;
1492}
1493
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001494static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1495{
1496 struct pending_cmd *cmd;
1497 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001498 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001499 bool changed;
1500
1501 BT_DBG("status 0x%02x", status);
1502
1503 hci_dev_lock(hdev);
1504
1505 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1506 if (!cmd)
1507 goto unlock;
1508
1509 if (status) {
1510 u8 mgmt_err = mgmt_status(status);
1511 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001512 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001513 goto remove_cmd;
1514 }
1515
1516 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001517 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001518 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1519 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001520
1521 if (hdev->discov_timeout > 0) {
1522 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1523 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1524 to);
1525 }
1526 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001527 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1528 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001529 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001530
1531 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1532
1533 if (changed)
1534 new_settings(hdev, cmd->sk);
1535
Marcel Holtmann970ba522013-10-15 06:33:57 -07001536 /* When the discoverable mode gets changed, make sure
1537 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001538 * bit correctly set. Also update page scan based on whitelist
1539 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001540 */
1541 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001542 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001543 update_class(&req);
1544 hci_req_run(&req, NULL);
1545
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001546remove_cmd:
1547 mgmt_pending_remove(cmd);
1548
1549unlock:
1550 hci_dev_unlock(hdev);
1551}
1552
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001553static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001554 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001555{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001556 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001557 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001558 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001559 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001560 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001561 int err;
1562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001563 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001564
Johan Hedberg9a43e252013-10-20 19:00:07 +03001565 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1566 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001567 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001568 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001569
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001570 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001571 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1572 MGMT_STATUS_INVALID_PARAMS);
1573
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001574 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001575
1576 /* Disabling discoverable requires that no timeout is set,
1577 * and enabling limited discoverable requires a timeout.
1578 */
1579 if ((cp->val == 0x00 && timeout > 0) ||
1580 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001581 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001582 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001583
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001584 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001585
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001587 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001588 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001589 goto failed;
1590 }
1591
1592 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001593 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001594 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001595 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001596 goto failed;
1597 }
1598
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001599 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001600 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001601 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001602 goto failed;
1603 }
1604
1605 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001606 bool changed = false;
1607
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001608 /* Setting limited discoverable when powered off is
1609 * not a valid operation since it requires a timeout
1610 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1611 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001612 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1613 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1614 changed = true;
1615 }
1616
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001617 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001618 if (err < 0)
1619 goto failed;
1620
1621 if (changed)
1622 err = new_settings(hdev, sk);
1623
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001624 goto failed;
1625 }
1626
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001627 /* If the current mode is the same, then just update the timeout
1628 * value with the new value. And if only the timeout gets updated,
1629 * then no need for any HCI transactions.
1630 */
1631 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1632 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1633 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001634 cancel_delayed_work(&hdev->discov_off);
1635 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001636
Marcel Holtmann36261542013-10-15 08:28:51 -07001637 if (cp->val && hdev->discov_timeout > 0) {
1638 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001639 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001640 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001641 }
1642
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001643 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001644 goto failed;
1645 }
1646
1647 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1648 if (!cmd) {
1649 err = -ENOMEM;
1650 goto failed;
1651 }
1652
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001653 /* Cancel any potential discoverable timeout that might be
1654 * still active and store new timeout value. The arming of
1655 * the timeout happens in the complete handler.
1656 */
1657 cancel_delayed_work(&hdev->discov_off);
1658 hdev->discov_timeout = timeout;
1659
Johan Hedbergb456f872013-10-19 23:38:22 +03001660 /* Limited discoverable mode */
1661 if (cp->val == 0x02)
1662 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1663 else
1664 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1665
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001666 hci_req_init(&req, hdev);
1667
Johan Hedberg9a43e252013-10-20 19:00:07 +03001668 /* The procedure for LE-only controllers is much simpler - just
1669 * update the advertising data.
1670 */
1671 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1672 goto update_ad;
1673
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001674 scan = SCAN_PAGE;
1675
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001676 if (cp->val) {
1677 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001678
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001679 if (cp->val == 0x02) {
1680 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001681 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001682 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1683 hci_cp.iac_lap[1] = 0x8b;
1684 hci_cp.iac_lap[2] = 0x9e;
1685 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1686 hci_cp.iac_lap[4] = 0x8b;
1687 hci_cp.iac_lap[5] = 0x9e;
1688 } else {
1689 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001690 hci_cp.num_iac = 1;
1691 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1692 hci_cp.iac_lap[1] = 0x8b;
1693 hci_cp.iac_lap[2] = 0x9e;
1694 }
1695
1696 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1697 (hci_cp.num_iac * 3) + 1, &hci_cp);
1698
1699 scan |= SCAN_INQUIRY;
1700 } else {
1701 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1702 }
1703
1704 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001705
Johan Hedberg9a43e252013-10-20 19:00:07 +03001706update_ad:
1707 update_adv_data(&req);
1708
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001709 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001710 if (err < 0)
1711 mgmt_pending_remove(cmd);
1712
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001713failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001714 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001715 return err;
1716}
1717
Johan Hedberg406d7802013-03-15 17:07:09 -05001718static void write_fast_connectable(struct hci_request *req, bool enable)
1719{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001720 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001721 struct hci_cp_write_page_scan_activity acp;
1722 u8 type;
1723
Johan Hedberg547003b2013-10-21 16:51:53 +03001724 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1725 return;
1726
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001727 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1728 return;
1729
Johan Hedberg406d7802013-03-15 17:07:09 -05001730 if (enable) {
1731 type = PAGE_SCAN_TYPE_INTERLACED;
1732
1733 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001734 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001735 } else {
1736 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1737
1738 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001739 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001740 }
1741
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001742 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001743
Johan Hedbergbd98b992013-03-15 17:07:13 -05001744 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1745 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1746 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1747 sizeof(acp), &acp);
1748
1749 if (hdev->page_scan_type != type)
1750 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001751}
1752
Johan Hedberg2b76f452013-03-15 17:07:04 -05001753static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1754{
1755 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001756 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001757 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001758
1759 BT_DBG("status 0x%02x", status);
1760
1761 hci_dev_lock(hdev);
1762
1763 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1764 if (!cmd)
1765 goto unlock;
1766
Johan Hedberg37438c12013-10-14 16:20:05 +03001767 if (status) {
1768 u8 mgmt_err = mgmt_status(status);
1769 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1770 goto remove_cmd;
1771 }
1772
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001773 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001774 if (cp->val) {
1775 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1776 &hdev->dev_flags);
1777 discov_changed = false;
1778 } else {
1779 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1780 &hdev->dev_flags);
1781 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1782 &hdev->dev_flags);
1783 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001784
Johan Hedberg2b76f452013-03-15 17:07:04 -05001785 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1786
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001787 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001788 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001789 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001790 if (discov_changed)
1791 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001792 hci_update_background_scan(hdev);
1793 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001794
Johan Hedberg37438c12013-10-14 16:20:05 +03001795remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001796 mgmt_pending_remove(cmd);
1797
1798unlock:
1799 hci_dev_unlock(hdev);
1800}
1801
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001802static int set_connectable_update_settings(struct hci_dev *hdev,
1803 struct sock *sk, u8 val)
1804{
1805 bool changed = false;
1806 int err;
1807
1808 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1809 changed = true;
1810
1811 if (val) {
1812 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1813 } else {
1814 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1815 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1816 }
1817
1818 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1819 if (err < 0)
1820 return err;
1821
Johan Hedberg562064e2014-07-08 16:35:34 +03001822 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001823 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001824 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001825 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001826 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001827
1828 return 0;
1829}
1830
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001831static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001832 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001833{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001834 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001835 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001836 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001837 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001838 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001839
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001840 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001841
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001842 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1843 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001844 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001845 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001846
Johan Hedberga7e80f22013-01-09 16:05:19 +02001847 if (cp->val != 0x00 && cp->val != 0x01)
1848 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1849 MGMT_STATUS_INVALID_PARAMS);
1850
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001851 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001852
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001853 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001854 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001855 goto failed;
1856 }
1857
1858 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001859 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001860 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001861 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001862 goto failed;
1863 }
1864
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001865 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1866 if (!cmd) {
1867 err = -ENOMEM;
1868 goto failed;
1869 }
1870
Johan Hedberg2b76f452013-03-15 17:07:04 -05001871 hci_req_init(&req, hdev);
1872
Johan Hedberg9a43e252013-10-20 19:00:07 +03001873 /* If BR/EDR is not enabled and we disable advertising as a
1874 * by-product of disabling connectable, we need to update the
1875 * advertising flags.
1876 */
1877 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1878 if (!cp->val) {
1879 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1880 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1881 }
1882 update_adv_data(&req);
1883 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001884 if (cp->val) {
1885 scan = SCAN_PAGE;
1886 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001887 /* If we don't have any whitelist entries just
1888 * disable all scanning. If there are entries
1889 * and we had both page and inquiry scanning
1890 * enabled then fall back to only page scanning.
1891 * Otherwise no changes are needed.
1892 */
1893 if (list_empty(&hdev->whitelist))
1894 scan = SCAN_DISABLED;
1895 else if (test_bit(HCI_ISCAN, &hdev->flags))
1896 scan = SCAN_PAGE;
1897 else
1898 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001899
1900 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001901 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001902 cancel_delayed_work(&hdev->discov_off);
1903 }
1904
1905 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1906 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001907
Johan Hedberg3bd27242014-07-28 20:53:58 +03001908no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001909 /* If we're going from non-connectable to connectable or
1910 * vice-versa when fast connectable is enabled ensure that fast
1911 * connectable gets disabled. write_fast_connectable won't do
1912 * anything if the page scan parameters are already what they
1913 * should be.
1914 */
1915 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001916 write_fast_connectable(&req, false);
1917
Johan Hedberge8b12022014-07-10 10:51:27 +03001918 /* Update the advertising parameters if necessary */
1919 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001920 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001921
Johan Hedberg2b76f452013-03-15 17:07:04 -05001922 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001923 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001924 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001925 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001926 err = set_connectable_update_settings(hdev, sk,
1927 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001928 goto failed;
1929 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001930
1931failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001932 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001933 return err;
1934}
1935
Johan Hedbergb2939472014-07-30 09:22:23 +03001936static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001937 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001938{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001939 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001940 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001941 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001942
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001943 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001944
Johan Hedberga7e80f22013-01-09 16:05:19 +02001945 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001946 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001947 MGMT_STATUS_INVALID_PARAMS);
1948
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001949 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001950
1951 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001952 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001953 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001954 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001955
Johan Hedbergb2939472014-07-30 09:22:23 +03001956 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001958 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001959
Marcel Holtmann55594352013-10-06 16:11:57 -07001960 if (changed)
1961 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001962
Marcel Holtmann55594352013-10-06 16:11:57 -07001963unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001964 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001965 return err;
1966}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001967
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001968static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1969 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001970{
1971 struct mgmt_mode *cp = data;
1972 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001973 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001974 int err;
1975
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001976 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001977
Johan Hedberge6fe7982013-10-02 15:45:22 +03001978 status = mgmt_bredr_support(hdev);
1979 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001980 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001981 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001982
Johan Hedberga7e80f22013-01-09 16:05:19 +02001983 if (cp->val != 0x00 && cp->val != 0x01)
1984 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1985 MGMT_STATUS_INVALID_PARAMS);
1986
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001987 hci_dev_lock(hdev);
1988
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001989 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001990 bool changed = false;
1991
1992 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001993 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001994 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1995 changed = true;
1996 }
1997
1998 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1999 if (err < 0)
2000 goto failed;
2001
2002 if (changed)
2003 err = new_settings(hdev, sk);
2004
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002005 goto failed;
2006 }
2007
2008 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002009 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002010 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002011 goto failed;
2012 }
2013
2014 val = !!cp->val;
2015
2016 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2017 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2018 goto failed;
2019 }
2020
2021 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2022 if (!cmd) {
2023 err = -ENOMEM;
2024 goto failed;
2025 }
2026
2027 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2028 if (err < 0) {
2029 mgmt_pending_remove(cmd);
2030 goto failed;
2031 }
2032
2033failed:
2034 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002035 return err;
2036}
2037
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002038static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002039{
2040 struct mgmt_mode *cp = data;
2041 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002042 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002043 int err;
2044
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002045 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002046
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002047 status = mgmt_bredr_support(hdev);
2048 if (status)
2049 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2050
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002051 if (!lmp_ssp_capable(hdev))
2052 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2053 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002054
Johan Hedberga7e80f22013-01-09 16:05:19 +02002055 if (cp->val != 0x00 && cp->val != 0x01)
2056 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2057 MGMT_STATUS_INVALID_PARAMS);
2058
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002059 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002060
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002061 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002062 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002063
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002064 if (cp->val) {
2065 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2066 &hdev->dev_flags);
2067 } else {
2068 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2069 &hdev->dev_flags);
2070 if (!changed)
2071 changed = test_and_clear_bit(HCI_HS_ENABLED,
2072 &hdev->dev_flags);
2073 else
2074 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002075 }
2076
2077 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2078 if (err < 0)
2079 goto failed;
2080
2081 if (changed)
2082 err = new_settings(hdev, sk);
2083
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002084 goto failed;
2085 }
2086
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002087 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2088 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002089 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2090 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002091 goto failed;
2092 }
2093
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002094 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002095 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2096 goto failed;
2097 }
2098
2099 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2100 if (!cmd) {
2101 err = -ENOMEM;
2102 goto failed;
2103 }
2104
Johan Hedberg37699722014-06-24 14:00:27 +03002105 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2106 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2107 sizeof(cp->val), &cp->val);
2108
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002109 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002110 if (err < 0) {
2111 mgmt_pending_remove(cmd);
2112 goto failed;
2113 }
2114
2115failed:
2116 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002117 return err;
2118}
2119
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002120static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002121{
2122 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002123 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002124 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002125 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002126
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002127 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002128
Johan Hedberge6fe7982013-10-02 15:45:22 +03002129 status = mgmt_bredr_support(hdev);
2130 if (status)
2131 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002132
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002133 if (!lmp_ssp_capable(hdev))
2134 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2135 MGMT_STATUS_NOT_SUPPORTED);
2136
2137 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2138 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2139 MGMT_STATUS_REJECTED);
2140
Johan Hedberga7e80f22013-01-09 16:05:19 +02002141 if (cp->val != 0x00 && cp->val != 0x01)
2142 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2143 MGMT_STATUS_INVALID_PARAMS);
2144
Marcel Holtmannee392692013-10-01 22:59:23 -07002145 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002146
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002147 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002148 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002149 } else {
2150 if (hdev_is_powered(hdev)) {
2151 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2152 MGMT_STATUS_REJECTED);
2153 goto unlock;
2154 }
2155
Marcel Holtmannee392692013-10-01 22:59:23 -07002156 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002157 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002158
2159 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2160 if (err < 0)
2161 goto unlock;
2162
2163 if (changed)
2164 err = new_settings(hdev, sk);
2165
2166unlock:
2167 hci_dev_unlock(hdev);
2168 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002169}
2170
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002171static void le_enable_complete(struct hci_dev *hdev, u8 status)
2172{
2173 struct cmd_lookup match = { NULL, hdev };
2174
2175 if (status) {
2176 u8 mgmt_err = mgmt_status(status);
2177
2178 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2179 &mgmt_err);
2180 return;
2181 }
2182
2183 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2184
2185 new_settings(hdev, match.sk);
2186
2187 if (match.sk)
2188 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002189
2190 /* Make sure the controller has a good default for
2191 * advertising data. Restrict the update to when LE
2192 * has actually been enabled. During power on, the
2193 * update in powered_update_hci will take care of it.
2194 */
2195 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2196 struct hci_request req;
2197
2198 hci_dev_lock(hdev);
2199
2200 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002201 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002202 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002203 hci_req_run(&req, NULL);
2204
Johan Hedberga70f4b52014-07-07 15:19:50 +03002205 hci_update_background_scan(hdev);
2206
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002207 hci_dev_unlock(hdev);
2208 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002209}
2210
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002211static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002212{
2213 struct mgmt_mode *cp = data;
2214 struct hci_cp_write_le_host_supported hci_cp;
2215 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002216 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002217 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002218 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002219
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002220 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002221
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002222 if (!lmp_le_capable(hdev))
2223 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2224 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002225
Johan Hedberga7e80f22013-01-09 16:05:19 +02002226 if (cp->val != 0x00 && cp->val != 0x01)
2227 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2228 MGMT_STATUS_INVALID_PARAMS);
2229
Johan Hedbergc73eee92013-04-19 18:35:21 +03002230 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002231 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002232 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2233 MGMT_STATUS_REJECTED);
2234
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002235 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002236
2237 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002238 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002240 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002241 bool changed = false;
2242
2243 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2244 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2245 changed = true;
2246 }
2247
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002248 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2249 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002250 changed = true;
2251 }
2252
Johan Hedberg06199cf2012-02-22 16:37:11 +02002253 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2254 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002255 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002256
2257 if (changed)
2258 err = new_settings(hdev, sk);
2259
Johan Hedberg1de028c2012-02-29 19:55:35 -08002260 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002261 }
2262
Johan Hedberg4375f102013-09-25 13:26:10 +03002263 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2264 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002265 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002266 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002267 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268 }
2269
2270 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2271 if (!cmd) {
2272 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002273 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002274 }
2275
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002276 hci_req_init(&req, hdev);
2277
Johan Hedberg06199cf2012-02-22 16:37:11 +02002278 memset(&hci_cp, 0, sizeof(hci_cp));
2279
2280 if (val) {
2281 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002282 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002283 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002284 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002285 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002286 }
2287
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002288 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2289 &hci_cp);
2290
2291 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302292 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002293 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002294
Johan Hedberg1de028c2012-02-29 19:55:35 -08002295unlock:
2296 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002297 return err;
2298}
2299
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002300/* This is a helper function to test for pending mgmt commands that can
2301 * cause CoD or EIR HCI commands. We can only allow one such pending
2302 * mgmt command at a time since otherwise we cannot easily track what
2303 * the current values are, will be, and based on that calculate if a new
2304 * HCI command needs to be sent and if yes with what value.
2305 */
2306static bool pending_eir_or_class(struct hci_dev *hdev)
2307{
2308 struct pending_cmd *cmd;
2309
2310 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2311 switch (cmd->opcode) {
2312 case MGMT_OP_ADD_UUID:
2313 case MGMT_OP_REMOVE_UUID:
2314 case MGMT_OP_SET_DEV_CLASS:
2315 case MGMT_OP_SET_POWERED:
2316 return true;
2317 }
2318 }
2319
2320 return false;
2321}
2322
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002323static const u8 bluetooth_base_uuid[] = {
2324 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2325 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2326};
2327
2328static u8 get_uuid_size(const u8 *uuid)
2329{
2330 u32 val;
2331
2332 if (memcmp(uuid, bluetooth_base_uuid, 12))
2333 return 128;
2334
2335 val = get_unaligned_le32(&uuid[12]);
2336 if (val > 0xffff)
2337 return 32;
2338
2339 return 16;
2340}
2341
Johan Hedberg92da6092013-03-15 17:06:55 -05002342static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2343{
2344 struct pending_cmd *cmd;
2345
2346 hci_dev_lock(hdev);
2347
2348 cmd = mgmt_pending_find(mgmt_op, hdev);
2349 if (!cmd)
2350 goto unlock;
2351
2352 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2353 hdev->dev_class, 3);
2354
2355 mgmt_pending_remove(cmd);
2356
2357unlock:
2358 hci_dev_unlock(hdev);
2359}
2360
2361static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2362{
2363 BT_DBG("status 0x%02x", status);
2364
2365 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2366}
2367
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002368static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002369{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002370 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002371 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002372 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002373 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002374 int err;
2375
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002376 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002378 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002379
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002380 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002381 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002382 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002383 goto failed;
2384 }
2385
Andre Guedes92c4c202012-06-07 19:05:44 -03002386 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002387 if (!uuid) {
2388 err = -ENOMEM;
2389 goto failed;
2390 }
2391
2392 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002393 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002394 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002395
Johan Hedbergde66aa62013-01-27 00:31:27 +02002396 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002397
Johan Hedberg890ea892013-03-15 17:06:52 -05002398 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002399
Johan Hedberg890ea892013-03-15 17:06:52 -05002400 update_class(&req);
2401 update_eir(&req);
2402
Johan Hedberg92da6092013-03-15 17:06:55 -05002403 err = hci_req_run(&req, add_uuid_complete);
2404 if (err < 0) {
2405 if (err != -ENODATA)
2406 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002407
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002410 goto failed;
2411 }
2412
2413 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002414 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002415 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002416 goto failed;
2417 }
2418
2419 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002420
2421failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002422 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002423 return err;
2424}
2425
Johan Hedberg24b78d02012-02-23 23:24:30 +02002426static bool enable_service_cache(struct hci_dev *hdev)
2427{
2428 if (!hdev_is_powered(hdev))
2429 return false;
2430
2431 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002432 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2433 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002434 return true;
2435 }
2436
2437 return false;
2438}
2439
Johan Hedberg92da6092013-03-15 17:06:55 -05002440static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2441{
2442 BT_DBG("status 0x%02x", status);
2443
2444 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2445}
2446
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002447static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002448 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002449{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002450 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002451 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002452 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002453 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 -05002454 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002455 int err, found;
2456
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002457 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002458
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002459 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002460
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002461 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002462 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002463 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002464 goto unlock;
2465 }
2466
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002467 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002468 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002469
Johan Hedberg24b78d02012-02-23 23:24:30 +02002470 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002471 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002472 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002473 goto unlock;
2474 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002475
Johan Hedberg9246a862012-02-23 21:33:16 +02002476 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002477 }
2478
2479 found = 0;
2480
Johan Hedberg056341c2013-01-27 00:31:30 +02002481 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2483 continue;
2484
2485 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002486 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487 found++;
2488 }
2489
2490 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002491 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002492 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002493 goto unlock;
2494 }
2495
Johan Hedberg9246a862012-02-23 21:33:16 +02002496update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002497 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002498
Johan Hedberg890ea892013-03-15 17:06:52 -05002499 update_class(&req);
2500 update_eir(&req);
2501
Johan Hedberg92da6092013-03-15 17:06:55 -05002502 err = hci_req_run(&req, remove_uuid_complete);
2503 if (err < 0) {
2504 if (err != -ENODATA)
2505 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002506
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002507 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002508 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002509 goto unlock;
2510 }
2511
2512 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002513 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002514 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002515 goto unlock;
2516 }
2517
2518 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002519
2520unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002521 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002522 return err;
2523}
2524
Johan Hedberg92da6092013-03-15 17:06:55 -05002525static void set_class_complete(struct hci_dev *hdev, u8 status)
2526{
2527 BT_DBG("status 0x%02x", status);
2528
2529 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2530}
2531
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002532static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002533 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002534{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002535 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002537 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002538 int err;
2539
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002540 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002541
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002542 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002543 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2544 MGMT_STATUS_NOT_SUPPORTED);
2545
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002546 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002547
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002548 if (pending_eir_or_class(hdev)) {
2549 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2550 MGMT_STATUS_BUSY);
2551 goto unlock;
2552 }
2553
2554 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2555 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2556 MGMT_STATUS_INVALID_PARAMS);
2557 goto unlock;
2558 }
2559
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002560 hdev->major_class = cp->major;
2561 hdev->minor_class = cp->minor;
2562
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002563 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002564 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002565 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002566 goto unlock;
2567 }
2568
Johan Hedberg890ea892013-03-15 17:06:52 -05002569 hci_req_init(&req, hdev);
2570
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002571 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002572 hci_dev_unlock(hdev);
2573 cancel_delayed_work_sync(&hdev->service_cache);
2574 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002575 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002576 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002577
Johan Hedberg890ea892013-03-15 17:06:52 -05002578 update_class(&req);
2579
Johan Hedberg92da6092013-03-15 17:06:55 -05002580 err = hci_req_run(&req, set_class_complete);
2581 if (err < 0) {
2582 if (err != -ENODATA)
2583 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002584
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002585 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002586 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002587 goto unlock;
2588 }
2589
2590 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002591 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002592 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002593 goto unlock;
2594 }
2595
2596 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002597
Johan Hedbergb5235a62012-02-21 14:32:24 +02002598unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002599 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002600 return err;
2601}
2602
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002603static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002604 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002605{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002606 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002607 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2608 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002609 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002610 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002611 int i;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002612
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002613 BT_DBG("request for %s", hdev->name);
2614
2615 if (!lmp_bredr_capable(hdev))
2616 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2617 MGMT_STATUS_NOT_SUPPORTED);
2618
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002619 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002620 if (key_count > max_key_count) {
2621 BT_ERR("load_link_keys: too big key_count value %u",
2622 key_count);
2623 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2624 MGMT_STATUS_INVALID_PARAMS);
2625 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002626
Johan Hedberg86742e12011-11-07 23:13:38 +02002627 expected_len = sizeof(*cp) + key_count *
2628 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002629 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002630 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002631 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002632 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002633 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002634 }
2635
Johan Hedberg4ae14302013-01-20 14:27:13 +02002636 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2637 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2638 MGMT_STATUS_INVALID_PARAMS);
2639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002640 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002641 key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002642
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002643 for (i = 0; i < key_count; i++) {
2644 struct mgmt_link_key_info *key = &cp->keys[i];
2645
Marcel Holtmann8e991132014-01-10 02:07:25 -08002646 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002647 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2648 MGMT_STATUS_INVALID_PARAMS);
2649 }
2650
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002651 hci_dev_lock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002652
2653 hci_link_keys_clear(hdev);
2654
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002655 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002656 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2657 &hdev->dev_flags);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002658 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002659 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2660 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002661
2662 if (changed)
2663 new_settings(hdev, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002664
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002665 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002666 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002667
Johan Hedberg58e92932014-06-24 14:00:26 +03002668 /* Always ignore debug keys and require a new pairing if
2669 * the user wants to use them.
2670 */
2671 if (key->type == HCI_LK_DEBUG_COMBINATION)
2672 continue;
2673
Johan Hedberg7652ff62014-06-24 13:15:49 +03002674 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2675 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002676 }
2677
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002678 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002679
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002680 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002681
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002682 return 0;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002683}
2684
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002685static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002686 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002687{
2688 struct mgmt_ev_device_unpaired ev;
2689
2690 bacpy(&ev.addr.bdaddr, bdaddr);
2691 ev.addr.type = addr_type;
2692
2693 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002694 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002695}
2696
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002697static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002698 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002699{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002700 struct mgmt_cp_unpair_device *cp = data;
2701 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002702 struct hci_cp_disconnect dc;
2703 struct pending_cmd *cmd;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002704 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002705 int err;
2706
Johan Hedberga8a1d192011-11-10 15:54:38 +02002707 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002708 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2709 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002710
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002711 if (!bdaddr_type_is_valid(cp->addr.type))
2712 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2713 MGMT_STATUS_INVALID_PARAMS,
2714 &rp, sizeof(rp));
2715
Johan Hedberg118da702013-01-20 14:27:20 +02002716 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2717 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2718 MGMT_STATUS_INVALID_PARAMS,
2719 &rp, sizeof(rp));
2720
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002721 hci_dev_lock(hdev);
2722
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002723 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002726 goto unlock;
2727 }
2728
Johan Hedberge0b2b272014-02-18 17:14:31 +02002729 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002730 /* If disconnection is requested, then look up the
2731 * connection. If the remote device is connected, it
2732 * will be later used to terminate the link.
2733 *
2734 * Setting it to NULL explicitly will cause no
2735 * termination of the link.
2736 */
2737 if (cp->disconnect)
2738 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2739 &cp->addr.bdaddr);
2740 else
2741 conn = NULL;
2742
Johan Hedberg124f6e32012-02-09 13:50:12 +02002743 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002744 } else {
2745 u8 addr_type;
2746
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002747 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2748 &cp->addr.bdaddr);
2749 if (conn) {
2750 /* Defer clearing up the connection parameters
2751 * until closing to give a chance of keeping
2752 * them if a repairing happens.
2753 */
2754 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2755
2756 /* If disconnection is not requested, then
2757 * clear the connection variable so that the
2758 * link is not terminated.
2759 */
2760 if (!cp->disconnect)
2761 conn = NULL;
2762 }
2763
Johan Hedberge0b2b272014-02-18 17:14:31 +02002764 if (cp->addr.type == BDADDR_LE_PUBLIC)
2765 addr_type = ADDR_LE_DEV_PUBLIC;
2766 else
2767 addr_type = ADDR_LE_DEV_RANDOM;
2768
Johan Hedberga7ec7332014-02-18 17:14:35 +02002769 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2770
Johan Hedberge0b2b272014-02-18 17:14:31 +02002771 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2772 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002773
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002774 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002775 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002776 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002777 goto unlock;
2778 }
2779
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002780 /* If the connection variable is set, then termination of the
2781 * link is requested.
2782 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002783 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002784 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002785 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002786 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002787 goto unlock;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002788 }
2789
Johan Hedberg124f6e32012-02-09 13:50:12 +02002790 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002791 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002792 if (!cmd) {
2793 err = -ENOMEM;
2794 goto unlock;
2795 }
2796
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002797 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002798 dc.reason = 0x13; /* Remote User Terminated Connection */
2799 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2800 if (err < 0)
2801 mgmt_pending_remove(cmd);
2802
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002803unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002804 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002805 return err;
2806}
2807
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002808static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002809 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002810{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002811 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002812 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002813 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002814 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002815 int err;
2816
2817 BT_DBG("");
2818
Johan Hedberg06a63b12013-01-20 14:27:21 +02002819 memset(&rp, 0, sizeof(rp));
2820 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2821 rp.addr.type = cp->addr.type;
2822
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002823 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002824 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2825 MGMT_STATUS_INVALID_PARAMS,
2826 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002827
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002828 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002829
2830 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002831 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2832 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002833 goto failed;
2834 }
2835
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002836 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002837 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2838 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002839 goto failed;
2840 }
2841
Andre Guedes591f47f2012-04-24 21:02:49 -03002842 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002843 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2844 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002845 else
2846 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002847
Vishal Agarwalf9607272012-06-13 05:32:43 +05302848 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002849 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2850 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002851 goto failed;
2852 }
2853
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002854 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002855 if (!cmd) {
2856 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002857 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002858 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002859
Johan Hedberge3f2f922014-08-18 20:33:33 +03002860 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002861 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002862 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002863
2864failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002865 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002866 return err;
2867}
2868
Andre Guedes57c14772012-04-24 21:02:50 -03002869static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002870{
2871 switch (link_type) {
2872 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002873 switch (addr_type) {
2874 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002875 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002876
Johan Hedberg48264f02011-11-09 13:58:58 +02002877 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002878 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002879 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002880 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002881
Johan Hedberg4c659c32011-11-07 23:13:39 +02002882 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002883 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002884 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002885 }
2886}
2887
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002888static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2889 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002890{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002891 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002892 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002893 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002894 int err;
2895 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002896
2897 BT_DBG("");
2898
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002899 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002900
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002901 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002902 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002903 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002904 goto unlock;
2905 }
2906
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002907 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002908 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2909 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002910 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002911 }
2912
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002913 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002914 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002915 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002916 err = -ENOMEM;
2917 goto unlock;
2918 }
2919
Johan Hedberg2784eb42011-01-21 13:56:35 +02002920 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002921 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002922 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2923 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002924 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002925 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002926 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002927 continue;
2928 i++;
2929 }
2930
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002931 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002932
Johan Hedberg4c659c32011-11-07 23:13:39 +02002933 /* Recalculate length in case of filtered SCO connections, etc */
2934 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002935
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002936 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002937 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002938
Johan Hedberga38528f2011-01-22 06:46:43 +02002939 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002940
2941unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002942 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002943 return err;
2944}
2945
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002946static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002947 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002948{
2949 struct pending_cmd *cmd;
2950 int err;
2951
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002952 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002953 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002954 if (!cmd)
2955 return -ENOMEM;
2956
Johan Hedbergd8457692012-02-17 14:24:57 +02002957 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002958 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002959 if (err < 0)
2960 mgmt_pending_remove(cmd);
2961
2962 return err;
2963}
2964
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002965static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002966 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002967{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002968 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002969 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002970 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002971 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002972 int err;
2973
2974 BT_DBG("");
2975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002976 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002977
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002978 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002979 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002980 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002981 goto failed;
2982 }
2983
Johan Hedbergd8457692012-02-17 14:24:57 +02002984 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002985 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002986 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002987 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002988 goto failed;
2989 }
2990
2991 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002992 struct mgmt_cp_pin_code_neg_reply ncp;
2993
2994 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002995
2996 BT_ERR("PIN code is not 16 bytes long");
2997
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002998 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002999 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003000 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003001 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003002
3003 goto failed;
3004 }
3005
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003006 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003007 if (!cmd) {
3008 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003009 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003010 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003011
Johan Hedbergd8457692012-02-17 14:24:57 +02003012 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003013 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003014 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003015
3016 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3017 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003018 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003019
3020failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003021 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003022 return err;
3023}
3024
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003025static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3026 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003027{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003028 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003029
3030 BT_DBG("");
3031
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003032 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3033 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3034 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3035
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003036 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003037
3038 hdev->io_capability = cp->io_capability;
3039
3040 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003041 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003042
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003043 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003044
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003045 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3046 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003047}
3048
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003049static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003050{
3051 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003052 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003053
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003054 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003055 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3056 continue;
3057
Johan Hedberge9a416b2011-02-19 12:05:56 -03003058 if (cmd->user_data != conn)
3059 continue;
3060
3061 return cmd;
3062 }
3063
3064 return NULL;
3065}
3066
3067static void pairing_complete(struct pending_cmd *cmd, u8 status)
3068{
3069 struct mgmt_rp_pair_device rp;
3070 struct hci_conn *conn = cmd->user_data;
3071
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003072 bacpy(&rp.addr.bdaddr, &conn->dst);
3073 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003074
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003075 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003076 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003077
3078 /* So we don't get further callbacks for this connection */
3079 conn->connect_cfm_cb = NULL;
3080 conn->security_cfm_cb = NULL;
3081 conn->disconn_cfm_cb = NULL;
3082
David Herrmann76a68ba2013-04-06 20:28:37 +02003083 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003084 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003085
Johan Hedberga664b5b2011-02-19 12:06:02 -03003086 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003087
3088 /* The device is paired so there is no need to remove
3089 * its connection parameters anymore.
3090 */
3091 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003092}
3093
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003094void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3095{
3096 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3097 struct pending_cmd *cmd;
3098
3099 cmd = find_pairing(conn);
3100 if (cmd)
3101 pairing_complete(cmd, status);
3102}
3103
Johan Hedberge9a416b2011-02-19 12:05:56 -03003104static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3105{
3106 struct pending_cmd *cmd;
3107
3108 BT_DBG("status %u", status);
3109
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003110 cmd = find_pairing(conn);
3111 if (!cmd)
3112 BT_DBG("Unable to find a pending command");
3113 else
Johan Hedberge2113262012-02-18 15:20:03 +02003114 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003115}
3116
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003117static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303118{
3119 struct pending_cmd *cmd;
3120
3121 BT_DBG("status %u", status);
3122
3123 if (!status)
3124 return;
3125
3126 cmd = find_pairing(conn);
3127 if (!cmd)
3128 BT_DBG("Unable to find a pending command");
3129 else
3130 pairing_complete(cmd, mgmt_status(status));
3131}
3132
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003133static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003134 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003135{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003136 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003137 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003138 struct pending_cmd *cmd;
3139 u8 sec_level, auth_type;
3140 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003141 int err;
3142
3143 BT_DBG("");
3144
Szymon Jancf950a30e2013-01-18 12:48:07 +01003145 memset(&rp, 0, sizeof(rp));
3146 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3147 rp.addr.type = cp->addr.type;
3148
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003149 if (!bdaddr_type_is_valid(cp->addr.type))
3150 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3151 MGMT_STATUS_INVALID_PARAMS,
3152 &rp, sizeof(rp));
3153
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003154 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3155 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3156 MGMT_STATUS_INVALID_PARAMS,
3157 &rp, sizeof(rp));
3158
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003159 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003160
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003161 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003162 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3163 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003164 goto unlock;
3165 }
3166
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003167 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003168 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003169
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003170 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003171 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3172 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003173 } else {
3174 u8 addr_type;
3175
3176 /* Convert from L2CAP channel address type to HCI address type
3177 */
3178 if (cp->addr.type == BDADDR_LE_PUBLIC)
3179 addr_type = ADDR_LE_DEV_PUBLIC;
3180 else
3181 addr_type = ADDR_LE_DEV_RANDOM;
3182
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003183 /* When pairing a new device, it is expected to remember
3184 * this device for future connections. Adding the connection
3185 * parameter information ahead of time allows tracking
3186 * of the slave preferred values and will speed up any
3187 * further connection establishment.
3188 *
3189 * If connection parameters already exist, then they
3190 * will be kept and this function does nothing.
3191 */
3192 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3193
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003194 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003195 sec_level, HCI_LE_CONN_TIMEOUT,
3196 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003197 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003198
Ville Tervo30e76272011-02-22 16:10:53 -03003199 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003200 int status;
3201
3202 if (PTR_ERR(conn) == -EBUSY)
3203 status = MGMT_STATUS_BUSY;
3204 else
3205 status = MGMT_STATUS_CONNECT_FAILED;
3206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003207 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003208 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003209 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003210 goto unlock;
3211 }
3212
3213 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003214 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003215 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003216 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003217 goto unlock;
3218 }
3219
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003220 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003221 if (!cmd) {
3222 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003223 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003224 goto unlock;
3225 }
3226
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003227 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003228 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003229 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003230 conn->security_cfm_cb = pairing_complete_cb;
3231 conn->disconn_cfm_cb = pairing_complete_cb;
3232 } else {
3233 conn->connect_cfm_cb = le_pairing_complete_cb;
3234 conn->security_cfm_cb = le_pairing_complete_cb;
3235 conn->disconn_cfm_cb = le_pairing_complete_cb;
3236 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003237
Johan Hedberge9a416b2011-02-19 12:05:56 -03003238 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003239 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003240
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003241 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003242 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003243 pairing_complete(cmd, 0);
3244
3245 err = 0;
3246
3247unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003248 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003249 return err;
3250}
3251
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003252static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3253 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003254{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003255 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003256 struct pending_cmd *cmd;
3257 struct hci_conn *conn;
3258 int err;
3259
3260 BT_DBG("");
3261
Johan Hedberg28424702012-02-02 04:02:29 +02003262 hci_dev_lock(hdev);
3263
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003264 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003265 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003266 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003267 goto unlock;
3268 }
3269
Johan Hedberg28424702012-02-02 04:02:29 +02003270 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3271 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003272 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003273 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003274 goto unlock;
3275 }
3276
3277 conn = cmd->user_data;
3278
3279 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003280 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003281 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003282 goto unlock;
3283 }
3284
3285 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3286
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003287 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003288 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003289unlock:
3290 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003291 return err;
3292}
3293
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003294static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003295 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003296 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003297{
Johan Hedberga5c29682011-02-19 12:05:57 -03003298 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003299 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003300 int err;
3301
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003302 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003303
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003304 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003305 err = cmd_complete(sk, hdev->id, mgmt_op,
3306 MGMT_STATUS_NOT_POWERED, addr,
3307 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003308 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003309 }
3310
Johan Hedberg1707c602013-03-15 17:07:15 -05003311 if (addr->type == BDADDR_BREDR)
3312 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003313 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003314 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003315
Johan Hedberg272d90d2012-02-09 15:26:12 +02003316 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003317 err = cmd_complete(sk, hdev->id, mgmt_op,
3318 MGMT_STATUS_NOT_CONNECTED, addr,
3319 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003320 goto done;
3321 }
3322
Johan Hedberg1707c602013-03-15 17:07:15 -05003323 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003324 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003325 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003326 err = cmd_complete(sk, hdev->id, mgmt_op,
3327 MGMT_STATUS_SUCCESS, addr,
3328 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003329 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003330 err = cmd_complete(sk, hdev->id, mgmt_op,
3331 MGMT_STATUS_FAILED, addr,
3332 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003333
Brian Gix47c15e22011-11-16 13:53:14 -08003334 goto done;
3335 }
3336
Johan Hedberg1707c602013-03-15 17:07:15 -05003337 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003338 if (!cmd) {
3339 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003340 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003341 }
3342
Brian Gix0df4c182011-11-16 13:53:13 -08003343 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003344 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3345 struct hci_cp_user_passkey_reply cp;
3346
Johan Hedberg1707c602013-03-15 17:07:15 -05003347 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003348 cp.passkey = passkey;
3349 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3350 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003351 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3352 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003353
Johan Hedberga664b5b2011-02-19 12:06:02 -03003354 if (err < 0)
3355 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003356
Brian Gix0df4c182011-11-16 13:53:13 -08003357done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003358 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003359 return err;
3360}
3361
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303362static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3363 void *data, u16 len)
3364{
3365 struct mgmt_cp_pin_code_neg_reply *cp = data;
3366
3367 BT_DBG("");
3368
Johan Hedberg1707c602013-03-15 17:07:15 -05003369 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303370 MGMT_OP_PIN_CODE_NEG_REPLY,
3371 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3372}
3373
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003374static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3375 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003376{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003377 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003378
3379 BT_DBG("");
3380
3381 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003382 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003383 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003384
Johan Hedberg1707c602013-03-15 17:07:15 -05003385 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003386 MGMT_OP_USER_CONFIRM_REPLY,
3387 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003388}
3389
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003390static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003391 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003392{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003393 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003394
3395 BT_DBG("");
3396
Johan Hedberg1707c602013-03-15 17:07:15 -05003397 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003398 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3399 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003400}
3401
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003402static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3403 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003404{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003405 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003406
3407 BT_DBG("");
3408
Johan Hedberg1707c602013-03-15 17:07:15 -05003409 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003410 MGMT_OP_USER_PASSKEY_REPLY,
3411 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003412}
3413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003414static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003415 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003416{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003417 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003418
3419 BT_DBG("");
3420
Johan Hedberg1707c602013-03-15 17:07:15 -05003421 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003422 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3423 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003424}
3425
Johan Hedberg13928972013-03-15 17:07:00 -05003426static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003427{
Johan Hedberg13928972013-03-15 17:07:00 -05003428 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003429 struct hci_cp_write_local_name cp;
3430
Johan Hedberg13928972013-03-15 17:07:00 -05003431 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003432
Johan Hedberg890ea892013-03-15 17:06:52 -05003433 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003434}
3435
Johan Hedberg13928972013-03-15 17:07:00 -05003436static void set_name_complete(struct hci_dev *hdev, u8 status)
3437{
3438 struct mgmt_cp_set_local_name *cp;
3439 struct pending_cmd *cmd;
3440
3441 BT_DBG("status 0x%02x", status);
3442
3443 hci_dev_lock(hdev);
3444
3445 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3446 if (!cmd)
3447 goto unlock;
3448
3449 cp = cmd->param;
3450
3451 if (status)
3452 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3453 mgmt_status(status));
3454 else
3455 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3456 cp, sizeof(*cp));
3457
3458 mgmt_pending_remove(cmd);
3459
3460unlock:
3461 hci_dev_unlock(hdev);
3462}
3463
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003464static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003465 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003466{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003467 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003468 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003469 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003470 int err;
3471
3472 BT_DBG("");
3473
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003474 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003475
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003476 /* If the old values are the same as the new ones just return a
3477 * direct command complete event.
3478 */
3479 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3480 !memcmp(hdev->short_name, cp->short_name,
3481 sizeof(hdev->short_name))) {
3482 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3483 data, len);
3484 goto failed;
3485 }
3486
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003487 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003488
Johan Hedbergb5235a62012-02-21 14:32:24 +02003489 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003490 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003491
3492 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003493 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003494 if (err < 0)
3495 goto failed;
3496
3497 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003498 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003499
Johan Hedbergb5235a62012-02-21 14:32:24 +02003500 goto failed;
3501 }
3502
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003503 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003504 if (!cmd) {
3505 err = -ENOMEM;
3506 goto failed;
3507 }
3508
Johan Hedberg13928972013-03-15 17:07:00 -05003509 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3510
Johan Hedberg890ea892013-03-15 17:06:52 -05003511 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003512
3513 if (lmp_bredr_capable(hdev)) {
3514 update_name(&req);
3515 update_eir(&req);
3516 }
3517
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003518 /* The name is stored in the scan response data and so
3519 * no need to udpate the advertising data here.
3520 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003521 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003522 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003523
Johan Hedberg13928972013-03-15 17:07:00 -05003524 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003525 if (err < 0)
3526 mgmt_pending_remove(cmd);
3527
3528failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003529 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003530 return err;
3531}
3532
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003533static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003534 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003535{
Szymon Jancc35938b2011-03-22 13:12:21 +01003536 struct pending_cmd *cmd;
3537 int err;
3538
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003539 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003540
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003541 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003542
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003543 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003544 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003545 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003546 goto unlock;
3547 }
3548
Andre Guedes9a1a1992012-07-24 15:03:48 -03003549 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003550 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003551 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003552 goto unlock;
3553 }
3554
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003555 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003556 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003557 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003558 goto unlock;
3559 }
3560
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003561 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003562 if (!cmd) {
3563 err = -ENOMEM;
3564 goto unlock;
3565 }
3566
Johan Hedberg710f11c2014-05-26 11:21:22 +03003567 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003568 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3569 0, NULL);
3570 else
3571 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3572
Szymon Jancc35938b2011-03-22 13:12:21 +01003573 if (err < 0)
3574 mgmt_pending_remove(cmd);
3575
3576unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003577 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003578 return err;
3579}
3580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003581static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003582 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003583{
Szymon Janc2763eda2011-03-22 13:12:22 +01003584 int err;
3585
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003586 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003587
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003588 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003589
Marcel Holtmannec109112014-01-10 02:07:30 -08003590 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3591 struct mgmt_cp_add_remote_oob_data *cp = data;
3592 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003593
Johan Hedbergc19a4952014-11-17 20:52:19 +02003594 if (cp->addr.type != BDADDR_BREDR) {
3595 err = cmd_complete(sk, hdev->id,
3596 MGMT_OP_ADD_REMOTE_OOB_DATA,
3597 MGMT_STATUS_INVALID_PARAMS,
3598 &cp->addr, sizeof(cp->addr));
3599 goto unlock;
3600 }
3601
Marcel Holtmannec109112014-01-10 02:07:30 -08003602 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003603 cp->addr.type, cp->hash,
3604 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003605 if (err < 0)
3606 status = MGMT_STATUS_FAILED;
3607 else
3608 status = MGMT_STATUS_SUCCESS;
3609
3610 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3611 status, &cp->addr, sizeof(cp->addr));
3612 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3613 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003614 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003615 u8 status;
3616
Johan Hedbergc19a4952014-11-17 20:52:19 +02003617 if (cp->addr.type != BDADDR_BREDR) {
3618 err = cmd_complete(sk, hdev->id,
3619 MGMT_OP_ADD_REMOTE_OOB_DATA,
3620 MGMT_STATUS_INVALID_PARAMS,
3621 &cp->addr, sizeof(cp->addr));
3622 goto unlock;
3623 }
3624
Johan Hedberg86df9202014-10-26 20:52:27 +01003625 if (bdaddr_type_is_le(cp->addr.type)) {
3626 rand192 = NULL;
3627 hash192 = NULL;
3628 } else {
3629 rand192 = cp->rand192;
3630 hash192 = cp->hash192;
3631 }
3632
Johan Hedberg81328d52014-10-26 20:33:47 +01003633 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003634 cp->addr.type, hash192, rand192,
3635 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003636 if (err < 0)
3637 status = MGMT_STATUS_FAILED;
3638 else
3639 status = MGMT_STATUS_SUCCESS;
3640
3641 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3642 status, &cp->addr, sizeof(cp->addr));
3643 } else {
3644 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3645 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3646 MGMT_STATUS_INVALID_PARAMS);
3647 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003648
Johan Hedbergc19a4952014-11-17 20:52:19 +02003649unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003650 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003651 return err;
3652}
3653
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003654static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003655 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003656{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003657 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003658 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003659 int err;
3660
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003661 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003662
Johan Hedbergc19a4952014-11-17 20:52:19 +02003663 if (cp->addr.type != BDADDR_BREDR)
3664 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3665 MGMT_STATUS_INVALID_PARAMS,
3666 &cp->addr, sizeof(cp->addr));
3667
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003668 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003669
Johan Hedbergeedbd582014-11-15 09:34:23 +02003670 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3671 hci_remote_oob_data_clear(hdev);
3672 status = MGMT_STATUS_SUCCESS;
3673 goto done;
3674 }
3675
Johan Hedberg6928a922014-10-26 20:46:09 +01003676 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003677 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003678 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003679 else
Szymon Janca6785be2012-12-13 15:11:21 +01003680 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003681
Johan Hedbergeedbd582014-11-15 09:34:23 +02003682done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003683 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003684 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003685
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003686 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003687 return err;
3688}
3689
Marcel Holtmann80190442014-12-04 11:36:36 +01003690static bool trigger_discovery(struct hci_request *req, u8 *status)
3691{
3692 struct hci_dev *hdev = req->hdev;
3693 struct hci_cp_le_set_scan_param param_cp;
3694 struct hci_cp_le_set_scan_enable enable_cp;
3695 struct hci_cp_inquiry inq_cp;
3696 /* General inquiry access code (GIAC) */
3697 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3698 u8 own_addr_type;
3699 int err;
3700
3701 switch (hdev->discovery.type) {
3702 case DISCOV_TYPE_BREDR:
3703 *status = mgmt_bredr_support(hdev);
3704 if (*status)
3705 return false;
3706
3707 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3708 *status = MGMT_STATUS_BUSY;
3709 return false;
3710 }
3711
3712 hci_inquiry_cache_flush(hdev);
3713
3714 memset(&inq_cp, 0, sizeof(inq_cp));
3715 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3716 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3717 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3718 break;
3719
3720 case DISCOV_TYPE_LE:
3721 case DISCOV_TYPE_INTERLEAVED:
3722 *status = mgmt_le_support(hdev);
3723 if (*status)
3724 return false;
3725
3726 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3727 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3728 *status = MGMT_STATUS_NOT_SUPPORTED;
3729 return false;
3730 }
3731
3732 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3733 /* Don't let discovery abort an outgoing
3734 * connection attempt that's using directed
3735 * advertising.
3736 */
3737 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3738 BT_CONNECT)) {
3739 *status = MGMT_STATUS_REJECTED;
3740 return false;
3741 }
3742
3743 disable_advertising(req);
3744 }
3745
3746 /* If controller is scanning, it means the background scanning
3747 * is running. Thus, we should temporarily stop it in order to
3748 * set the discovery scanning parameters.
3749 */
3750 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3751 hci_req_add_le_scan_disable(req);
3752
3753 memset(&param_cp, 0, sizeof(param_cp));
3754
3755 /* All active scans will be done with either a resolvable
3756 * private address (when privacy feature has been enabled)
3757 * or unresolvable private address.
3758 */
3759 err = hci_update_random_address(req, true, &own_addr_type);
3760 if (err < 0) {
3761 *status = MGMT_STATUS_FAILED;
3762 return false;
3763 }
3764
3765 param_cp.type = LE_SCAN_ACTIVE;
3766 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3767 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3768 param_cp.own_address_type = own_addr_type;
3769 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3770 &param_cp);
3771
3772 memset(&enable_cp, 0, sizeof(enable_cp));
3773 enable_cp.enable = LE_SCAN_ENABLE;
3774 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3775 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3776 &enable_cp);
3777 break;
3778
3779 default:
3780 *status = MGMT_STATUS_INVALID_PARAMS;
3781 return false;
3782 }
3783
3784 return true;
3785}
3786
Andre Guedes7c307722013-04-30 15:29:28 -03003787static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3788{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003789 struct pending_cmd *cmd;
3790 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003791
Andre Guedes7c307722013-04-30 15:29:28 -03003792 BT_DBG("status %d", status);
3793
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003794 hci_dev_lock(hdev);
3795
3796 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003797 if (!cmd)
3798 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3799
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003800 if (cmd) {
3801 u8 type = hdev->discovery.type;
3802
3803 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
3804 mgmt_status(status), &type, sizeof(type));
3805 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003806 }
3807
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003808 if (status) {
3809 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3810 goto unlock;
3811 }
3812
Andre Guedes7c307722013-04-30 15:29:28 -03003813 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003814
3815 switch (hdev->discovery.type) {
3816 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003817 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003818 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003819 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003820 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003821 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003822 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003823 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003824 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003825 default:
3826 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003827 timeout = 0;
3828 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003829 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003830
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003831 if (timeout)
3832 queue_delayed_work(hdev->workqueue,
3833 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003834
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003835unlock:
3836 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003837}
3838
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003839static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003840 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003841{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003842 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003843 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003844 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003845 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003846 int err;
3847
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003848 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003849
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003850 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003851
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003852 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003853 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3854 MGMT_STATUS_NOT_POWERED,
3855 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003856 goto failed;
3857 }
3858
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003859 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3860 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003861 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3862 MGMT_STATUS_BUSY, &cp->type,
3863 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003864 goto failed;
3865 }
3866
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003867 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003868 if (!cmd) {
3869 err = -ENOMEM;
3870 goto failed;
3871 }
3872
Marcel Holtmann22078802014-12-05 11:45:22 +01003873 /* Clear the discovery filter first to free any previously
3874 * allocated memory for the UUID list.
3875 */
3876 hci_discovery_filter_clear(hdev);
3877
Andre Guedes4aab14e2012-02-17 20:39:36 -03003878 hdev->discovery.type = cp->type;
3879
Andre Guedes7c307722013-04-30 15:29:28 -03003880 hci_req_init(&req, hdev);
3881
Marcel Holtmann80190442014-12-04 11:36:36 +01003882 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003883 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003884 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003885 mgmt_pending_remove(cmd);
3886 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003887 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003888
Andre Guedes7c307722013-04-30 15:29:28 -03003889 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003890 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003891 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003892 goto failed;
3893 }
3894
3895 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003896
3897failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003898 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003899 return err;
3900}
3901
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003902static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3903 void *data, u16 len)
3904{
3905 struct mgmt_cp_start_service_discovery *cp = data;
3906 struct pending_cmd *cmd;
3907 struct hci_request req;
3908 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3909 u16 uuid_count, expected_len;
3910 u8 status;
3911 int err;
3912
3913 BT_DBG("%s", hdev->name);
3914
3915 hci_dev_lock(hdev);
3916
3917 if (!hdev_is_powered(hdev)) {
3918 err = cmd_complete(sk, hdev->id,
3919 MGMT_OP_START_SERVICE_DISCOVERY,
3920 MGMT_STATUS_NOT_POWERED,
3921 &cp->type, sizeof(cp->type));
3922 goto failed;
3923 }
3924
3925 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3926 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3927 err = cmd_complete(sk, hdev->id,
3928 MGMT_OP_START_SERVICE_DISCOVERY,
3929 MGMT_STATUS_BUSY, &cp->type,
3930 sizeof(cp->type));
3931 goto failed;
3932 }
3933
3934 uuid_count = __le16_to_cpu(cp->uuid_count);
3935 if (uuid_count > max_uuid_count) {
3936 BT_ERR("service_discovery: too big uuid_count value %u",
3937 uuid_count);
3938 err = cmd_complete(sk, hdev->id,
3939 MGMT_OP_START_SERVICE_DISCOVERY,
3940 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3941 sizeof(cp->type));
3942 goto failed;
3943 }
3944
3945 expected_len = sizeof(*cp) + uuid_count * 16;
3946 if (expected_len != len) {
3947 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3948 expected_len, len);
3949 err = cmd_complete(sk, hdev->id,
3950 MGMT_OP_START_SERVICE_DISCOVERY,
3951 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3952 sizeof(cp->type));
3953 goto failed;
3954 }
3955
3956 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
3957 hdev, NULL, 0);
3958 if (!cmd) {
3959 err = -ENOMEM;
3960 goto failed;
3961 }
3962
Marcel Holtmann22078802014-12-05 11:45:22 +01003963 /* Clear the discovery filter first to free any previously
3964 * allocated memory for the UUID list.
3965 */
3966 hci_discovery_filter_clear(hdev);
3967
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003968 hdev->discovery.type = cp->type;
3969 hdev->discovery.rssi = cp->rssi;
3970 hdev->discovery.uuid_count = uuid_count;
3971
3972 if (uuid_count > 0) {
3973 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
3974 GFP_KERNEL);
3975 if (!hdev->discovery.uuids) {
3976 err = cmd_complete(sk, hdev->id,
3977 MGMT_OP_START_SERVICE_DISCOVERY,
3978 MGMT_STATUS_FAILED,
3979 &cp->type, sizeof(cp->type));
3980 mgmt_pending_remove(cmd);
3981 goto failed;
3982 }
3983 }
3984
3985 hci_req_init(&req, hdev);
3986
3987 if (!trigger_discovery(&req, &status)) {
3988 err = cmd_complete(sk, hdev->id,
3989 MGMT_OP_START_SERVICE_DISCOVERY,
3990 status, &cp->type, sizeof(cp->type));
3991 mgmt_pending_remove(cmd);
3992 goto failed;
3993 }
3994
3995 err = hci_req_run(&req, start_discovery_complete);
3996 if (err < 0) {
3997 mgmt_pending_remove(cmd);
3998 goto failed;
3999 }
4000
4001 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4002
4003failed:
4004 hci_dev_unlock(hdev);
4005 return err;
4006}
4007
Andre Guedes0e05bba2013-04-30 15:29:33 -03004008static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4009{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004010 struct pending_cmd *cmd;
4011
Andre Guedes0e05bba2013-04-30 15:29:33 -03004012 BT_DBG("status %d", status);
4013
4014 hci_dev_lock(hdev);
4015
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004016 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4017 if (cmd) {
4018 u8 type = hdev->discovery.type;
4019
4020 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
4021 mgmt_status(status), &type, sizeof(type));
4022 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004023 }
4024
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004025 if (!status)
4026 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004027
Andre Guedes0e05bba2013-04-30 15:29:33 -03004028 hci_dev_unlock(hdev);
4029}
4030
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004031static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004032 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004033{
Johan Hedbergd9306502012-02-20 23:25:18 +02004034 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004035 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004036 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004037 int err;
4038
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004039 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004040
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004041 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004042
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004043 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004044 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004045 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4046 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004047 goto unlock;
4048 }
4049
4050 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004051 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004052 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4053 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004054 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004055 }
4056
Johan Hedberg2e58ef32011-11-08 20:40:15 +02004057 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04004058 if (!cmd) {
4059 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004060 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004061 }
4062
Andre Guedes0e05bba2013-04-30 15:29:33 -03004063 hci_req_init(&req, hdev);
4064
Johan Hedberg21a60d32014-06-10 14:05:58 +03004065 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004066
Johan Hedberg21a60d32014-06-10 14:05:58 +03004067 err = hci_req_run(&req, stop_discovery_complete);
4068 if (!err) {
4069 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004070 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004071 }
4072
Johan Hedberg21a60d32014-06-10 14:05:58 +03004073 mgmt_pending_remove(cmd);
4074
4075 /* If no HCI commands were sent we're done */
4076 if (err == -ENODATA) {
4077 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4078 &mgmt_cp->type, sizeof(mgmt_cp->type));
4079 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4080 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004081
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004082unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004083 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004084 return err;
4085}
4086
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004087static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004088 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004089{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004090 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004091 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004092 int err;
4093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004094 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004095
Johan Hedberg561aafb2012-01-04 13:31:59 +02004096 hci_dev_lock(hdev);
4097
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004098 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004099 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4100 MGMT_STATUS_FAILED, &cp->addr,
4101 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004102 goto failed;
4103 }
4104
Johan Hedberga198e7b2012-02-17 14:27:06 +02004105 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004106 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004107 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4108 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4109 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004110 goto failed;
4111 }
4112
4113 if (cp->name_known) {
4114 e->name_state = NAME_KNOWN;
4115 list_del(&e->list);
4116 } else {
4117 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004118 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004119 }
4120
Johan Hedberge3846622013-01-09 15:29:33 +02004121 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4122 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004123
4124failed:
4125 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004126 return err;
4127}
4128
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004129static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004130 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004131{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004132 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004133 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004134 int err;
4135
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004136 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004137
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004138 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004139 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4140 MGMT_STATUS_INVALID_PARAMS,
4141 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004142
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004143 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004144
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004145 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4146 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004147 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004148 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004149 goto done;
4150 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004151
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004152 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4153 sk);
4154 status = MGMT_STATUS_SUCCESS;
4155
4156done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004157 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004158 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004159
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004160 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004161
4162 return err;
4163}
4164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004165static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004166 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004167{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004168 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004169 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004170 int err;
4171
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004172 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004173
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004174 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004175 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4176 MGMT_STATUS_INVALID_PARAMS,
4177 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004178
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004179 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004180
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004181 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4182 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004183 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004184 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004185 goto done;
4186 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004187
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004188 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4189 sk);
4190 status = MGMT_STATUS_SUCCESS;
4191
4192done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004193 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004194 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004195
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004196 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004197
4198 return err;
4199}
4200
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004201static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4202 u16 len)
4203{
4204 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004205 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004206 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004207 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004208
4209 BT_DBG("%s", hdev->name);
4210
Szymon Jancc72d4b82012-03-16 16:02:57 +01004211 source = __le16_to_cpu(cp->source);
4212
4213 if (source > 0x0002)
4214 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4215 MGMT_STATUS_INVALID_PARAMS);
4216
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004217 hci_dev_lock(hdev);
4218
Szymon Jancc72d4b82012-03-16 16:02:57 +01004219 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004220 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4221 hdev->devid_product = __le16_to_cpu(cp->product);
4222 hdev->devid_version = __le16_to_cpu(cp->version);
4223
4224 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4225
Johan Hedberg890ea892013-03-15 17:06:52 -05004226 hci_req_init(&req, hdev);
4227 update_eir(&req);
4228 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004229
4230 hci_dev_unlock(hdev);
4231
4232 return err;
4233}
4234
Johan Hedberg4375f102013-09-25 13:26:10 +03004235static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4236{
4237 struct cmd_lookup match = { NULL, hdev };
4238
4239 if (status) {
4240 u8 mgmt_err = mgmt_status(status);
4241
4242 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4243 cmd_status_rsp, &mgmt_err);
4244 return;
4245 }
4246
Johan Hedbergc93bd152014-07-08 15:07:48 +03004247 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4248 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4249 else
4250 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4251
Johan Hedberg4375f102013-09-25 13:26:10 +03004252 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4253 &match);
4254
4255 new_settings(hdev, match.sk);
4256
4257 if (match.sk)
4258 sock_put(match.sk);
4259}
4260
Marcel Holtmann21b51872013-10-10 09:47:53 -07004261static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4262 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004263{
4264 struct mgmt_mode *cp = data;
4265 struct pending_cmd *cmd;
4266 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004267 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004268 int err;
4269
4270 BT_DBG("request for %s", hdev->name);
4271
Johan Hedberge6fe7982013-10-02 15:45:22 +03004272 status = mgmt_le_support(hdev);
4273 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004274 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004275 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004276
4277 if (cp->val != 0x00 && cp->val != 0x01)
4278 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4279 MGMT_STATUS_INVALID_PARAMS);
4280
4281 hci_dev_lock(hdev);
4282
4283 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004284 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004285
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004286 /* The following conditions are ones which mean that we should
4287 * not do any HCI communication but directly send a mgmt
4288 * response to user space (after toggling the flag if
4289 * necessary).
4290 */
4291 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004292 hci_conn_num(hdev, LE_LINK) > 0 ||
4293 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4294 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004295 bool changed = false;
4296
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004297 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4298 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004299 changed = true;
4300 }
4301
4302 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4303 if (err < 0)
4304 goto unlock;
4305
4306 if (changed)
4307 err = new_settings(hdev, sk);
4308
4309 goto unlock;
4310 }
4311
4312 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4313 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4314 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4315 MGMT_STATUS_BUSY);
4316 goto unlock;
4317 }
4318
4319 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4320 if (!cmd) {
4321 err = -ENOMEM;
4322 goto unlock;
4323 }
4324
4325 hci_req_init(&req, hdev);
4326
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004327 if (val)
4328 enable_advertising(&req);
4329 else
4330 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004331
4332 err = hci_req_run(&req, set_advertising_complete);
4333 if (err < 0)
4334 mgmt_pending_remove(cmd);
4335
4336unlock:
4337 hci_dev_unlock(hdev);
4338 return err;
4339}
4340
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004341static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4342 void *data, u16 len)
4343{
4344 struct mgmt_cp_set_static_address *cp = data;
4345 int err;
4346
4347 BT_DBG("%s", hdev->name);
4348
Marcel Holtmann62af4442013-10-02 22:10:32 -07004349 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004350 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004351 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004352
4353 if (hdev_is_powered(hdev))
4354 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4355 MGMT_STATUS_REJECTED);
4356
4357 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4358 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4359 return cmd_status(sk, hdev->id,
4360 MGMT_OP_SET_STATIC_ADDRESS,
4361 MGMT_STATUS_INVALID_PARAMS);
4362
4363 /* Two most significant bits shall be set */
4364 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4365 return cmd_status(sk, hdev->id,
4366 MGMT_OP_SET_STATIC_ADDRESS,
4367 MGMT_STATUS_INVALID_PARAMS);
4368 }
4369
4370 hci_dev_lock(hdev);
4371
4372 bacpy(&hdev->static_addr, &cp->bdaddr);
4373
4374 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4375
4376 hci_dev_unlock(hdev);
4377
4378 return err;
4379}
4380
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004381static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4382 void *data, u16 len)
4383{
4384 struct mgmt_cp_set_scan_params *cp = data;
4385 __u16 interval, window;
4386 int err;
4387
4388 BT_DBG("%s", hdev->name);
4389
4390 if (!lmp_le_capable(hdev))
4391 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4392 MGMT_STATUS_NOT_SUPPORTED);
4393
4394 interval = __le16_to_cpu(cp->interval);
4395
4396 if (interval < 0x0004 || interval > 0x4000)
4397 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4398 MGMT_STATUS_INVALID_PARAMS);
4399
4400 window = __le16_to_cpu(cp->window);
4401
4402 if (window < 0x0004 || window > 0x4000)
4403 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4404 MGMT_STATUS_INVALID_PARAMS);
4405
Marcel Holtmann899e1072013-10-14 09:55:32 -07004406 if (window > interval)
4407 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4408 MGMT_STATUS_INVALID_PARAMS);
4409
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004410 hci_dev_lock(hdev);
4411
4412 hdev->le_scan_interval = interval;
4413 hdev->le_scan_window = window;
4414
4415 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4416
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004417 /* If background scan is running, restart it so new parameters are
4418 * loaded.
4419 */
4420 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4421 hdev->discovery.state == DISCOVERY_STOPPED) {
4422 struct hci_request req;
4423
4424 hci_req_init(&req, hdev);
4425
4426 hci_req_add_le_scan_disable(&req);
4427 hci_req_add_le_passive_scan(&req);
4428
4429 hci_req_run(&req, NULL);
4430 }
4431
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004432 hci_dev_unlock(hdev);
4433
4434 return err;
4435}
4436
Johan Hedberg33e38b32013-03-15 17:07:05 -05004437static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4438{
4439 struct pending_cmd *cmd;
4440
4441 BT_DBG("status 0x%02x", status);
4442
4443 hci_dev_lock(hdev);
4444
4445 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4446 if (!cmd)
4447 goto unlock;
4448
4449 if (status) {
4450 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4451 mgmt_status(status));
4452 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004453 struct mgmt_mode *cp = cmd->param;
4454
4455 if (cp->val)
4456 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4457 else
4458 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4459
Johan Hedberg33e38b32013-03-15 17:07:05 -05004460 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4461 new_settings(hdev, cmd->sk);
4462 }
4463
4464 mgmt_pending_remove(cmd);
4465
4466unlock:
4467 hci_dev_unlock(hdev);
4468}
4469
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004470static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004471 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004472{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004473 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004474 struct pending_cmd *cmd;
4475 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004476 int err;
4477
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004478 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004479
Johan Hedberg56f87902013-10-02 13:43:13 +03004480 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4481 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004482 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4483 MGMT_STATUS_NOT_SUPPORTED);
4484
Johan Hedberga7e80f22013-01-09 16:05:19 +02004485 if (cp->val != 0x00 && cp->val != 0x01)
4486 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4487 MGMT_STATUS_INVALID_PARAMS);
4488
Johan Hedberg5400c042012-02-21 16:40:33 +02004489 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004490 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004491 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004492
4493 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004494 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004495 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004496
4497 hci_dev_lock(hdev);
4498
Johan Hedberg05cbf292013-03-15 17:07:07 -05004499 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4500 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4501 MGMT_STATUS_BUSY);
4502 goto unlock;
4503 }
4504
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004505 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4506 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4507 hdev);
4508 goto unlock;
4509 }
4510
Johan Hedberg33e38b32013-03-15 17:07:05 -05004511 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4512 data, len);
4513 if (!cmd) {
4514 err = -ENOMEM;
4515 goto unlock;
4516 }
4517
4518 hci_req_init(&req, hdev);
4519
Johan Hedberg406d7802013-03-15 17:07:09 -05004520 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004521
4522 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004523 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004524 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004525 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004526 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004527 }
4528
Johan Hedberg33e38b32013-03-15 17:07:05 -05004529unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004530 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004531
Antti Julkuf6422ec2011-06-22 13:11:56 +03004532 return err;
4533}
4534
Johan Hedberg0663ca22013-10-02 13:43:14 +03004535static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4536{
4537 struct pending_cmd *cmd;
4538
4539 BT_DBG("status 0x%02x", status);
4540
4541 hci_dev_lock(hdev);
4542
4543 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4544 if (!cmd)
4545 goto unlock;
4546
4547 if (status) {
4548 u8 mgmt_err = mgmt_status(status);
4549
4550 /* We need to restore the flag if related HCI commands
4551 * failed.
4552 */
4553 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4554
4555 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4556 } else {
4557 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4558 new_settings(hdev, cmd->sk);
4559 }
4560
4561 mgmt_pending_remove(cmd);
4562
4563unlock:
4564 hci_dev_unlock(hdev);
4565}
4566
4567static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4568{
4569 struct mgmt_mode *cp = data;
4570 struct pending_cmd *cmd;
4571 struct hci_request req;
4572 int err;
4573
4574 BT_DBG("request for %s", hdev->name);
4575
4576 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4577 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4578 MGMT_STATUS_NOT_SUPPORTED);
4579
4580 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4581 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4582 MGMT_STATUS_REJECTED);
4583
4584 if (cp->val != 0x00 && cp->val != 0x01)
4585 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4586 MGMT_STATUS_INVALID_PARAMS);
4587
4588 hci_dev_lock(hdev);
4589
4590 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4591 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4592 goto unlock;
4593 }
4594
4595 if (!hdev_is_powered(hdev)) {
4596 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004597 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4598 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4599 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4600 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4601 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4602 }
4603
4604 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4605
4606 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4607 if (err < 0)
4608 goto unlock;
4609
4610 err = new_settings(hdev, sk);
4611 goto unlock;
4612 }
4613
4614 /* Reject disabling when powered on */
4615 if (!cp->val) {
4616 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4617 MGMT_STATUS_REJECTED);
4618 goto unlock;
4619 }
4620
4621 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4622 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4623 MGMT_STATUS_BUSY);
4624 goto unlock;
4625 }
4626
4627 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4628 if (!cmd) {
4629 err = -ENOMEM;
4630 goto unlock;
4631 }
4632
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004633 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004634 * generates the correct flags.
4635 */
4636 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4637
4638 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004639
Johan Hedberg432df052014-08-01 11:13:31 +03004640 write_fast_connectable(&req, false);
4641 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004642
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004643 /* Since only the advertising data flags will change, there
4644 * is no need to update the scan response data.
4645 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004646 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004647
Johan Hedberg0663ca22013-10-02 13:43:14 +03004648 err = hci_req_run(&req, set_bredr_complete);
4649 if (err < 0)
4650 mgmt_pending_remove(cmd);
4651
4652unlock:
4653 hci_dev_unlock(hdev);
4654 return err;
4655}
4656
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004657static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4658 void *data, u16 len)
4659{
4660 struct mgmt_mode *cp = data;
4661 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004662 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004663 int err;
4664
4665 BT_DBG("request for %s", hdev->name);
4666
Johan Hedberga3209692014-05-26 11:23:35 +03004667 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4668 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004669 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4670 MGMT_STATUS_NOT_SUPPORTED);
4671
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004672 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004673 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4674 MGMT_STATUS_INVALID_PARAMS);
4675
4676 hci_dev_lock(hdev);
4677
Johan Hedberga3209692014-05-26 11:23:35 +03004678 if (!hdev_is_powered(hdev) ||
4679 (!lmp_sc_capable(hdev) &&
4680 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4681 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004682 bool changed;
4683
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004684 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004685 changed = !test_and_set_bit(HCI_SC_ENABLED,
4686 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004687 if (cp->val == 0x02)
4688 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4689 else
4690 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4691 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004692 changed = test_and_clear_bit(HCI_SC_ENABLED,
4693 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004694 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4695 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004696
4697 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4698 if (err < 0)
4699 goto failed;
4700
4701 if (changed)
4702 err = new_settings(hdev, sk);
4703
4704 goto failed;
4705 }
4706
4707 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4708 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4709 MGMT_STATUS_BUSY);
4710 goto failed;
4711 }
4712
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004713 val = !!cp->val;
4714
4715 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4716 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004717 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4718 goto failed;
4719 }
4720
4721 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4722 if (!cmd) {
4723 err = -ENOMEM;
4724 goto failed;
4725 }
4726
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004727 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004728 if (err < 0) {
4729 mgmt_pending_remove(cmd);
4730 goto failed;
4731 }
4732
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004733 if (cp->val == 0x02)
4734 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4735 else
4736 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4737
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004738failed:
4739 hci_dev_unlock(hdev);
4740 return err;
4741}
4742
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004743static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4744 void *data, u16 len)
4745{
4746 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004747 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004748 int err;
4749
4750 BT_DBG("request for %s", hdev->name);
4751
Johan Hedbergb97109792014-06-24 14:00:28 +03004752 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004753 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4754 MGMT_STATUS_INVALID_PARAMS);
4755
4756 hci_dev_lock(hdev);
4757
4758 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004759 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4760 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004761 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004762 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4763 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004764
Johan Hedbergb97109792014-06-24 14:00:28 +03004765 if (cp->val == 0x02)
4766 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4767 &hdev->dev_flags);
4768 else
4769 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4770 &hdev->dev_flags);
4771
4772 if (hdev_is_powered(hdev) && use_changed &&
4773 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4774 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4775 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4776 sizeof(mode), &mode);
4777 }
4778
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004779 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4780 if (err < 0)
4781 goto unlock;
4782
4783 if (changed)
4784 err = new_settings(hdev, sk);
4785
4786unlock:
4787 hci_dev_unlock(hdev);
4788 return err;
4789}
4790
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004791static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4792 u16 len)
4793{
4794 struct mgmt_cp_set_privacy *cp = cp_data;
4795 bool changed;
4796 int err;
4797
4798 BT_DBG("request for %s", hdev->name);
4799
4800 if (!lmp_le_capable(hdev))
4801 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4802 MGMT_STATUS_NOT_SUPPORTED);
4803
4804 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4805 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4806 MGMT_STATUS_INVALID_PARAMS);
4807
4808 if (hdev_is_powered(hdev))
4809 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4810 MGMT_STATUS_REJECTED);
4811
4812 hci_dev_lock(hdev);
4813
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004814 /* If user space supports this command it is also expected to
4815 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4816 */
4817 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4818
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004819 if (cp->privacy) {
4820 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4821 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4822 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4823 } else {
4824 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4825 memset(hdev->irk, 0, sizeof(hdev->irk));
4826 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4827 }
4828
4829 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4830 if (err < 0)
4831 goto unlock;
4832
4833 if (changed)
4834 err = new_settings(hdev, sk);
4835
4836unlock:
4837 hci_dev_unlock(hdev);
4838 return err;
4839}
4840
Johan Hedberg41edf162014-02-18 10:19:35 +02004841static bool irk_is_valid(struct mgmt_irk_info *irk)
4842{
4843 switch (irk->addr.type) {
4844 case BDADDR_LE_PUBLIC:
4845 return true;
4846
4847 case BDADDR_LE_RANDOM:
4848 /* Two most significant bits shall be set */
4849 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4850 return false;
4851 return true;
4852 }
4853
4854 return false;
4855}
4856
4857static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4858 u16 len)
4859{
4860 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004861 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4862 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004863 u16 irk_count, expected_len;
4864 int i, err;
4865
4866 BT_DBG("request for %s", hdev->name);
4867
4868 if (!lmp_le_capable(hdev))
4869 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4870 MGMT_STATUS_NOT_SUPPORTED);
4871
4872 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004873 if (irk_count > max_irk_count) {
4874 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4875 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4876 MGMT_STATUS_INVALID_PARAMS);
4877 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004878
4879 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4880 if (expected_len != len) {
4881 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004882 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004883 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4884 MGMT_STATUS_INVALID_PARAMS);
4885 }
4886
4887 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4888
4889 for (i = 0; i < irk_count; i++) {
4890 struct mgmt_irk_info *key = &cp->irks[i];
4891
4892 if (!irk_is_valid(key))
4893 return cmd_status(sk, hdev->id,
4894 MGMT_OP_LOAD_IRKS,
4895 MGMT_STATUS_INVALID_PARAMS);
4896 }
4897
4898 hci_dev_lock(hdev);
4899
4900 hci_smp_irks_clear(hdev);
4901
4902 for (i = 0; i < irk_count; i++) {
4903 struct mgmt_irk_info *irk = &cp->irks[i];
4904 u8 addr_type;
4905
4906 if (irk->addr.type == BDADDR_LE_PUBLIC)
4907 addr_type = ADDR_LE_DEV_PUBLIC;
4908 else
4909 addr_type = ADDR_LE_DEV_RANDOM;
4910
4911 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4912 BDADDR_ANY);
4913 }
4914
4915 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4916
4917 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4918
4919 hci_dev_unlock(hdev);
4920
4921 return err;
4922}
4923
Johan Hedberg3f706b72013-01-20 14:27:16 +02004924static bool ltk_is_valid(struct mgmt_ltk_info *key)
4925{
4926 if (key->master != 0x00 && key->master != 0x01)
4927 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004928
4929 switch (key->addr.type) {
4930 case BDADDR_LE_PUBLIC:
4931 return true;
4932
4933 case BDADDR_LE_RANDOM:
4934 /* Two most significant bits shall be set */
4935 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4936 return false;
4937 return true;
4938 }
4939
4940 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004941}
4942
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004943static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004944 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004945{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004946 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004947 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4948 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004949 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004950 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004951
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004952 BT_DBG("request for %s", hdev->name);
4953
4954 if (!lmp_le_capable(hdev))
4955 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4956 MGMT_STATUS_NOT_SUPPORTED);
4957
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004958 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004959 if (key_count > max_key_count) {
4960 BT_ERR("load_ltks: too big key_count value %u", key_count);
4961 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4962 MGMT_STATUS_INVALID_PARAMS);
4963 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004964
4965 expected_len = sizeof(*cp) + key_count *
4966 sizeof(struct mgmt_ltk_info);
4967 if (expected_len != len) {
4968 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004969 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004970 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004971 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004972 }
4973
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004974 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004975
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004976 for (i = 0; i < key_count; i++) {
4977 struct mgmt_ltk_info *key = &cp->keys[i];
4978
Johan Hedberg3f706b72013-01-20 14:27:16 +02004979 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004980 return cmd_status(sk, hdev->id,
4981 MGMT_OP_LOAD_LONG_TERM_KEYS,
4982 MGMT_STATUS_INVALID_PARAMS);
4983 }
4984
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004985 hci_dev_lock(hdev);
4986
4987 hci_smp_ltks_clear(hdev);
4988
4989 for (i = 0; i < key_count; i++) {
4990 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004991 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004992
4993 if (key->addr.type == BDADDR_LE_PUBLIC)
4994 addr_type = ADDR_LE_DEV_PUBLIC;
4995 else
4996 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004997
Johan Hedberg61b43352014-05-29 19:36:53 +03004998 switch (key->type) {
4999 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005000 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005001 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005002 break;
5003 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005004 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005005 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005006 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005007 case MGMT_LTK_P256_UNAUTH:
5008 authenticated = 0x00;
5009 type = SMP_LTK_P256;
5010 break;
5011 case MGMT_LTK_P256_AUTH:
5012 authenticated = 0x01;
5013 type = SMP_LTK_P256;
5014 break;
5015 case MGMT_LTK_P256_DEBUG:
5016 authenticated = 0x00;
5017 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005018 default:
5019 continue;
5020 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005021
Johan Hedberg35d70272014-02-19 14:57:47 +02005022 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005023 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005024 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005025 }
5026
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005027 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5028 NULL, 0);
5029
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005030 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005031
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005032 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005033}
5034
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005035struct cmd_conn_lookup {
5036 struct hci_conn *conn;
5037 bool valid_tx_power;
5038 u8 mgmt_status;
5039};
5040
5041static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
5042{
5043 struct cmd_conn_lookup *match = data;
5044 struct mgmt_cp_get_conn_info *cp;
5045 struct mgmt_rp_get_conn_info rp;
5046 struct hci_conn *conn = cmd->user_data;
5047
5048 if (conn != match->conn)
5049 return;
5050
5051 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
5052
5053 memset(&rp, 0, sizeof(rp));
5054 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5055 rp.addr.type = cp->addr.type;
5056
5057 if (!match->mgmt_status) {
5058 rp.rssi = conn->rssi;
5059
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005060 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005061 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005062 rp.max_tx_power = conn->max_tx_power;
5063 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005064 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005065 rp.max_tx_power = HCI_TX_POWER_INVALID;
5066 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005067 }
5068
5069 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5070 match->mgmt_status, &rp, sizeof(rp));
5071
5072 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005073 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005074
5075 mgmt_pending_remove(cmd);
5076}
5077
5078static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5079{
5080 struct hci_cp_read_rssi *cp;
5081 struct hci_conn *conn;
5082 struct cmd_conn_lookup match;
5083 u16 handle;
5084
5085 BT_DBG("status 0x%02x", status);
5086
5087 hci_dev_lock(hdev);
5088
5089 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005090 * otherwise we assume it's not valid. At the moment we assume that
5091 * either both or none of current and max values are valid to keep code
5092 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005093 */
5094 match.valid_tx_power = !status;
5095
5096 /* Commands sent in request are either Read RSSI or Read Transmit Power
5097 * Level so we check which one was last sent to retrieve connection
5098 * handle. Both commands have handle as first parameter so it's safe to
5099 * cast data on the same command struct.
5100 *
5101 * First command sent is always Read RSSI and we fail only if it fails.
5102 * In other case we simply override error to indicate success as we
5103 * already remembered if TX power value is actually valid.
5104 */
5105 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5106 if (!cp) {
5107 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5108 status = 0;
5109 }
5110
5111 if (!cp) {
5112 BT_ERR("invalid sent_cmd in response");
5113 goto unlock;
5114 }
5115
5116 handle = __le16_to_cpu(cp->handle);
5117 conn = hci_conn_hash_lookup_handle(hdev, handle);
5118 if (!conn) {
5119 BT_ERR("unknown handle (%d) in response", handle);
5120 goto unlock;
5121 }
5122
5123 match.conn = conn;
5124 match.mgmt_status = mgmt_status(status);
5125
5126 /* Cache refresh is complete, now reply for mgmt request for given
5127 * connection only.
5128 */
5129 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5130 get_conn_info_complete, &match);
5131
5132unlock:
5133 hci_dev_unlock(hdev);
5134}
5135
5136static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5137 u16 len)
5138{
5139 struct mgmt_cp_get_conn_info *cp = data;
5140 struct mgmt_rp_get_conn_info rp;
5141 struct hci_conn *conn;
5142 unsigned long conn_info_age;
5143 int err = 0;
5144
5145 BT_DBG("%s", hdev->name);
5146
5147 memset(&rp, 0, sizeof(rp));
5148 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5149 rp.addr.type = cp->addr.type;
5150
5151 if (!bdaddr_type_is_valid(cp->addr.type))
5152 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5153 MGMT_STATUS_INVALID_PARAMS,
5154 &rp, sizeof(rp));
5155
5156 hci_dev_lock(hdev);
5157
5158 if (!hdev_is_powered(hdev)) {
5159 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5160 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5161 goto unlock;
5162 }
5163
5164 if (cp->addr.type == BDADDR_BREDR)
5165 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5166 &cp->addr.bdaddr);
5167 else
5168 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5169
5170 if (!conn || conn->state != BT_CONNECTED) {
5171 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5172 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5173 goto unlock;
5174 }
5175
5176 /* To avoid client trying to guess when to poll again for information we
5177 * calculate conn info age as random value between min/max set in hdev.
5178 */
5179 conn_info_age = hdev->conn_info_min_age +
5180 prandom_u32_max(hdev->conn_info_max_age -
5181 hdev->conn_info_min_age);
5182
5183 /* Query controller to refresh cached values if they are too old or were
5184 * never read.
5185 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005186 if (time_after(jiffies, conn->conn_info_timestamp +
5187 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005188 !conn->conn_info_timestamp) {
5189 struct hci_request req;
5190 struct hci_cp_read_tx_power req_txp_cp;
5191 struct hci_cp_read_rssi req_rssi_cp;
5192 struct pending_cmd *cmd;
5193
5194 hci_req_init(&req, hdev);
5195 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5196 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5197 &req_rssi_cp);
5198
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005199 /* For LE links TX power does not change thus we don't need to
5200 * query for it once value is known.
5201 */
5202 if (!bdaddr_type_is_le(cp->addr.type) ||
5203 conn->tx_power == HCI_TX_POWER_INVALID) {
5204 req_txp_cp.handle = cpu_to_le16(conn->handle);
5205 req_txp_cp.type = 0x00;
5206 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5207 sizeof(req_txp_cp), &req_txp_cp);
5208 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005209
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005210 /* Max TX power needs to be read only once per connection */
5211 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5212 req_txp_cp.handle = cpu_to_le16(conn->handle);
5213 req_txp_cp.type = 0x01;
5214 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5215 sizeof(req_txp_cp), &req_txp_cp);
5216 }
5217
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005218 err = hci_req_run(&req, conn_info_refresh_complete);
5219 if (err < 0)
5220 goto unlock;
5221
5222 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5223 data, len);
5224 if (!cmd) {
5225 err = -ENOMEM;
5226 goto unlock;
5227 }
5228
5229 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005230 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005231
5232 conn->conn_info_timestamp = jiffies;
5233 } else {
5234 /* Cache is valid, just reply with values cached in hci_conn */
5235 rp.rssi = conn->rssi;
5236 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005237 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005238
5239 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5240 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5241 }
5242
5243unlock:
5244 hci_dev_unlock(hdev);
5245 return err;
5246}
5247
Johan Hedberg95868422014-06-28 17:54:07 +03005248static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5249{
5250 struct mgmt_cp_get_clock_info *cp;
5251 struct mgmt_rp_get_clock_info rp;
5252 struct hci_cp_read_clock *hci_cp;
5253 struct pending_cmd *cmd;
5254 struct hci_conn *conn;
5255
5256 BT_DBG("%s status %u", hdev->name, status);
5257
5258 hci_dev_lock(hdev);
5259
5260 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5261 if (!hci_cp)
5262 goto unlock;
5263
5264 if (hci_cp->which) {
5265 u16 handle = __le16_to_cpu(hci_cp->handle);
5266 conn = hci_conn_hash_lookup_handle(hdev, handle);
5267 } else {
5268 conn = NULL;
5269 }
5270
5271 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5272 if (!cmd)
5273 goto unlock;
5274
5275 cp = cmd->param;
5276
5277 memset(&rp, 0, sizeof(rp));
5278 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5279
5280 if (status)
5281 goto send_rsp;
5282
5283 rp.local_clock = cpu_to_le32(hdev->clock);
5284
5285 if (conn) {
5286 rp.piconet_clock = cpu_to_le32(conn->clock);
5287 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5288 }
5289
5290send_rsp:
5291 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5292 &rp, sizeof(rp));
5293 mgmt_pending_remove(cmd);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005294 if (conn) {
Johan Hedberg95868422014-06-28 17:54:07 +03005295 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005296 hci_conn_put(conn);
5297 }
Johan Hedberg95868422014-06-28 17:54:07 +03005298
5299unlock:
5300 hci_dev_unlock(hdev);
5301}
5302
5303static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5304 u16 len)
5305{
5306 struct mgmt_cp_get_clock_info *cp = data;
5307 struct mgmt_rp_get_clock_info rp;
5308 struct hci_cp_read_clock hci_cp;
5309 struct pending_cmd *cmd;
5310 struct hci_request req;
5311 struct hci_conn *conn;
5312 int err;
5313
5314 BT_DBG("%s", hdev->name);
5315
5316 memset(&rp, 0, sizeof(rp));
5317 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5318 rp.addr.type = cp->addr.type;
5319
5320 if (cp->addr.type != BDADDR_BREDR)
5321 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5322 MGMT_STATUS_INVALID_PARAMS,
5323 &rp, sizeof(rp));
5324
5325 hci_dev_lock(hdev);
5326
5327 if (!hdev_is_powered(hdev)) {
5328 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5329 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5330 goto unlock;
5331 }
5332
5333 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5334 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5335 &cp->addr.bdaddr);
5336 if (!conn || conn->state != BT_CONNECTED) {
5337 err = cmd_complete(sk, hdev->id,
5338 MGMT_OP_GET_CLOCK_INFO,
5339 MGMT_STATUS_NOT_CONNECTED,
5340 &rp, sizeof(rp));
5341 goto unlock;
5342 }
5343 } else {
5344 conn = NULL;
5345 }
5346
5347 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5348 if (!cmd) {
5349 err = -ENOMEM;
5350 goto unlock;
5351 }
5352
5353 hci_req_init(&req, hdev);
5354
5355 memset(&hci_cp, 0, sizeof(hci_cp));
5356 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5357
5358 if (conn) {
5359 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005360 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005361
5362 hci_cp.handle = cpu_to_le16(conn->handle);
5363 hci_cp.which = 0x01; /* Piconet clock */
5364 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5365 }
5366
5367 err = hci_req_run(&req, get_clock_info_complete);
5368 if (err < 0)
5369 mgmt_pending_remove(cmd);
5370
5371unlock:
5372 hci_dev_unlock(hdev);
5373 return err;
5374}
5375
Marcel Holtmann8afef092014-06-29 22:28:34 +02005376static void device_added(struct sock *sk, struct hci_dev *hdev,
5377 bdaddr_t *bdaddr, u8 type, u8 action)
5378{
5379 struct mgmt_ev_device_added ev;
5380
5381 bacpy(&ev.addr.bdaddr, bdaddr);
5382 ev.addr.type = type;
5383 ev.action = action;
5384
5385 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5386}
5387
Marcel Holtmann2faade52014-06-29 19:44:03 +02005388static int add_device(struct sock *sk, struct hci_dev *hdev,
5389 void *data, u16 len)
5390{
5391 struct mgmt_cp_add_device *cp = data;
5392 u8 auto_conn, addr_type;
5393 int err;
5394
5395 BT_DBG("%s", hdev->name);
5396
Johan Hedberg66593582014-07-09 12:59:14 +03005397 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005398 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5399 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5400 MGMT_STATUS_INVALID_PARAMS,
5401 &cp->addr, sizeof(cp->addr));
5402
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005403 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005404 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5405 MGMT_STATUS_INVALID_PARAMS,
5406 &cp->addr, sizeof(cp->addr));
5407
5408 hci_dev_lock(hdev);
5409
Johan Hedberg66593582014-07-09 12:59:14 +03005410 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005411 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005412 if (cp->action != 0x01) {
5413 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5414 MGMT_STATUS_INVALID_PARAMS,
5415 &cp->addr, sizeof(cp->addr));
5416 goto unlock;
5417 }
5418
5419 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5420 cp->addr.type);
5421 if (err)
5422 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005423
Johan Hedberg432df052014-08-01 11:13:31 +03005424 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005425
Johan Hedberg66593582014-07-09 12:59:14 +03005426 goto added;
5427 }
5428
Marcel Holtmann2faade52014-06-29 19:44:03 +02005429 if (cp->addr.type == BDADDR_LE_PUBLIC)
5430 addr_type = ADDR_LE_DEV_PUBLIC;
5431 else
5432 addr_type = ADDR_LE_DEV_RANDOM;
5433
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005434 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005435 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005436 else if (cp->action == 0x01)
5437 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005438 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005439 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005440
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005441 /* If the connection parameters don't exist for this device,
5442 * they will be created and configured with defaults.
5443 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005444 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5445 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005446 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5447 MGMT_STATUS_FAILED,
5448 &cp->addr, sizeof(cp->addr));
5449 goto unlock;
5450 }
5451
Johan Hedberg66593582014-07-09 12:59:14 +03005452added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005453 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5454
Marcel Holtmann2faade52014-06-29 19:44:03 +02005455 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5456 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5457
5458unlock:
5459 hci_dev_unlock(hdev);
5460 return err;
5461}
5462
Marcel Holtmann8afef092014-06-29 22:28:34 +02005463static void device_removed(struct sock *sk, struct hci_dev *hdev,
5464 bdaddr_t *bdaddr, u8 type)
5465{
5466 struct mgmt_ev_device_removed ev;
5467
5468 bacpy(&ev.addr.bdaddr, bdaddr);
5469 ev.addr.type = type;
5470
5471 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5472}
5473
Marcel Holtmann2faade52014-06-29 19:44:03 +02005474static int remove_device(struct sock *sk, struct hci_dev *hdev,
5475 void *data, u16 len)
5476{
5477 struct mgmt_cp_remove_device *cp = data;
5478 int err;
5479
5480 BT_DBG("%s", hdev->name);
5481
5482 hci_dev_lock(hdev);
5483
5484 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005485 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005486 u8 addr_type;
5487
Johan Hedberg66593582014-07-09 12:59:14 +03005488 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005489 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5490 MGMT_STATUS_INVALID_PARAMS,
5491 &cp->addr, sizeof(cp->addr));
5492 goto unlock;
5493 }
5494
Johan Hedberg66593582014-07-09 12:59:14 +03005495 if (cp->addr.type == BDADDR_BREDR) {
5496 err = hci_bdaddr_list_del(&hdev->whitelist,
5497 &cp->addr.bdaddr,
5498 cp->addr.type);
5499 if (err) {
5500 err = cmd_complete(sk, hdev->id,
5501 MGMT_OP_REMOVE_DEVICE,
5502 MGMT_STATUS_INVALID_PARAMS,
5503 &cp->addr, sizeof(cp->addr));
5504 goto unlock;
5505 }
5506
Johan Hedberg432df052014-08-01 11:13:31 +03005507 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005508
Johan Hedberg66593582014-07-09 12:59:14 +03005509 device_removed(sk, hdev, &cp->addr.bdaddr,
5510 cp->addr.type);
5511 goto complete;
5512 }
5513
Marcel Holtmann2faade52014-06-29 19:44:03 +02005514 if (cp->addr.type == BDADDR_LE_PUBLIC)
5515 addr_type = ADDR_LE_DEV_PUBLIC;
5516 else
5517 addr_type = ADDR_LE_DEV_RANDOM;
5518
Johan Hedbergc71593d2014-07-02 17:37:28 +03005519 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5520 addr_type);
5521 if (!params) {
5522 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5523 MGMT_STATUS_INVALID_PARAMS,
5524 &cp->addr, sizeof(cp->addr));
5525 goto unlock;
5526 }
5527
5528 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5529 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5530 MGMT_STATUS_INVALID_PARAMS,
5531 &cp->addr, sizeof(cp->addr));
5532 goto unlock;
5533 }
5534
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005535 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005536 list_del(&params->list);
5537 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005538 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005539
5540 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005541 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005542 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005543 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005544
Marcel Holtmann2faade52014-06-29 19:44:03 +02005545 if (cp->addr.type) {
5546 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5547 MGMT_STATUS_INVALID_PARAMS,
5548 &cp->addr, sizeof(cp->addr));
5549 goto unlock;
5550 }
5551
Johan Hedberg66593582014-07-09 12:59:14 +03005552 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5553 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5554 list_del(&b->list);
5555 kfree(b);
5556 }
5557
Johan Hedberg432df052014-08-01 11:13:31 +03005558 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005559
Johan Hedberg19de0822014-07-06 13:06:51 +03005560 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5561 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5562 continue;
5563 device_removed(sk, hdev, &p->addr, p->addr_type);
5564 list_del(&p->action);
5565 list_del(&p->list);
5566 kfree(p);
5567 }
5568
5569 BT_DBG("All LE connection parameters were removed");
5570
5571 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005572 }
5573
Johan Hedberg66593582014-07-09 12:59:14 +03005574complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005575 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5576 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5577
5578unlock:
5579 hci_dev_unlock(hdev);
5580 return err;
5581}
5582
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005583static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5584 u16 len)
5585{
5586 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005587 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5588 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005589 u16 param_count, expected_len;
5590 int i;
5591
5592 if (!lmp_le_capable(hdev))
5593 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5594 MGMT_STATUS_NOT_SUPPORTED);
5595
5596 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005597 if (param_count > max_param_count) {
5598 BT_ERR("load_conn_param: too big param_count value %u",
5599 param_count);
5600 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5601 MGMT_STATUS_INVALID_PARAMS);
5602 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005603
5604 expected_len = sizeof(*cp) + param_count *
5605 sizeof(struct mgmt_conn_param);
5606 if (expected_len != len) {
5607 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5608 expected_len, len);
5609 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5610 MGMT_STATUS_INVALID_PARAMS);
5611 }
5612
5613 BT_DBG("%s param_count %u", hdev->name, param_count);
5614
5615 hci_dev_lock(hdev);
5616
5617 hci_conn_params_clear_disabled(hdev);
5618
5619 for (i = 0; i < param_count; i++) {
5620 struct mgmt_conn_param *param = &cp->params[i];
5621 struct hci_conn_params *hci_param;
5622 u16 min, max, latency, timeout;
5623 u8 addr_type;
5624
5625 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5626 param->addr.type);
5627
5628 if (param->addr.type == BDADDR_LE_PUBLIC) {
5629 addr_type = ADDR_LE_DEV_PUBLIC;
5630 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5631 addr_type = ADDR_LE_DEV_RANDOM;
5632 } else {
5633 BT_ERR("Ignoring invalid connection parameters");
5634 continue;
5635 }
5636
5637 min = le16_to_cpu(param->min_interval);
5638 max = le16_to_cpu(param->max_interval);
5639 latency = le16_to_cpu(param->latency);
5640 timeout = le16_to_cpu(param->timeout);
5641
5642 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5643 min, max, latency, timeout);
5644
5645 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5646 BT_ERR("Ignoring invalid connection parameters");
5647 continue;
5648 }
5649
5650 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5651 addr_type);
5652 if (!hci_param) {
5653 BT_ERR("Failed to add connection parameters");
5654 continue;
5655 }
5656
5657 hci_param->conn_min_interval = min;
5658 hci_param->conn_max_interval = max;
5659 hci_param->conn_latency = latency;
5660 hci_param->supervision_timeout = timeout;
5661 }
5662
5663 hci_dev_unlock(hdev);
5664
5665 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5666}
5667
Marcel Holtmanndbece372014-07-04 18:11:55 +02005668static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5669 void *data, u16 len)
5670{
5671 struct mgmt_cp_set_external_config *cp = data;
5672 bool changed;
5673 int err;
5674
5675 BT_DBG("%s", hdev->name);
5676
5677 if (hdev_is_powered(hdev))
5678 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5679 MGMT_STATUS_REJECTED);
5680
5681 if (cp->config != 0x00 && cp->config != 0x01)
5682 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5683 MGMT_STATUS_INVALID_PARAMS);
5684
5685 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5686 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5687 MGMT_STATUS_NOT_SUPPORTED);
5688
5689 hci_dev_lock(hdev);
5690
5691 if (cp->config)
5692 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5693 &hdev->dev_flags);
5694 else
5695 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5696 &hdev->dev_flags);
5697
5698 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5699 if (err < 0)
5700 goto unlock;
5701
5702 if (!changed)
5703 goto unlock;
5704
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005705 err = new_options(hdev, sk);
5706
Marcel Holtmanndbece372014-07-04 18:11:55 +02005707 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5708 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005709
5710 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5711 set_bit(HCI_CONFIG, &hdev->dev_flags);
5712 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5713
5714 queue_work(hdev->req_workqueue, &hdev->power_on);
5715 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005716 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005717 mgmt_index_added(hdev);
5718 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005719 }
5720
5721unlock:
5722 hci_dev_unlock(hdev);
5723 return err;
5724}
5725
Marcel Holtmann9713c172014-07-06 12:11:15 +02005726static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5727 void *data, u16 len)
5728{
5729 struct mgmt_cp_set_public_address *cp = data;
5730 bool changed;
5731 int err;
5732
5733 BT_DBG("%s", hdev->name);
5734
5735 if (hdev_is_powered(hdev))
5736 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5737 MGMT_STATUS_REJECTED);
5738
5739 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5740 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5741 MGMT_STATUS_INVALID_PARAMS);
5742
5743 if (!hdev->set_bdaddr)
5744 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5745 MGMT_STATUS_NOT_SUPPORTED);
5746
5747 hci_dev_lock(hdev);
5748
5749 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5750 bacpy(&hdev->public_addr, &cp->bdaddr);
5751
5752 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5753 if (err < 0)
5754 goto unlock;
5755
5756 if (!changed)
5757 goto unlock;
5758
5759 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5760 err = new_options(hdev, sk);
5761
5762 if (is_configured(hdev)) {
5763 mgmt_index_removed(hdev);
5764
5765 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5766
5767 set_bit(HCI_CONFIG, &hdev->dev_flags);
5768 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5769
5770 queue_work(hdev->req_workqueue, &hdev->power_on);
5771 }
5772
5773unlock:
5774 hci_dev_unlock(hdev);
5775 return err;
5776}
5777
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005778static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005779 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5780 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005781 bool var_len;
5782 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005783} mgmt_handlers[] = {
5784 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005785 { read_version, false, MGMT_READ_VERSION_SIZE },
5786 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5787 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5788 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5789 { set_powered, false, MGMT_SETTING_SIZE },
5790 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5791 { set_connectable, false, MGMT_SETTING_SIZE },
5792 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005793 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005794 { set_link_security, false, MGMT_SETTING_SIZE },
5795 { set_ssp, false, MGMT_SETTING_SIZE },
5796 { set_hs, false, MGMT_SETTING_SIZE },
5797 { set_le, false, MGMT_SETTING_SIZE },
5798 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5799 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5800 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5801 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5802 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5803 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5804 { disconnect, false, MGMT_DISCONNECT_SIZE },
5805 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5806 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5807 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5808 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5809 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5810 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5811 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5812 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5813 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5814 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5815 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5816 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005817 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005818 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5819 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5820 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5821 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5822 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5823 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005824 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005825 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005826 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005827 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005828 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005829 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005830 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005831 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005832 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005833 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005834 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005835 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5836 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005837 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5838 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005839 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005840 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005841 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005842 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005843};
5844
Johan Hedberg03811012010-12-08 00:21:06 +02005845int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5846{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005847 void *buf;
5848 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005849 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005850 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005851 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005852 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005853 int err;
5854
5855 BT_DBG("got %zu bytes", msglen);
5856
5857 if (msglen < sizeof(*hdr))
5858 return -EINVAL;
5859
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005860 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005861 if (!buf)
5862 return -ENOMEM;
5863
5864 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5865 err = -EFAULT;
5866 goto done;
5867 }
5868
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005869 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005870 opcode = __le16_to_cpu(hdr->opcode);
5871 index = __le16_to_cpu(hdr->index);
5872 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005873
5874 if (len != msglen - sizeof(*hdr)) {
5875 err = -EINVAL;
5876 goto done;
5877 }
5878
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005879 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005880 hdev = hci_dev_get(index);
5881 if (!hdev) {
5882 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005883 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005884 goto done;
5885 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005886
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005887 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005888 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005889 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005890 err = cmd_status(sk, index, opcode,
5891 MGMT_STATUS_INVALID_INDEX);
5892 goto done;
5893 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005894
5895 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005896 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005897 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5898 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005899 err = cmd_status(sk, index, opcode,
5900 MGMT_STATUS_INVALID_INDEX);
5901 goto done;
5902 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005903 }
5904
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005905 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005906 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005907 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005908 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005909 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005910 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005911 }
5912
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005913 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5914 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5915 err = cmd_status(sk, index, opcode,
5916 MGMT_STATUS_INVALID_INDEX);
5917 goto done;
5918 }
5919
5920 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5921 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005922 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005923 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005924 goto done;
5925 }
5926
Johan Hedbergbe22b542012-03-01 22:24:41 +02005927 handler = &mgmt_handlers[opcode];
5928
5929 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005930 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005931 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005932 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005933 goto done;
5934 }
5935
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005936 if (hdev)
5937 mgmt_init_hdev(sk, hdev);
5938
5939 cp = buf + sizeof(*hdr);
5940
Johan Hedbergbe22b542012-03-01 22:24:41 +02005941 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005942 if (err < 0)
5943 goto done;
5944
Johan Hedberg03811012010-12-08 00:21:06 +02005945 err = msglen;
5946
5947done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005948 if (hdev)
5949 hci_dev_put(hdev);
5950
Johan Hedberg03811012010-12-08 00:21:06 +02005951 kfree(buf);
5952 return err;
5953}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005954
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005955void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005956{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005957 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005958 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005959
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005960 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5961 return;
5962
5963 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5964 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5965 else
5966 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005967}
5968
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005969void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005970{
Johan Hedberg5f159032012-03-02 03:13:19 +02005971 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005972
Marcel Holtmann1514b892013-10-06 08:25:01 -07005973 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005974 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005975
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005976 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5977 return;
5978
Johan Hedberg744cf192011-11-08 20:40:14 +02005979 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005980
Marcel Holtmannedd38962014-07-02 21:30:55 +02005981 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5982 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5983 else
5984 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005985}
5986
Andre Guedes6046dc32014-02-26 20:21:51 -03005987/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005988static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005989{
5990 struct hci_conn_params *p;
5991
5992 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005993 /* Needed for AUTO_OFF case where might not "really"
5994 * have been powered off.
5995 */
5996 list_del_init(&p->action);
5997
5998 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005999 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006000 case HCI_AUTO_CONN_ALWAYS:
6001 list_add(&p->action, &hdev->pend_le_conns);
6002 break;
6003 case HCI_AUTO_CONN_REPORT:
6004 list_add(&p->action, &hdev->pend_le_reports);
6005 break;
6006 default:
6007 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006008 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006009 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006010
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006011 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006012}
6013
Johan Hedberg229ab392013-03-15 17:06:53 -05006014static void powered_complete(struct hci_dev *hdev, u8 status)
6015{
6016 struct cmd_lookup match = { NULL, hdev };
6017
6018 BT_DBG("status 0x%02x", status);
6019
6020 hci_dev_lock(hdev);
6021
Johan Hedbergd7347f32014-07-04 12:37:23 +03006022 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006023
Johan Hedberg229ab392013-03-15 17:06:53 -05006024 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6025
6026 new_settings(hdev, match.sk);
6027
6028 hci_dev_unlock(hdev);
6029
6030 if (match.sk)
6031 sock_put(match.sk);
6032}
6033
Johan Hedberg70da6242013-03-15 17:06:51 -05006034static int powered_update_hci(struct hci_dev *hdev)
6035{
Johan Hedberg890ea892013-03-15 17:06:52 -05006036 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006037 u8 link_sec;
6038
Johan Hedberg890ea892013-03-15 17:06:52 -05006039 hci_req_init(&req, hdev);
6040
Johan Hedberg70da6242013-03-15 17:06:51 -05006041 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6042 !lmp_host_ssp_capable(hdev)) {
6043 u8 ssp = 1;
6044
Johan Hedberg890ea892013-03-15 17:06:52 -05006045 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006046 }
6047
Johan Hedbergc73eee92013-04-19 18:35:21 +03006048 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6049 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006050 struct hci_cp_write_le_host_supported cp;
6051
Marcel Holtmann32226e42014-07-24 20:04:16 +02006052 cp.le = 0x01;
6053 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006054
6055 /* Check first if we already have the right
6056 * host state (host features set)
6057 */
6058 if (cp.le != lmp_host_le_capable(hdev) ||
6059 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006060 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6061 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006062 }
6063
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006064 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006065 /* Make sure the controller has a good default for
6066 * advertising data. This also applies to the case
6067 * where BR/EDR was toggled during the AUTO_OFF phase.
6068 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006069 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006070 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006071 update_scan_rsp_data(&req);
6072 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006073
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006074 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6075 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006076 }
6077
Johan Hedberg70da6242013-03-15 17:06:51 -05006078 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6079 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006080 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6081 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006082
6083 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006084 write_fast_connectable(&req, false);
6085 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006086 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006087 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006088 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006089 }
6090
Johan Hedberg229ab392013-03-15 17:06:53 -05006091 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006092}
6093
Johan Hedberg744cf192011-11-08 20:40:14 +02006094int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006095{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006096 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006097 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6098 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006099 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006100
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006101 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6102 return 0;
6103
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006104 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006105 if (powered_update_hci(hdev) == 0)
6106 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006107
Johan Hedberg229ab392013-03-15 17:06:53 -05006108 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6109 &match);
6110 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006111 }
6112
Johan Hedberg229ab392013-03-15 17:06:53 -05006113 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6114 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
6115
6116 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6117 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6118 zero_cod, sizeof(zero_cod), NULL);
6119
6120new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006121 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006122
6123 if (match.sk)
6124 sock_put(match.sk);
6125
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006126 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006127}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006128
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006129void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006130{
6131 struct pending_cmd *cmd;
6132 u8 status;
6133
6134 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6135 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006136 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006137
6138 if (err == -ERFKILL)
6139 status = MGMT_STATUS_RFKILLED;
6140 else
6141 status = MGMT_STATUS_FAILED;
6142
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006143 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006144
6145 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006146}
6147
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006148void mgmt_discoverable_timeout(struct hci_dev *hdev)
6149{
6150 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006151
6152 hci_dev_lock(hdev);
6153
6154 /* When discoverable timeout triggers, then just make sure
6155 * the limited discoverable flag is cleared. Even in the case
6156 * of a timeout triggered from general discoverable, it is
6157 * safe to unconditionally clear the flag.
6158 */
6159 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006160 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006161
6162 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006163 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6164 u8 scan = SCAN_PAGE;
6165 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6166 sizeof(scan), &scan);
6167 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006168 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006169 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006170 hci_req_run(&req, NULL);
6171
6172 hdev->discov_timeout = 0;
6173
Johan Hedberg9a43e252013-10-20 19:00:07 +03006174 new_settings(hdev, NULL);
6175
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006176 hci_dev_unlock(hdev);
6177}
6178
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006179void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6180 bool persistent)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006181{
Johan Hedberg86742e12011-11-07 23:13:38 +02006182 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006183
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006184 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006185
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006186 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006187 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006188 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006189 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006190 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006191 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006192
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006193 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006194}
Johan Hedbergf7520542011-01-20 12:34:39 +02006195
Johan Hedbergd7b25452014-05-23 13:19:53 +03006196static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6197{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006198 switch (ltk->type) {
6199 case SMP_LTK:
6200 case SMP_LTK_SLAVE:
6201 if (ltk->authenticated)
6202 return MGMT_LTK_AUTHENTICATED;
6203 return MGMT_LTK_UNAUTHENTICATED;
6204 case SMP_LTK_P256:
6205 if (ltk->authenticated)
6206 return MGMT_LTK_P256_AUTH;
6207 return MGMT_LTK_P256_UNAUTH;
6208 case SMP_LTK_P256_DEBUG:
6209 return MGMT_LTK_P256_DEBUG;
6210 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006211
6212 return MGMT_LTK_UNAUTHENTICATED;
6213}
6214
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006215void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006216{
6217 struct mgmt_ev_new_long_term_key ev;
6218
6219 memset(&ev, 0, sizeof(ev));
6220
Marcel Holtmann5192d302014-02-19 17:11:58 -08006221 /* Devices using resolvable or non-resolvable random addresses
6222 * without providing an indentity resolving key don't require
6223 * to store long term keys. Their addresses will change the
6224 * next time around.
6225 *
6226 * Only when a remote device provides an identity address
6227 * make sure the long term key is stored. If the remote
6228 * identity is known, the long term keys are internally
6229 * mapped to the identity address. So allow static random
6230 * and public addresses here.
6231 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006232 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6233 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6234 ev.store_hint = 0x00;
6235 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006236 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006237
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006238 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006239 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006240 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006241 ev.key.enc_size = key->enc_size;
6242 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006243 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006244
Johan Hedberg2ceba532014-06-16 19:25:16 +03006245 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006246 ev.key.master = 1;
6247
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006248 memcpy(ev.key.val, key->val, sizeof(key->val));
6249
Marcel Holtmann083368f2013-10-15 14:26:29 -07006250 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006251}
6252
Johan Hedberg95fbac82014-02-19 15:18:31 +02006253void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6254{
6255 struct mgmt_ev_new_irk ev;
6256
6257 memset(&ev, 0, sizeof(ev));
6258
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006259 /* For identity resolving keys from devices that are already
6260 * using a public address or static random address, do not
6261 * ask for storing this key. The identity resolving key really
6262 * is only mandatory for devices using resovlable random
6263 * addresses.
6264 *
6265 * Storing all identity resolving keys has the downside that
6266 * they will be also loaded on next boot of they system. More
6267 * identity resolving keys, means more time during scanning is
6268 * needed to actually resolve these addresses.
6269 */
6270 if (bacmp(&irk->rpa, BDADDR_ANY))
6271 ev.store_hint = 0x01;
6272 else
6273 ev.store_hint = 0x00;
6274
Johan Hedberg95fbac82014-02-19 15:18:31 +02006275 bacpy(&ev.rpa, &irk->rpa);
6276 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6277 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6278 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6279
6280 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6281}
6282
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006283void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6284 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006285{
6286 struct mgmt_ev_new_csrk ev;
6287
6288 memset(&ev, 0, sizeof(ev));
6289
6290 /* Devices using resolvable or non-resolvable random addresses
6291 * without providing an indentity resolving key don't require
6292 * to store signature resolving keys. Their addresses will change
6293 * the next time around.
6294 *
6295 * Only when a remote device provides an identity address
6296 * make sure the signature resolving key is stored. So allow
6297 * static random and public addresses here.
6298 */
6299 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6300 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6301 ev.store_hint = 0x00;
6302 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006303 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006304
6305 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6306 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6307 ev.key.master = csrk->master;
6308 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6309
6310 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6311}
6312
Andre Guedesffb5a8272014-07-01 18:10:11 -03006313void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006314 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6315 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006316{
6317 struct mgmt_ev_new_conn_param ev;
6318
Johan Hedbergc103aea2014-07-02 17:37:34 +03006319 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6320 return;
6321
Andre Guedesffb5a8272014-07-01 18:10:11 -03006322 memset(&ev, 0, sizeof(ev));
6323 bacpy(&ev.addr.bdaddr, bdaddr);
6324 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006325 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006326 ev.min_interval = cpu_to_le16(min_interval);
6327 ev.max_interval = cpu_to_le16(max_interval);
6328 ev.latency = cpu_to_le16(latency);
6329 ev.timeout = cpu_to_le16(timeout);
6330
6331 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6332}
6333
Marcel Holtmann94933992013-10-15 10:26:39 -07006334static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6335 u8 data_len)
6336{
6337 eir[eir_len++] = sizeof(type) + data_len;
6338 eir[eir_len++] = type;
6339 memcpy(&eir[eir_len], data, data_len);
6340 eir_len += data_len;
6341
6342 return eir_len;
6343}
6344
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006345void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6346 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006347{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006348 char buf[512];
6349 struct mgmt_ev_device_connected *ev = (void *) buf;
6350 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006351
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006352 bacpy(&ev->addr.bdaddr, &conn->dst);
6353 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006354
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006355 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006356
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006357 /* We must ensure that the EIR Data fields are ordered and
6358 * unique. Keep it simple for now and avoid the problem by not
6359 * adding any BR/EDR data to the LE adv.
6360 */
6361 if (conn->le_adv_data_len > 0) {
6362 memcpy(&ev->eir[eir_len],
6363 conn->le_adv_data, conn->le_adv_data_len);
6364 eir_len = conn->le_adv_data_len;
6365 } else {
6366 if (name_len > 0)
6367 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6368 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006369
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006370 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006371 eir_len = eir_append_data(ev->eir, eir_len,
6372 EIR_CLASS_OF_DEV,
6373 conn->dev_class, 3);
6374 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006375
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006376 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006377
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006378 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6379 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006380}
6381
Johan Hedberg8962ee72011-01-20 12:40:27 +02006382static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6383{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006384 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006385 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006386 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006387
Johan Hedberg88c3df12012-02-09 14:27:38 +02006388 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6389 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006390
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006391 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006392 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006393
6394 *sk = cmd->sk;
6395 sock_hold(*sk);
6396
Johan Hedberga664b5b2011-02-19 12:06:02 -03006397 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006398}
6399
Johan Hedberg124f6e32012-02-09 13:50:12 +02006400static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006401{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006402 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006403 struct mgmt_cp_unpair_device *cp = cmd->param;
6404 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006405
6406 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006407 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6408 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006409
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006410 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6411
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006412 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006413
6414 mgmt_pending_remove(cmd);
6415}
6416
Johan Hedberg84c61d92014-08-01 11:13:30 +03006417bool mgmt_powering_down(struct hci_dev *hdev)
6418{
6419 struct pending_cmd *cmd;
6420 struct mgmt_mode *cp;
6421
6422 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6423 if (!cmd)
6424 return false;
6425
6426 cp = cmd->param;
6427 if (!cp->val)
6428 return true;
6429
6430 return false;
6431}
6432
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006433void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006434 u8 link_type, u8 addr_type, u8 reason,
6435 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006436{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006437 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006438 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006439
Johan Hedberg84c61d92014-08-01 11:13:30 +03006440 /* The connection is still in hci_conn_hash so test for 1
6441 * instead of 0 to know if this is the last one.
6442 */
6443 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6444 cancel_delayed_work(&hdev->power_off);
6445 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006446 }
6447
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006448 if (!mgmt_connected)
6449 return;
6450
Andre Guedes57eb7762013-10-30 19:01:41 -03006451 if (link_type != ACL_LINK && link_type != LE_LINK)
6452 return;
6453
Johan Hedberg744cf192011-11-08 20:40:14 +02006454 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006455
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006456 bacpy(&ev.addr.bdaddr, bdaddr);
6457 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6458 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006459
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006460 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006461
6462 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006463 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006464
Johan Hedberg124f6e32012-02-09 13:50:12 +02006465 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006466 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006467}
6468
Marcel Holtmann78929242013-10-06 23:55:47 -07006469void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6470 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006471{
Andre Guedes3655bba2013-10-30 19:01:40 -03006472 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6473 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006474 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006475 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006476
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006477 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6478 hdev);
6479
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006480 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006481 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006482 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006483
Andre Guedes3655bba2013-10-30 19:01:40 -03006484 cp = cmd->param;
6485
6486 if (bacmp(bdaddr, &cp->addr.bdaddr))
6487 return;
6488
6489 if (cp->addr.type != bdaddr_type)
6490 return;
6491
Johan Hedberg88c3df12012-02-09 14:27:38 +02006492 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006493 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006494
Marcel Holtmann78929242013-10-06 23:55:47 -07006495 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6496 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006497
Johan Hedberga664b5b2011-02-19 12:06:02 -03006498 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006499}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006500
Marcel Holtmann445608d2013-10-06 23:55:48 -07006501void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6502 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006503{
6504 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006505
Johan Hedberg84c61d92014-08-01 11:13:30 +03006506 /* The connection is still in hci_conn_hash so test for 1
6507 * instead of 0 to know if this is the last one.
6508 */
6509 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6510 cancel_delayed_work(&hdev->power_off);
6511 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006512 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006513
Johan Hedberg4c659c32011-11-07 23:13:39 +02006514 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006515 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006516 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006517
Marcel Holtmann445608d2013-10-06 23:55:48 -07006518 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006519}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006520
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006521void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006522{
6523 struct mgmt_ev_pin_code_request ev;
6524
Johan Hedbergd8457692012-02-17 14:24:57 +02006525 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006526 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006527 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006528
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006529 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006530}
6531
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006532void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6533 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006534{
6535 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006536 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006537
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006538 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006539 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006540 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006541
Johan Hedbergd8457692012-02-17 14:24:57 +02006542 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006543 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006544
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006545 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6546 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006547
Johan Hedberga664b5b2011-02-19 12:06:02 -03006548 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006549}
6550
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006551void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6552 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006553{
6554 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006555 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006556
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006557 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006558 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006559 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006560
Johan Hedbergd8457692012-02-17 14:24:57 +02006561 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006562 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006563
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006564 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6565 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006566
Johan Hedberga664b5b2011-02-19 12:06:02 -03006567 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006568}
Johan Hedberga5c29682011-02-19 12:05:57 -03006569
Johan Hedberg744cf192011-11-08 20:40:14 +02006570int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006571 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006572 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006573{
6574 struct mgmt_ev_user_confirm_request ev;
6575
Johan Hedberg744cf192011-11-08 20:40:14 +02006576 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006577
Johan Hedberg272d90d2012-02-09 15:26:12 +02006578 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006579 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006580 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006581 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006582
Johan Hedberg744cf192011-11-08 20:40:14 +02006583 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006584 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006585}
6586
Johan Hedberg272d90d2012-02-09 15:26:12 +02006587int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006588 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006589{
6590 struct mgmt_ev_user_passkey_request ev;
6591
6592 BT_DBG("%s", hdev->name);
6593
Johan Hedberg272d90d2012-02-09 15:26:12 +02006594 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006595 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006596
6597 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006598 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006599}
6600
Brian Gix0df4c182011-11-16 13:53:13 -08006601static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006602 u8 link_type, u8 addr_type, u8 status,
6603 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006604{
6605 struct pending_cmd *cmd;
6606 struct mgmt_rp_user_confirm_reply rp;
6607 int err;
6608
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006609 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006610 if (!cmd)
6611 return -ENOENT;
6612
Johan Hedberg272d90d2012-02-09 15:26:12 +02006613 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006614 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006615 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006616 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006617
Johan Hedberga664b5b2011-02-19 12:06:02 -03006618 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006619
6620 return err;
6621}
6622
Johan Hedberg744cf192011-11-08 20:40:14 +02006623int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006624 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006625{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006626 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006627 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006628}
6629
Johan Hedberg272d90d2012-02-09 15:26:12 +02006630int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006631 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006632{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006633 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006634 status,
6635 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006636}
Johan Hedberg2a611692011-02-19 12:06:00 -03006637
Brian Gix604086b2011-11-23 08:28:33 -08006638int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006639 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006640{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006641 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006642 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006643}
6644
Johan Hedberg272d90d2012-02-09 15:26:12 +02006645int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006646 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006647{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006648 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006649 status,
6650 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006651}
6652
Johan Hedberg92a25252012-09-06 18:39:26 +03006653int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6654 u8 link_type, u8 addr_type, u32 passkey,
6655 u8 entered)
6656{
6657 struct mgmt_ev_passkey_notify ev;
6658
6659 BT_DBG("%s", hdev->name);
6660
6661 bacpy(&ev.addr.bdaddr, bdaddr);
6662 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6663 ev.passkey = __cpu_to_le32(passkey);
6664 ev.entered = entered;
6665
6666 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6667}
6668
Johan Hedberge1e930f2014-09-08 17:09:49 -07006669void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006670{
6671 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006672 struct pending_cmd *cmd;
6673 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006674
Johan Hedberge1e930f2014-09-08 17:09:49 -07006675 bacpy(&ev.addr.bdaddr, &conn->dst);
6676 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6677 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006678
Johan Hedberge1e930f2014-09-08 17:09:49 -07006679 cmd = find_pairing(conn);
6680
6681 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6682 cmd ? cmd->sk : NULL);
6683
6684 if (cmd)
6685 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006686}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006687
Marcel Holtmann464996a2013-10-15 14:26:24 -07006688void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006689{
6690 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006691 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006692
6693 if (status) {
6694 u8 mgmt_err = mgmt_status(status);
6695 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006696 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006697 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006698 }
6699
Marcel Holtmann464996a2013-10-15 14:26:24 -07006700 if (test_bit(HCI_AUTH, &hdev->flags))
6701 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6702 &hdev->dev_flags);
6703 else
6704 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6705 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006706
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006707 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006708 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006709
Johan Hedberg47990ea2012-02-22 11:58:37 +02006710 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006711 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006712
6713 if (match.sk)
6714 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006715}
6716
Johan Hedberg890ea892013-03-15 17:06:52 -05006717static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006718{
Johan Hedberg890ea892013-03-15 17:06:52 -05006719 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006720 struct hci_cp_write_eir cp;
6721
Johan Hedberg976eb202012-10-24 21:12:01 +03006722 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006723 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006724
Johan Hedbergc80da272012-02-22 15:38:48 +02006725 memset(hdev->eir, 0, sizeof(hdev->eir));
6726
Johan Hedbergcacaf522012-02-21 00:52:42 +02006727 memset(&cp, 0, sizeof(cp));
6728
Johan Hedberg890ea892013-03-15 17:06:52 -05006729 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006730}
6731
Marcel Holtmann3e248562013-10-15 14:26:25 -07006732void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006733{
6734 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006735 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006736 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006737
6738 if (status) {
6739 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006740
6741 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006742 &hdev->dev_flags)) {
6743 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006744 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006745 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006746
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006747 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6748 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006749 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006750 }
6751
6752 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006753 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006754 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006755 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6756 if (!changed)
6757 changed = test_and_clear_bit(HCI_HS_ENABLED,
6758 &hdev->dev_flags);
6759 else
6760 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006761 }
6762
6763 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6764
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006765 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006766 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006767
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006768 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006769 sock_put(match.sk);
6770
Johan Hedberg890ea892013-03-15 17:06:52 -05006771 hci_req_init(&req, hdev);
6772
Johan Hedberg37699722014-06-24 14:00:27 +03006773 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6774 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6775 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6776 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006777 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006778 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006779 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006780 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006781
6782 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006783}
6784
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006785void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6786{
6787 struct cmd_lookup match = { NULL, hdev };
6788 bool changed = false;
6789
6790 if (status) {
6791 u8 mgmt_err = mgmt_status(status);
6792
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006793 if (enable) {
6794 if (test_and_clear_bit(HCI_SC_ENABLED,
6795 &hdev->dev_flags))
6796 new_settings(hdev, NULL);
6797 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6798 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006799
6800 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6801 cmd_status_rsp, &mgmt_err);
6802 return;
6803 }
6804
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006805 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006806 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006807 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006808 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006809 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6810 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006811
6812 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6813 settings_rsp, &match);
6814
6815 if (changed)
6816 new_settings(hdev, match.sk);
6817
6818 if (match.sk)
6819 sock_put(match.sk);
6820}
6821
Johan Hedberg92da6092013-03-15 17:06:55 -05006822static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006823{
6824 struct cmd_lookup *match = data;
6825
Johan Hedberg90e70452012-02-23 23:09:40 +02006826 if (match->sk == NULL) {
6827 match->sk = cmd->sk;
6828 sock_hold(match->sk);
6829 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006830}
6831
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006832void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6833 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006834{
Johan Hedberg90e70452012-02-23 23:09:40 +02006835 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006836
Johan Hedberg92da6092013-03-15 17:06:55 -05006837 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6838 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6839 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006840
6841 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006842 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6843 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006844
6845 if (match.sk)
6846 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006847}
6848
Marcel Holtmann7667da32013-10-15 14:26:27 -07006849void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006850{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006851 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006852 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006853
Johan Hedberg13928972013-03-15 17:07:00 -05006854 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006855 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006856
6857 memset(&ev, 0, sizeof(ev));
6858 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006859 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006860
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006861 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006862 if (!cmd) {
6863 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006864
Johan Hedberg13928972013-03-15 17:07:00 -05006865 /* If this is a HCI command related to powering on the
6866 * HCI dev don't send any mgmt signals.
6867 */
6868 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006869 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006870 }
6871
Marcel Holtmann7667da32013-10-15 14:26:27 -07006872 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6873 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006874}
Szymon Jancc35938b2011-03-22 13:12:21 +01006875
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006876void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006877 u8 *rand192, u8 *hash256, u8 *rand256,
6878 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006879{
6880 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006881
Johan Hedberg744cf192011-11-08 20:40:14 +02006882 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006883
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006884 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006885 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006886 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006887
6888 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006889 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6890 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006891 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006892 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006893 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006894
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006895 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006896 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006897
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006898 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006899 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006900
6901 cmd_complete(cmd->sk, hdev->id,
6902 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6903 &rp, sizeof(rp));
6904 } else {
6905 struct mgmt_rp_read_local_oob_data rp;
6906
6907 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006908 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006909
6910 cmd_complete(cmd->sk, hdev->id,
6911 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6912 &rp, sizeof(rp));
6913 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006914 }
6915
6916 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006917}
Johan Hedberge17acd42011-03-30 23:57:16 +03006918
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006919/* this is reversed hex representation of bluetooth base uuid. We need it for
6920 * service uuid parsing in eir.
6921 */
6922static const u8 reverse_base_uuid[] = {
6923 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
6924 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6925};
6926
6927static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6928{
6929 int i;
6930
6931 for (i = 0; i < uuid_count; i++) {
6932 if (!memcmp(uuid, uuids[i], 16))
6933 return true;
6934 }
6935
6936 return false;
6937}
6938
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006939static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6940{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006941 u16 parsed = 0;
6942
6943 while (parsed < eir_len) {
6944 u8 field_len = eir[0];
6945 u8 uuid[16];
6946 int i;
6947
6948 if (field_len == 0)
6949 break;
6950
6951 if (eir_len - parsed < field_len + 1)
6952 break;
6953
6954 switch (eir[1]) {
6955 case EIR_UUID16_ALL:
6956 case EIR_UUID16_SOME:
6957 for (i = 0; i + 3 <= field_len; i += 2) {
6958 memcpy(uuid, reverse_base_uuid, 16);
6959 uuid[13] = eir[i + 3];
6960 uuid[12] = eir[i + 2];
6961 if (has_uuid(uuid, uuid_count, uuids))
6962 return true;
6963 }
6964 break;
6965 case EIR_UUID32_ALL:
6966 case EIR_UUID32_SOME:
6967 for (i = 0; i + 5 <= field_len; i += 4) {
6968 memcpy(uuid, reverse_base_uuid, 16);
6969 uuid[15] = eir[i + 5];
6970 uuid[14] = eir[i + 4];
6971 uuid[13] = eir[i + 3];
6972 uuid[12] = eir[i + 2];
6973 if (has_uuid(uuid, uuid_count, uuids))
6974 return true;
6975 }
6976 break;
6977 case EIR_UUID128_ALL:
6978 case EIR_UUID128_SOME:
6979 for (i = 0; i + 17 <= field_len; i += 16) {
6980 memcpy(uuid, eir + i + 2, 16);
6981 if (has_uuid(uuid, uuid_count, uuids))
6982 return true;
6983 }
6984 break;
6985 }
6986
6987 parsed += field_len + 1;
6988 eir += field_len + 1;
6989 }
6990
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006991 return false;
6992}
6993
Marcel Holtmann901801b2013-10-06 23:55:51 -07006994void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006995 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6996 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006997{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006998 char buf[512];
6999 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007000 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007001 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007002
Johan Hedberg75ce2082014-07-02 22:42:01 +03007003 /* Don't send events for a non-kernel initiated discovery. With
7004 * LE one exception is if we have pend_le_reports > 0 in which
7005 * case we're doing passive scanning and want these events.
7006 */
7007 if (!hci_discovery_active(hdev)) {
7008 if (link_type == ACL_LINK)
7009 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007010 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007011 return;
7012 }
Andre Guedes12602d02013-04-30 15:29:40 -03007013
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007014 /* When using service discovery with a RSSI threshold, then check
7015 * if such a RSSI threshold is specified. If a RSSI threshold has
7016 * been specified, then all results with a RSSI smaller than the
7017 * RSSI threshold will be dropped.
7018 */
7019 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7020 rssi < hdev->discovery.rssi)
7021 return;
7022
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007023 /* Make sure that the buffer is big enough. The 5 extra bytes
7024 * are for the potential CoD field.
7025 */
7026 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007027 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007028
Johan Hedberg1dc06092012-01-15 21:01:23 +02007029 memset(buf, 0, sizeof(buf));
7030
Johan Hedberg841c5642014-07-07 12:45:54 +03007031 bacpy(&ev->addr.bdaddr, bdaddr);
7032 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007033 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007034 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007035
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007036 if (eir_len > 0) {
7037 /* When using service discovery and a list of UUID is
7038 * provided, results with no matching UUID should be
7039 * dropped. In case there is a match the result is
7040 * kept and checking possible scan response data
7041 * will be skipped.
7042 */
7043 if (hdev->discovery.uuid_count > 0) {
7044 match = eir_has_uuids(eir, eir_len,
7045 hdev->discovery.uuid_count,
7046 hdev->discovery.uuids);
7047 if (!match)
7048 return;
7049 }
7050
7051 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007052 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007053 } else {
7054 /* When using service discovery and a list of UUID is
7055 * provided, results with empty EIR or advertising data
7056 * should be dropped since they do not match any UUID.
7057 */
7058 if (hdev->discovery.uuid_count > 0)
7059 return;
7060 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007061
Johan Hedberg1dc06092012-01-15 21:01:23 +02007062 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7063 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007064 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007065
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007066 if (scan_rsp_len > 0) {
7067 /* When using service discovery and a list of UUID is
7068 * provided, results with no matching UUID should be
7069 * dropped if there is no previous match from the
7070 * advertising data.
7071 */
7072 if (hdev->discovery.uuid_count > 0) {
7073 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7074 hdev->discovery.uuid_count,
7075 hdev->discovery.uuids))
7076 return;
7077 }
7078
7079 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007080 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007081 } else {
7082 /* When using service discovery and a list of UUID is
7083 * provided, results with empty scan response and no
7084 * previous matched advertising data should be dropped.
7085 */
7086 if (hdev->discovery.uuid_count > 0 && !match)
7087 return;
7088 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007089
7090 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7091 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007092
Marcel Holtmann901801b2013-10-06 23:55:51 -07007093 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007094}
Johan Hedberga88a9652011-03-30 13:18:12 +03007095
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007096void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7097 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007098{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007099 struct mgmt_ev_device_found *ev;
7100 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7101 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007102
Johan Hedbergb644ba32012-01-17 21:48:47 +02007103 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007104
Johan Hedbergb644ba32012-01-17 21:48:47 +02007105 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007106
Johan Hedbergb644ba32012-01-17 21:48:47 +02007107 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007108 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007109 ev->rssi = rssi;
7110
7111 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007112 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007113
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007114 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007115
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007116 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007117}
Johan Hedberg314b2382011-04-27 10:29:57 -04007118
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007119void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007120{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007121 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007122
Andre Guedes343fb142011-11-22 17:14:19 -03007123 BT_DBG("%s discovering %u", hdev->name, discovering);
7124
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007125 memset(&ev, 0, sizeof(ev));
7126 ev.type = hdev->discovery.type;
7127 ev.discovering = discovering;
7128
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007129 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007130}
Antti Julku5e762442011-08-25 16:48:02 +03007131
Marcel Holtmann5976e602013-10-06 04:08:14 -07007132static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7133{
7134 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007135}
7136
7137void mgmt_reenable_advertising(struct hci_dev *hdev)
7138{
7139 struct hci_request req;
7140
Marcel Holtmann5976e602013-10-06 04:08:14 -07007141 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7142 return;
7143
7144 hci_req_init(&req, hdev);
7145 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007146 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007147}