blob: 77cf0ef0d8a31cff859bb8352a7fe290b8f0cb65 [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,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200132struct pending_cmd {
133 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200134 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100136 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300138 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139};
140
Johan Hedbergca69b792011-11-11 18:10:00 +0200141/* HCI to MGMT error code conversion table */
142static u8 mgmt_status_table[] = {
143 MGMT_STATUS_SUCCESS,
144 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
145 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
146 MGMT_STATUS_FAILED, /* Hardware Failure */
147 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
148 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200149 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200150 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
151 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
152 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
153 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
154 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
155 MGMT_STATUS_BUSY, /* Command Disallowed */
156 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
157 MGMT_STATUS_REJECTED, /* Rejected Security */
158 MGMT_STATUS_REJECTED, /* Rejected Personal */
159 MGMT_STATUS_TIMEOUT, /* Host Timeout */
160 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
161 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
162 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
163 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
164 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
165 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
166 MGMT_STATUS_BUSY, /* Repeated Attempts */
167 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
168 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
169 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
170 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
171 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
172 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
173 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
174 MGMT_STATUS_FAILED, /* Unspecified Error */
175 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
176 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
177 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
178 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
179 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
180 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
181 MGMT_STATUS_FAILED, /* Unit Link Key Used */
182 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
183 MGMT_STATUS_TIMEOUT, /* Instant Passed */
184 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
185 MGMT_STATUS_FAILED, /* Transaction Collision */
186 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
187 MGMT_STATUS_REJECTED, /* QoS Rejected */
188 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
189 MGMT_STATUS_REJECTED, /* Insufficient Security */
190 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
191 MGMT_STATUS_BUSY, /* Role Switch Pending */
192 MGMT_STATUS_FAILED, /* Slot Violation */
193 MGMT_STATUS_FAILED, /* Role Switch Failed */
194 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
195 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
196 MGMT_STATUS_BUSY, /* Host Busy Pairing */
197 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
198 MGMT_STATUS_BUSY, /* Controller Busy */
199 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
200 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
201 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
202 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
203 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
204};
205
206static u8 mgmt_status(u8 hci_status)
207{
208 if (hci_status < ARRAY_SIZE(mgmt_status_table))
209 return mgmt_status_table[hci_status];
210
211 return MGMT_STATUS_FAILED;
212}
213
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200214static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
215 struct sock *skip_sk)
216{
217 struct sk_buff *skb;
218 struct mgmt_hdr *hdr;
219
220 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
221 if (!skb)
222 return -ENOMEM;
223
224 hdr = (void *) skb_put(skb, sizeof(*hdr));
225 hdr->opcode = cpu_to_le16(event);
226 if (hdev)
227 hdr->index = cpu_to_le16(hdev->id);
228 else
229 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
230 hdr->len = cpu_to_le16(data_len);
231
232 if (data)
233 memcpy(skb_put(skb, data_len), data, data_len);
234
235 /* Time stamp */
236 __net_timestamp(skb);
237
238 hci_send_to_control(skb, skip_sk);
239 kfree_skb(skb);
240
241 return 0;
242}
243
Szymon Janc4e51eae2011-02-25 19:05:48 +0100244static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200245{
246 struct sk_buff *skb;
247 struct mgmt_hdr *hdr;
248 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300249 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200250
Szymon Janc34eb5252011-02-28 14:10:08 +0100251 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200252
Andre Guedes790eff42012-06-07 19:05:46 -0300253 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200254 if (!skb)
255 return -ENOMEM;
256
257 hdr = (void *) skb_put(skb, sizeof(*hdr));
258
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700259 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100260 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200261 hdr->len = cpu_to_le16(sizeof(*ev));
262
263 ev = (void *) skb_put(skb, sizeof(*ev));
264 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200265 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200266
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300267 err = sock_queue_rcv_skb(sk, skb);
268 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269 kfree_skb(skb);
270
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300271 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272}
273
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200274static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300275 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200276{
277 struct sk_buff *skb;
278 struct mgmt_hdr *hdr;
279 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300280 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200281
282 BT_DBG("sock %p", sk);
283
Andre Guedes790eff42012-06-07 19:05:46 -0300284 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200285 if (!skb)
286 return -ENOMEM;
287
288 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200289
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700290 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100291 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200292 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200293
Johan Hedberga38528f2011-01-22 06:46:43 +0200294 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200295 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200296 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100297
298 if (rp)
299 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200300
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300301 err = sock_queue_rcv_skb(sk, skb);
302 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200303 kfree_skb(skb);
304
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100305 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200306}
307
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300308static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
309 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200310{
311 struct mgmt_rp_read_version rp;
312
313 BT_DBG("sock %p", sk);
314
315 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700316 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200317
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200318 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300319 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200320}
321
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
323 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200324{
325 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200326 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
327 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200328 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200329 size_t rp_size;
330 int i, err;
331
332 BT_DBG("sock %p", sk);
333
334 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
335
336 rp = kmalloc(rp_size, GFP_KERNEL);
337 if (!rp)
338 return -ENOMEM;
339
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700340 rp->num_commands = cpu_to_le16(num_commands);
341 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200342
343 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
344 put_unaligned_le16(mgmt_commands[i], opcode);
345
346 for (i = 0; i < num_events; i++, opcode++)
347 put_unaligned_le16(mgmt_events[i], opcode);
348
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200349 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300350 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200351 kfree(rp);
352
353 return err;
354}
355
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300356static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
357 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200358{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200359 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200360 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200361 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300363 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200364
365 BT_DBG("sock %p", sk);
366
367 read_lock(&hci_dev_list_lock);
368
369 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300370 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200371 if (d->dev_type == HCI_BREDR &&
372 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700373 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374 }
375
Johan Hedberga38528f2011-01-22 06:46:43 +0200376 rp_len = sizeof(*rp) + (2 * count);
377 rp = kmalloc(rp_len, GFP_ATOMIC);
378 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100379 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200380 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100381 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382
Johan Hedberg476e44c2012-10-19 20:10:46 +0300383 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200384 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200385 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200386 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200387 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200388 continue;
389
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 /* Devices marked as raw-only are neither configured
391 * nor unconfigured controllers.
392 */
393 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700394 continue;
395
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200396 if (d->dev_type == HCI_BREDR &&
397 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700398 rp->index[count++] = cpu_to_le16(d->id);
399 BT_DBG("Added hci%u", d->id);
400 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200401 }
402
Johan Hedberg476e44c2012-10-19 20:10:46 +0300403 rp->num_controllers = cpu_to_le16(count);
404 rp_len = sizeof(*rp) + (2 * count);
405
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200406 read_unlock(&hci_dev_list_lock);
407
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200408 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300409 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200410
Johan Hedberga38528f2011-01-22 06:46:43 +0200411 kfree(rp);
412
413 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200414}
415
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200416static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
417 void *data, u16 data_len)
418{
419 struct mgmt_rp_read_unconf_index_list *rp;
420 struct hci_dev *d;
421 size_t rp_len;
422 u16 count;
423 int err;
424
425 BT_DBG("sock %p", sk);
426
427 read_lock(&hci_dev_list_lock);
428
429 count = 0;
430 list_for_each_entry(d, &hci_dev_list, list) {
431 if (d->dev_type == HCI_BREDR &&
432 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
433 count++;
434 }
435
436 rp_len = sizeof(*rp) + (2 * count);
437 rp = kmalloc(rp_len, GFP_ATOMIC);
438 if (!rp) {
439 read_unlock(&hci_dev_list_lock);
440 return -ENOMEM;
441 }
442
443 count = 0;
444 list_for_each_entry(d, &hci_dev_list, list) {
445 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200446 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200447 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
448 continue;
449
450 /* Devices marked as raw-only are neither configured
451 * nor unconfigured controllers.
452 */
453 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
454 continue;
455
456 if (d->dev_type == HCI_BREDR &&
457 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
458 rp->index[count++] = cpu_to_le16(d->id);
459 BT_DBG("Added hci%u", d->id);
460 }
461 }
462
463 rp->num_controllers = cpu_to_le16(count);
464 rp_len = sizeof(*rp) + (2 * count);
465
466 read_unlock(&hci_dev_list_lock);
467
468 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
469 0, rp, rp_len);
470
471 kfree(rp);
472
473 return err;
474}
475
Marcel Holtmanndbece372014-07-04 18:11:55 +0200476static bool is_configured(struct hci_dev *hdev)
477{
478 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
479 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
480 return false;
481
482 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
483 !bacmp(&hdev->public_addr, BDADDR_ANY))
484 return false;
485
486 return true;
487}
488
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200489static __le32 get_missing_options(struct hci_dev *hdev)
490{
491 u32 options = 0;
492
Marcel Holtmanndbece372014-07-04 18:11:55 +0200493 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
494 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200495 options |= MGMT_OPTION_EXTERNAL_CONFIG;
496
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200497 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
498 !bacmp(&hdev->public_addr, BDADDR_ANY))
499 options |= MGMT_OPTION_PUBLIC_ADDRESS;
500
501 return cpu_to_le32(options);
502}
503
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200504static int new_options(struct hci_dev *hdev, struct sock *skip)
505{
506 __le32 options = get_missing_options(hdev);
507
508 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
509 sizeof(options), skip);
510}
511
Marcel Holtmanndbece372014-07-04 18:11:55 +0200512static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
513{
514 __le32 options = get_missing_options(hdev);
515
516 return cmd_complete(sk, hdev->id, opcode, 0, &options,
517 sizeof(options));
518}
519
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200520static int read_config_info(struct sock *sk, struct hci_dev *hdev,
521 void *data, u16 data_len)
522{
523 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200524 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200525
526 BT_DBG("sock %p %s", sk, hdev->name);
527
528 hci_dev_lock(hdev);
529
530 memset(&rp, 0, sizeof(rp));
531 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200532
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200533 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
534 options |= MGMT_OPTION_EXTERNAL_CONFIG;
535
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200536 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200537 options |= MGMT_OPTION_PUBLIC_ADDRESS;
538
539 rp.supported_options = cpu_to_le32(options);
540 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200541
542 hci_dev_unlock(hdev);
543
544 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
545 sizeof(rp));
546}
547
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200548static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200549{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200550 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200551
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200552 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300553 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800554 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300555 settings |= MGMT_SETTING_CONNECTABLE;
556 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200557
Andre Guedesed3fa312012-07-24 15:03:46 -0300558 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500559 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
560 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200561 settings |= MGMT_SETTING_BREDR;
562 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700563
564 if (lmp_ssp_capable(hdev)) {
565 settings |= MGMT_SETTING_SSP;
566 settings |= MGMT_SETTING_HS;
567 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800568
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800569 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200570 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700572 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100573
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300574 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200575 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300576 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300577 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200578 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200580
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200581 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
582 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200583 settings |= MGMT_SETTING_CONFIGURATION;
584
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200585 return settings;
586}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200587
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200588static u32 get_current_settings(struct hci_dev *hdev)
589{
590 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200591
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200592 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100593 settings |= MGMT_SETTING_POWERED;
594
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200595 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200596 settings |= MGMT_SETTING_CONNECTABLE;
597
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500598 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
599 settings |= MGMT_SETTING_FAST_CONNECTABLE;
600
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200601 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200602 settings |= MGMT_SETTING_DISCOVERABLE;
603
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300604 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300605 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200606
Johan Hedberg56f87902013-10-02 13:43:13 +0300607 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200608 settings |= MGMT_SETTING_BREDR;
609
Johan Hedberg06199cf2012-02-22 16:37:11 +0200610 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200611 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200612
Johan Hedberg47990ea2012-02-22 11:58:37 +0200613 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200615
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200616 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200618
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200619 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
620 settings |= MGMT_SETTING_HS;
621
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200622 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300623 settings |= MGMT_SETTING_ADVERTISING;
624
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800625 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
626 settings |= MGMT_SETTING_SECURE_CONN;
627
Johan Hedberg0663b292014-06-24 13:15:50 +0300628 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800629 settings |= MGMT_SETTING_DEBUG_KEYS;
630
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200631 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
632 settings |= MGMT_SETTING_PRIVACY;
633
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200634 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200635}
636
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300637#define PNP_INFO_SVCLASS_ID 0x1200
638
Johan Hedberg213202e2013-01-27 00:31:33 +0200639static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
640{
641 u8 *ptr = data, *uuids_start = NULL;
642 struct bt_uuid *uuid;
643
644 if (len < 4)
645 return ptr;
646
647 list_for_each_entry(uuid, &hdev->uuids, list) {
648 u16 uuid16;
649
650 if (uuid->size != 16)
651 continue;
652
653 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
654 if (uuid16 < 0x1100)
655 continue;
656
657 if (uuid16 == PNP_INFO_SVCLASS_ID)
658 continue;
659
660 if (!uuids_start) {
661 uuids_start = ptr;
662 uuids_start[0] = 1;
663 uuids_start[1] = EIR_UUID16_ALL;
664 ptr += 2;
665 }
666
667 /* Stop if not enough space to put next UUID */
668 if ((ptr - data) + sizeof(u16) > len) {
669 uuids_start[1] = EIR_UUID16_SOME;
670 break;
671 }
672
673 *ptr++ = (uuid16 & 0x00ff);
674 *ptr++ = (uuid16 & 0xff00) >> 8;
675 uuids_start[0] += sizeof(uuid16);
676 }
677
678 return ptr;
679}
680
Johan Hedbergcdf19632013-01-27 00:31:34 +0200681static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
682{
683 u8 *ptr = data, *uuids_start = NULL;
684 struct bt_uuid *uuid;
685
686 if (len < 6)
687 return ptr;
688
689 list_for_each_entry(uuid, &hdev->uuids, list) {
690 if (uuid->size != 32)
691 continue;
692
693 if (!uuids_start) {
694 uuids_start = ptr;
695 uuids_start[0] = 1;
696 uuids_start[1] = EIR_UUID32_ALL;
697 ptr += 2;
698 }
699
700 /* Stop if not enough space to put next UUID */
701 if ((ptr - data) + sizeof(u32) > len) {
702 uuids_start[1] = EIR_UUID32_SOME;
703 break;
704 }
705
706 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
707 ptr += sizeof(u32);
708 uuids_start[0] += sizeof(u32);
709 }
710
711 return ptr;
712}
713
Johan Hedbergc00d5752013-01-27 00:31:35 +0200714static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
715{
716 u8 *ptr = data, *uuids_start = NULL;
717 struct bt_uuid *uuid;
718
719 if (len < 18)
720 return ptr;
721
722 list_for_each_entry(uuid, &hdev->uuids, list) {
723 if (uuid->size != 128)
724 continue;
725
726 if (!uuids_start) {
727 uuids_start = ptr;
728 uuids_start[0] = 1;
729 uuids_start[1] = EIR_UUID128_ALL;
730 ptr += 2;
731 }
732
733 /* Stop if not enough space to put next UUID */
734 if ((ptr - data) + 16 > len) {
735 uuids_start[1] = EIR_UUID128_SOME;
736 break;
737 }
738
739 memcpy(ptr, uuid->uuid, 16);
740 ptr += 16;
741 uuids_start[0] += 16;
742 }
743
744 return ptr;
745}
746
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300747static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
748{
749 struct pending_cmd *cmd;
750
751 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
752 if (cmd->opcode == opcode)
753 return cmd;
754 }
755
756 return NULL;
757}
758
Johan Hedberg95868422014-06-28 17:54:07 +0300759static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
760 struct hci_dev *hdev,
761 const void *data)
762{
763 struct pending_cmd *cmd;
764
765 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
766 if (cmd->user_data != data)
767 continue;
768 if (cmd->opcode == opcode)
769 return cmd;
770 }
771
772 return NULL;
773}
774
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700775static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
776{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700777 u8 ad_len = 0;
778 size_t name_len;
779
780 name_len = strlen(hdev->dev_name);
781 if (name_len > 0) {
782 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
783
784 if (name_len > max_len) {
785 name_len = max_len;
786 ptr[1] = EIR_NAME_SHORT;
787 } else
788 ptr[1] = EIR_NAME_COMPLETE;
789
790 ptr[0] = name_len + 1;
791
792 memcpy(ptr + 2, hdev->dev_name, name_len);
793
794 ad_len += (name_len + 2);
795 ptr += (name_len + 2);
796 }
797
798 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700799}
800
801static void update_scan_rsp_data(struct hci_request *req)
802{
803 struct hci_dev *hdev = req->hdev;
804 struct hci_cp_le_set_scan_rsp_data cp;
805 u8 len;
806
Johan Hedberg7751ef12013-10-19 23:38:15 +0300807 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700808 return;
809
810 memset(&cp, 0, sizeof(cp));
811
812 len = create_scan_rsp_data(hdev, cp.data);
813
Johan Hedbergeb438b52013-10-16 15:31:07 +0300814 if (hdev->scan_rsp_data_len == len &&
815 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700816 return;
817
Johan Hedbergeb438b52013-10-16 15:31:07 +0300818 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
819 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700820
821 cp.length = len;
822
823 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
824}
825
Johan Hedberg9a43e252013-10-20 19:00:07 +0300826static u8 get_adv_discov_flags(struct hci_dev *hdev)
827{
828 struct pending_cmd *cmd;
829
830 /* If there's a pending mgmt command the flags will not yet have
831 * their final values, so check for this first.
832 */
833 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
834 if (cmd) {
835 struct mgmt_mode *cp = cmd->param;
836 if (cp->val == 0x01)
837 return LE_AD_GENERAL;
838 else if (cp->val == 0x02)
839 return LE_AD_LIMITED;
840 } else {
841 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
842 return LE_AD_LIMITED;
843 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_GENERAL;
845 }
846
847 return 0;
848}
849
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700850static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700851{
852 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853
Johan Hedberg9a43e252013-10-20 19:00:07 +0300854 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberge8340042014-01-30 11:16:50 -0800856 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858
859 if (flags) {
860 BT_DBG("adv flags 0x%02x", flags);
861
862 ptr[0] = 2;
863 ptr[1] = EIR_FLAGS;
864 ptr[2] = flags;
865
866 ad_len += 3;
867 ptr += 3;
868 }
869
870 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
871 ptr[0] = 2;
872 ptr[1] = EIR_TX_POWER;
873 ptr[2] = (u8) hdev->adv_tx_power;
874
875 ad_len += 3;
876 ptr += 3;
877 }
878
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700879 return ad_len;
880}
881
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700882static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700883{
884 struct hci_dev *hdev = req->hdev;
885 struct hci_cp_le_set_adv_data cp;
886 u8 len;
887
Johan Hedberg10994ce2013-10-19 23:38:16 +0300888 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700889 return;
890
891 memset(&cp, 0, sizeof(cp));
892
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700893 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700894
895 if (hdev->adv_data_len == len &&
896 memcmp(cp.data, hdev->adv_data, len) == 0)
897 return;
898
899 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
900 hdev->adv_data_len = len;
901
902 cp.length = len;
903
904 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
905}
906
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300907int mgmt_update_adv_data(struct hci_dev *hdev)
908{
909 struct hci_request req;
910
911 hci_req_init(&req, hdev);
912 update_adv_data(&req);
913
914 return hci_req_run(&req, NULL);
915}
916
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300917static void create_eir(struct hci_dev *hdev, u8 *data)
918{
919 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300920 size_t name_len;
921
922 name_len = strlen(hdev->dev_name);
923
924 if (name_len > 0) {
925 /* EIR Data type */
926 if (name_len > 48) {
927 name_len = 48;
928 ptr[1] = EIR_NAME_SHORT;
929 } else
930 ptr[1] = EIR_NAME_COMPLETE;
931
932 /* EIR Data length */
933 ptr[0] = name_len + 1;
934
935 memcpy(ptr + 2, hdev->dev_name, name_len);
936
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300937 ptr += (name_len + 2);
938 }
939
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100940 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700941 ptr[0] = 2;
942 ptr[1] = EIR_TX_POWER;
943 ptr[2] = (u8) hdev->inq_tx_power;
944
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700945 ptr += 3;
946 }
947
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700948 if (hdev->devid_source > 0) {
949 ptr[0] = 9;
950 ptr[1] = EIR_DEVICE_ID;
951
952 put_unaligned_le16(hdev->devid_source, ptr + 2);
953 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
954 put_unaligned_le16(hdev->devid_product, ptr + 6);
955 put_unaligned_le16(hdev->devid_version, ptr + 8);
956
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700957 ptr += 10;
958 }
959
Johan Hedberg213202e2013-01-27 00:31:33 +0200960 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200961 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200962 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300963}
964
Johan Hedberg890ea892013-03-15 17:06:52 -0500965static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300966{
Johan Hedberg890ea892013-03-15 17:06:52 -0500967 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300968 struct hci_cp_write_eir cp;
969
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200970 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500971 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200972
Johan Hedberg976eb202012-10-24 21:12:01 +0300973 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500974 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300975
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200976 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500977 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300978
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200979 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981
982 memset(&cp, 0, sizeof(cp));
983
984 create_eir(hdev, cp.data);
985
986 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500987 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300988
989 memcpy(hdev->eir, cp.data, sizeof(cp.data));
990
Johan Hedberg890ea892013-03-15 17:06:52 -0500991 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300992}
993
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200994static u8 get_service_classes(struct hci_dev *hdev)
995{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300996 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200997 u8 val = 0;
998
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300999 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001001
1002 return val;
1003}
1004
Johan Hedberg890ea892013-03-15 17:06:52 -05001005static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001006{
Johan Hedberg890ea892013-03-15 17:06:52 -05001007 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001008 u8 cod[3];
1009
1010 BT_DBG("%s", hdev->name);
1011
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001012 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001013 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001014
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001015 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1016 return;
1017
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001018 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001019 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001020
1021 cod[0] = hdev->minor_class;
1022 cod[1] = hdev->major_class;
1023 cod[2] = get_service_classes(hdev);
1024
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001025 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1026 cod[1] |= 0x20;
1027
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001028 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001029 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030
Johan Hedberg890ea892013-03-15 17:06:52 -05001031 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001032}
1033
Johan Hedberga4858cb2014-02-25 19:56:31 +02001034static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001035{
1036 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037
1038 /* If there's a pending mgmt command the flag will not yet have
1039 * it's final value, so check for this first.
1040 */
1041 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1042 if (cmd) {
1043 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001044 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001045 }
1046
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048}
1049
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001050static void disable_advertising(struct hci_request *req)
1051{
1052 u8 enable = 0x00;
1053
1054 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1055}
1056
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001057static void enable_advertising(struct hci_request *req)
1058{
1059 struct hci_dev *hdev = req->hdev;
1060 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001061 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001062 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001063
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001064 if (hci_conn_num(hdev, LE_LINK) > 0)
1065 return;
1066
1067 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1068 disable_advertising(req);
1069
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001070 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001071 * hci_update_random_address knows that it's safe to go ahead
1072 * and write a new random address. The flag will be set back on
1073 * as soon as the SET_ADV_ENABLE HCI command completes.
1074 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001075 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001076
Johan Hedberga4858cb2014-02-25 19:56:31 +02001077 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001078
Johan Hedberga4858cb2014-02-25 19:56:31 +02001079 /* Set require_privacy to true only when non-connectable
1080 * advertising is used. In that case it is fine to use a
1081 * non-resolvable private address.
1082 */
1083 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001084 return;
1085
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001086 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001087 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1088 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001089 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001090 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001091 cp.channel_map = hdev->le_adv_channel_map;
1092
1093 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1094
1095 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1096}
1097
Johan Hedberg7d785252011-12-15 00:47:39 +02001098static void service_cache_off(struct work_struct *work)
1099{
1100 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001101 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001102 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001103
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001104 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001105 return;
1106
Johan Hedberg890ea892013-03-15 17:06:52 -05001107 hci_req_init(&req, hdev);
1108
Johan Hedberg7d785252011-12-15 00:47:39 +02001109 hci_dev_lock(hdev);
1110
Johan Hedberg890ea892013-03-15 17:06:52 -05001111 update_eir(&req);
1112 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001113
1114 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001115
1116 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001117}
1118
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001119static void rpa_expired(struct work_struct *work)
1120{
1121 struct hci_dev *hdev = container_of(work, struct hci_dev,
1122 rpa_expired.work);
1123 struct hci_request req;
1124
1125 BT_DBG("");
1126
1127 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1128
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001129 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001130 return;
1131
1132 /* The generation of a new RPA and programming it into the
1133 * controller happens in the enable_advertising() function.
1134 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001135 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001136 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 hci_req_run(&req, NULL);
1138}
1139
Johan Hedberg6a919082012-02-28 06:17:26 +02001140static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001141{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001142 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001143 return;
1144
Johan Hedberg4f87da82012-03-02 19:55:56 +02001145 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001146 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001147
Johan Hedberg4f87da82012-03-02 19:55:56 +02001148 /* Non-mgmt controlled devices get this bit set
1149 * implicitly so that pairing works for them, however
1150 * for mgmt we require user-space to explicitly enable
1151 * it
1152 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001153 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001154}
1155
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001156static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001157 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001158{
1159 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001160
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001161 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001162
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001163 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001164
Johan Hedberg03811012010-12-08 00:21:06 +02001165 memset(&rp, 0, sizeof(rp));
1166
Johan Hedberg03811012010-12-08 00:21:06 +02001167 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001168
1169 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001170 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001171
1172 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1173 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1174
1175 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001176
1177 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001178 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001179
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001180 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001181
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001182 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001183 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001184}
1185
1186static void mgmt_pending_free(struct pending_cmd *cmd)
1187{
1188 sock_put(cmd->sk);
1189 kfree(cmd->param);
1190 kfree(cmd);
1191}
1192
1193static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001194 struct hci_dev *hdev, void *data,
1195 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001196{
1197 struct pending_cmd *cmd;
1198
Johan Hedbergfca20012014-06-28 17:54:05 +03001199 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001200 if (!cmd)
1201 return NULL;
1202
1203 cmd->opcode = opcode;
1204 cmd->index = hdev->id;
1205
Andre Guedes12b94562012-06-07 19:05:45 -03001206 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001207 if (!cmd->param) {
1208 kfree(cmd);
1209 return NULL;
1210 }
1211
1212 if (data)
1213 memcpy(cmd->param, data, len);
1214
1215 cmd->sk = sk;
1216 sock_hold(sk);
1217
1218 list_add(&cmd->list, &hdev->mgmt_pending);
1219
1220 return cmd;
1221}
1222
1223static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001224 void (*cb)(struct pending_cmd *cmd,
1225 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001226 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001227{
Andre Guedesa3d09352013-02-01 11:21:30 -03001228 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001229
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001231 if (opcode > 0 && cmd->opcode != opcode)
1232 continue;
1233
1234 cb(cmd, data);
1235 }
1236}
1237
Johan Hedberg03811012010-12-08 00:21:06 +02001238static void mgmt_pending_remove(struct pending_cmd *cmd)
1239{
1240 list_del(&cmd->list);
1241 mgmt_pending_free(cmd);
1242}
1243
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001244static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001245{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001247
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001248 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001249 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001250}
1251
Johan Hedberg8b064a32014-02-24 14:52:22 +02001252static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1253{
1254 BT_DBG("%s status 0x%02x", hdev->name, status);
1255
Johan Hedberga3172b72014-02-28 09:33:44 +02001256 if (hci_conn_count(hdev) == 0) {
1257 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001258 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001259 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260}
1261
Johan Hedberg23a48092014-07-08 16:05:06 +03001262static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001263{
1264 struct hci_dev *hdev = req->hdev;
1265 struct hci_cp_remote_name_req_cancel cp;
1266 struct inquiry_entry *e;
1267
1268 switch (hdev->discovery.state) {
1269 case DISCOVERY_FINDING:
1270 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1271 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1272 } else {
1273 cancel_delayed_work(&hdev->le_scan_disable);
1274 hci_req_add_le_scan_disable(req);
1275 }
1276
Johan Hedberg23a48092014-07-08 16:05:06 +03001277 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001278
1279 case DISCOVERY_RESOLVING:
1280 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1281 NAME_PENDING);
1282 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001283 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001284
1285 bacpy(&cp.bdaddr, &e->data.bdaddr);
1286 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1287 &cp);
1288
Johan Hedberg23a48092014-07-08 16:05:06 +03001289 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001290
1291 default:
1292 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001293 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001294 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 return true;
1296 }
1297
Johan Hedberg21a60d32014-06-10 14:05:58 +03001298 break;
1299 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001300
1301 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001302}
1303
Johan Hedberg8b064a32014-02-24 14:52:22 +02001304static int clean_up_hci_state(struct hci_dev *hdev)
1305{
1306 struct hci_request req;
1307 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001308 bool discov_stopped;
1309 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001310
1311 hci_req_init(&req, hdev);
1312
1313 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1314 test_bit(HCI_PSCAN, &hdev->flags)) {
1315 u8 scan = 0x00;
1316 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1317 }
1318
Johan Hedberg73e082f2014-07-08 15:07:51 +03001319 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001320 disable_advertising(&req);
1321
Johan Hedberg23a48092014-07-08 16:05:06 +03001322 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001323
1324 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1325 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001326 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001327
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 switch (conn->state) {
1329 case BT_CONNECTED:
1330 case BT_CONFIG:
1331 dc.handle = cpu_to_le16(conn->handle);
1332 dc.reason = 0x15; /* Terminated due to Power Off */
1333 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1334 break;
1335 case BT_CONNECT:
1336 if (conn->type == LE_LINK)
1337 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1338 0, NULL);
1339 else if (conn->type == ACL_LINK)
1340 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1341 6, &conn->dst);
1342 break;
1343 case BT_CONNECT2:
1344 bacpy(&rej.bdaddr, &conn->dst);
1345 rej.reason = 0x15; /* Terminated due to Power Off */
1346 if (conn->type == ACL_LINK)
1347 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1348 sizeof(rej), &rej);
1349 else if (conn->type == SCO_LINK)
1350 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1351 sizeof(rej), &rej);
1352 break;
1353 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001354 }
1355
Johan Hedberg23a48092014-07-08 16:05:06 +03001356 err = hci_req_run(&req, clean_up_hci_complete);
1357 if (!err && discov_stopped)
1358 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1359
1360 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001361}
1362
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001363static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001364 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001365{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001366 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001367 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001368 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001369
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001370 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedberga7e80f22013-01-09 16:05:19 +02001372 if (cp->val != 0x00 && cp->val != 0x01)
1373 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1374 MGMT_STATUS_INVALID_PARAMS);
1375
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001376 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001377
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001378 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1379 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1380 MGMT_STATUS_BUSY);
1381 goto failed;
1382 }
1383
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001384 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1385 cancel_delayed_work(&hdev->power_off);
1386
1387 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001388 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1389 data, len);
1390 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001391 goto failed;
1392 }
1393 }
1394
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001395 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001396 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001397 goto failed;
1398 }
1399
Johan Hedberg03811012010-12-08 00:21:06 +02001400 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1401 if (!cmd) {
1402 err = -ENOMEM;
1403 goto failed;
1404 }
1405
Johan Hedberg8b064a32014-02-24 14:52:22 +02001406 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001407 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 err = 0;
1409 } else {
1410 /* Disconnect connections, stop scans, etc */
1411 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001412 if (!err)
1413 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1414 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001415
Johan Hedberg8b064a32014-02-24 14:52:22 +02001416 /* ENODATA means there were no HCI commands queued */
1417 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001418 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001419 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1420 err = 0;
1421 }
1422 }
Johan Hedberg03811012010-12-08 00:21:06 +02001423
1424failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001425 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001426 return err;
1427}
1428
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001429static int new_settings(struct hci_dev *hdev, struct sock *skip)
1430{
1431 __le32 ev;
1432
1433 ev = cpu_to_le32(get_current_settings(hdev));
1434
1435 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1436}
1437
Johan Hedberg91a668b2014-07-09 13:28:26 +03001438int mgmt_new_settings(struct hci_dev *hdev)
1439{
1440 return new_settings(hdev, NULL);
1441}
1442
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001443struct cmd_lookup {
1444 struct sock *sk;
1445 struct hci_dev *hdev;
1446 u8 mgmt_status;
1447};
1448
1449static void settings_rsp(struct pending_cmd *cmd, void *data)
1450{
1451 struct cmd_lookup *match = data;
1452
1453 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1454
1455 list_del(&cmd->list);
1456
1457 if (match->sk == NULL) {
1458 match->sk = cmd->sk;
1459 sock_hold(match->sk);
1460 }
1461
1462 mgmt_pending_free(cmd);
1463}
1464
1465static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1466{
1467 u8 *status = data;
1468
1469 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1470 mgmt_pending_remove(cmd);
1471}
1472
Johan Hedberge6fe7982013-10-02 15:45:22 +03001473static u8 mgmt_bredr_support(struct hci_dev *hdev)
1474{
1475 if (!lmp_bredr_capable(hdev))
1476 return MGMT_STATUS_NOT_SUPPORTED;
1477 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1478 return MGMT_STATUS_REJECTED;
1479 else
1480 return MGMT_STATUS_SUCCESS;
1481}
1482
1483static u8 mgmt_le_support(struct hci_dev *hdev)
1484{
1485 if (!lmp_le_capable(hdev))
1486 return MGMT_STATUS_NOT_SUPPORTED;
1487 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1488 return MGMT_STATUS_REJECTED;
1489 else
1490 return MGMT_STATUS_SUCCESS;
1491}
1492
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001493static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1494{
1495 struct pending_cmd *cmd;
1496 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001497 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001498 bool changed;
1499
1500 BT_DBG("status 0x%02x", status);
1501
1502 hci_dev_lock(hdev);
1503
1504 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1505 if (!cmd)
1506 goto unlock;
1507
1508 if (status) {
1509 u8 mgmt_err = mgmt_status(status);
1510 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001511 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001512 goto remove_cmd;
1513 }
1514
1515 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001516 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001517 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1518 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001519
1520 if (hdev->discov_timeout > 0) {
1521 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1522 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1523 to);
1524 }
1525 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1527 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001528 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001529
1530 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1531
1532 if (changed)
1533 new_settings(hdev, cmd->sk);
1534
Marcel Holtmann970ba522013-10-15 06:33:57 -07001535 /* When the discoverable mode gets changed, make sure
1536 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001537 * bit correctly set. Also update page scan based on whitelist
1538 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001539 */
1540 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001541 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001542 update_class(&req);
1543 hci_req_run(&req, NULL);
1544
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545remove_cmd:
1546 mgmt_pending_remove(cmd);
1547
1548unlock:
1549 hci_dev_unlock(hdev);
1550}
1551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001552static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001553 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001554{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001555 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001556 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001558 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001559 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001560 int err;
1561
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001562 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001563
Johan Hedberg9a43e252013-10-20 19:00:07 +03001564 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1565 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001566 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001567 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001568
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001569 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1571 MGMT_STATUS_INVALID_PARAMS);
1572
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001573 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001574
1575 /* Disabling discoverable requires that no timeout is set,
1576 * and enabling limited discoverable requires a timeout.
1577 */
1578 if ((cp->val == 0x00 && timeout > 0) ||
1579 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001582
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001583 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001584
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001585 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001586 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001587 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001588 goto failed;
1589 }
1590
1591 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001592 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001593 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001594 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001595 goto failed;
1596 }
1597
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001598 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001599 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001600 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001601 goto failed;
1602 }
1603
1604 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001605 bool changed = false;
1606
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001607 /* Setting limited discoverable when powered off is
1608 * not a valid operation since it requires a timeout
1609 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1610 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001611 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1612 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1613 changed = true;
1614 }
1615
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001616 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001617 if (err < 0)
1618 goto failed;
1619
1620 if (changed)
1621 err = new_settings(hdev, sk);
1622
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001623 goto failed;
1624 }
1625
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001626 /* If the current mode is the same, then just update the timeout
1627 * value with the new value. And if only the timeout gets updated,
1628 * then no need for any HCI transactions.
1629 */
1630 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1631 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1632 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001633 cancel_delayed_work(&hdev->discov_off);
1634 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001635
Marcel Holtmann36261542013-10-15 08:28:51 -07001636 if (cp->val && hdev->discov_timeout > 0) {
1637 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001638 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001639 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001640 }
1641
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001642 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001643 goto failed;
1644 }
1645
1646 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1647 if (!cmd) {
1648 err = -ENOMEM;
1649 goto failed;
1650 }
1651
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001652 /* Cancel any potential discoverable timeout that might be
1653 * still active and store new timeout value. The arming of
1654 * the timeout happens in the complete handler.
1655 */
1656 cancel_delayed_work(&hdev->discov_off);
1657 hdev->discov_timeout = timeout;
1658
Johan Hedbergb456f872013-10-19 23:38:22 +03001659 /* Limited discoverable mode */
1660 if (cp->val == 0x02)
1661 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1662 else
1663 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1664
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001665 hci_req_init(&req, hdev);
1666
Johan Hedberg9a43e252013-10-20 19:00:07 +03001667 /* The procedure for LE-only controllers is much simpler - just
1668 * update the advertising data.
1669 */
1670 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1671 goto update_ad;
1672
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001673 scan = SCAN_PAGE;
1674
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001675 if (cp->val) {
1676 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001677
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001678 if (cp->val == 0x02) {
1679 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001680 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001681 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1682 hci_cp.iac_lap[1] = 0x8b;
1683 hci_cp.iac_lap[2] = 0x9e;
1684 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1685 hci_cp.iac_lap[4] = 0x8b;
1686 hci_cp.iac_lap[5] = 0x9e;
1687 } else {
1688 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001689 hci_cp.num_iac = 1;
1690 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1691 hci_cp.iac_lap[1] = 0x8b;
1692 hci_cp.iac_lap[2] = 0x9e;
1693 }
1694
1695 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1696 (hci_cp.num_iac * 3) + 1, &hci_cp);
1697
1698 scan |= SCAN_INQUIRY;
1699 } else {
1700 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1701 }
1702
1703 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001704
Johan Hedberg9a43e252013-10-20 19:00:07 +03001705update_ad:
1706 update_adv_data(&req);
1707
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001708 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001709 if (err < 0)
1710 mgmt_pending_remove(cmd);
1711
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001712failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001713 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001714 return err;
1715}
1716
Johan Hedberg406d7802013-03-15 17:07:09 -05001717static void write_fast_connectable(struct hci_request *req, bool enable)
1718{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001719 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001720 struct hci_cp_write_page_scan_activity acp;
1721 u8 type;
1722
Johan Hedberg547003b2013-10-21 16:51:53 +03001723 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1724 return;
1725
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001726 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1727 return;
1728
Johan Hedberg406d7802013-03-15 17:07:09 -05001729 if (enable) {
1730 type = PAGE_SCAN_TYPE_INTERLACED;
1731
1732 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001733 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001734 } else {
1735 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1736
1737 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001738 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001739 }
1740
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001741 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001742
Johan Hedbergbd98b992013-03-15 17:07:13 -05001743 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1744 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1745 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1746 sizeof(acp), &acp);
1747
1748 if (hdev->page_scan_type != type)
1749 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001750}
1751
Johan Hedberg2b76f452013-03-15 17:07:04 -05001752static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1753{
1754 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001755 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001756 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001757
1758 BT_DBG("status 0x%02x", status);
1759
1760 hci_dev_lock(hdev);
1761
1762 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1763 if (!cmd)
1764 goto unlock;
1765
Johan Hedberg37438c12013-10-14 16:20:05 +03001766 if (status) {
1767 u8 mgmt_err = mgmt_status(status);
1768 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1769 goto remove_cmd;
1770 }
1771
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001772 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001773 if (cp->val) {
1774 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1775 &hdev->dev_flags);
1776 discov_changed = false;
1777 } else {
1778 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1779 &hdev->dev_flags);
1780 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1781 &hdev->dev_flags);
1782 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783
Johan Hedberg2b76f452013-03-15 17:07:04 -05001784 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1785
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001786 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001787 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001788 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001789 if (discov_changed)
1790 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001791 hci_update_background_scan(hdev);
1792 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001793
Johan Hedberg37438c12013-10-14 16:20:05 +03001794remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001795 mgmt_pending_remove(cmd);
1796
1797unlock:
1798 hci_dev_unlock(hdev);
1799}
1800
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001801static int set_connectable_update_settings(struct hci_dev *hdev,
1802 struct sock *sk, u8 val)
1803{
1804 bool changed = false;
1805 int err;
1806
1807 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1808 changed = true;
1809
1810 if (val) {
1811 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1812 } else {
1813 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1814 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1815 }
1816
1817 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1818 if (err < 0)
1819 return err;
1820
Johan Hedberg562064e2014-07-08 16:35:34 +03001821 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001822 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001823 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001824 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001825 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001826
1827 return 0;
1828}
1829
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001830static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001831 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001832{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001833 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001834 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001835 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001836 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001837 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001838
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001839 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001840
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001841 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1842 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001843 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001844 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001845
Johan Hedberga7e80f22013-01-09 16:05:19 +02001846 if (cp->val != 0x00 && cp->val != 0x01)
1847 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1848 MGMT_STATUS_INVALID_PARAMS);
1849
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001850 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001851
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001852 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001853 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001854 goto failed;
1855 }
1856
1857 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001858 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001859 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001860 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001861 goto failed;
1862 }
1863
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001864 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1865 if (!cmd) {
1866 err = -ENOMEM;
1867 goto failed;
1868 }
1869
Johan Hedberg2b76f452013-03-15 17:07:04 -05001870 hci_req_init(&req, hdev);
1871
Johan Hedberg9a43e252013-10-20 19:00:07 +03001872 /* If BR/EDR is not enabled and we disable advertising as a
1873 * by-product of disabling connectable, we need to update the
1874 * advertising flags.
1875 */
1876 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1877 if (!cp->val) {
1878 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1879 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1880 }
1881 update_adv_data(&req);
1882 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001883 if (cp->val) {
1884 scan = SCAN_PAGE;
1885 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001886 /* If we don't have any whitelist entries just
1887 * disable all scanning. If there are entries
1888 * and we had both page and inquiry scanning
1889 * enabled then fall back to only page scanning.
1890 * Otherwise no changes are needed.
1891 */
1892 if (list_empty(&hdev->whitelist))
1893 scan = SCAN_DISABLED;
1894 else if (test_bit(HCI_ISCAN, &hdev->flags))
1895 scan = SCAN_PAGE;
1896 else
1897 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001898
1899 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001900 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001901 cancel_delayed_work(&hdev->discov_off);
1902 }
1903
1904 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1905 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001906
Johan Hedberg3bd27242014-07-28 20:53:58 +03001907no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001908 /* If we're going from non-connectable to connectable or
1909 * vice-versa when fast connectable is enabled ensure that fast
1910 * connectable gets disabled. write_fast_connectable won't do
1911 * anything if the page scan parameters are already what they
1912 * should be.
1913 */
1914 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001915 write_fast_connectable(&req, false);
1916
Johan Hedberge8b12022014-07-10 10:51:27 +03001917 /* Update the advertising parameters if necessary */
1918 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001919 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001920
Johan Hedberg2b76f452013-03-15 17:07:04 -05001921 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001922 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001923 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001924 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001925 err = set_connectable_update_settings(hdev, sk,
1926 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001927 goto failed;
1928 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001929
1930failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001931 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001932 return err;
1933}
1934
Johan Hedbergb2939472014-07-30 09:22:23 +03001935static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001936 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001937{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001938 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001939 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001940 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001941
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001942 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001943
Johan Hedberga7e80f22013-01-09 16:05:19 +02001944 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001945 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001946 MGMT_STATUS_INVALID_PARAMS);
1947
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001948 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001949
1950 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001951 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001952 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001953 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001954
Johan Hedbergb2939472014-07-30 09:22:23 +03001955 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001956 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001957 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001958
Marcel Holtmann55594352013-10-06 16:11:57 -07001959 if (changed)
1960 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001961
Marcel Holtmann55594352013-10-06 16:11:57 -07001962unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001963 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001964 return err;
1965}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001966
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001967static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1968 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001969{
1970 struct mgmt_mode *cp = data;
1971 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001972 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001973 int err;
1974
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001975 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001976
Johan Hedberge6fe7982013-10-02 15:45:22 +03001977 status = mgmt_bredr_support(hdev);
1978 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001979 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001980 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001981
Johan Hedberga7e80f22013-01-09 16:05:19 +02001982 if (cp->val != 0x00 && cp->val != 0x01)
1983 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1984 MGMT_STATUS_INVALID_PARAMS);
1985
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001986 hci_dev_lock(hdev);
1987
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001988 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001989 bool changed = false;
1990
1991 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001992 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001993 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1994 changed = true;
1995 }
1996
1997 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1998 if (err < 0)
1999 goto failed;
2000
2001 if (changed)
2002 err = new_settings(hdev, sk);
2003
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002004 goto failed;
2005 }
2006
2007 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002008 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002009 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002010 goto failed;
2011 }
2012
2013 val = !!cp->val;
2014
2015 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2016 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2017 goto failed;
2018 }
2019
2020 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2021 if (!cmd) {
2022 err = -ENOMEM;
2023 goto failed;
2024 }
2025
2026 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2027 if (err < 0) {
2028 mgmt_pending_remove(cmd);
2029 goto failed;
2030 }
2031
2032failed:
2033 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002034 return err;
2035}
2036
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002037static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002038{
2039 struct mgmt_mode *cp = data;
2040 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002041 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002042 int err;
2043
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002044 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002045
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002046 status = mgmt_bredr_support(hdev);
2047 if (status)
2048 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2049
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002050 if (!lmp_ssp_capable(hdev))
2051 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2052 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002053
Johan Hedberga7e80f22013-01-09 16:05:19 +02002054 if (cp->val != 0x00 && cp->val != 0x01)
2055 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2056 MGMT_STATUS_INVALID_PARAMS);
2057
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002058 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002059
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002060 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002061 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002062
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002063 if (cp->val) {
2064 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2065 &hdev->dev_flags);
2066 } else {
2067 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2068 &hdev->dev_flags);
2069 if (!changed)
2070 changed = test_and_clear_bit(HCI_HS_ENABLED,
2071 &hdev->dev_flags);
2072 else
2073 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002074 }
2075
2076 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2077 if (err < 0)
2078 goto failed;
2079
2080 if (changed)
2081 err = new_settings(hdev, sk);
2082
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002083 goto failed;
2084 }
2085
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002086 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2087 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002088 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2089 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002090 goto failed;
2091 }
2092
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002093 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002094 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2095 goto failed;
2096 }
2097
2098 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2099 if (!cmd) {
2100 err = -ENOMEM;
2101 goto failed;
2102 }
2103
Johan Hedberg37699722014-06-24 14:00:27 +03002104 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2105 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2106 sizeof(cp->val), &cp->val);
2107
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002108 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002109 if (err < 0) {
2110 mgmt_pending_remove(cmd);
2111 goto failed;
2112 }
2113
2114failed:
2115 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002116 return err;
2117}
2118
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002119static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002120{
2121 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002122 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002123 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002124 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002125
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002126 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002127
Johan Hedberge6fe7982013-10-02 15:45:22 +03002128 status = mgmt_bredr_support(hdev);
2129 if (status)
2130 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002131
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002132 if (!lmp_ssp_capable(hdev))
2133 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2134 MGMT_STATUS_NOT_SUPPORTED);
2135
2136 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2137 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2138 MGMT_STATUS_REJECTED);
2139
Johan Hedberga7e80f22013-01-09 16:05:19 +02002140 if (cp->val != 0x00 && cp->val != 0x01)
2141 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2142 MGMT_STATUS_INVALID_PARAMS);
2143
Marcel Holtmannee392692013-10-01 22:59:23 -07002144 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002145
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002146 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002147 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002148 } else {
2149 if (hdev_is_powered(hdev)) {
2150 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2151 MGMT_STATUS_REJECTED);
2152 goto unlock;
2153 }
2154
Marcel Holtmannee392692013-10-01 22:59:23 -07002155 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002156 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002157
2158 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2159 if (err < 0)
2160 goto unlock;
2161
2162 if (changed)
2163 err = new_settings(hdev, sk);
2164
2165unlock:
2166 hci_dev_unlock(hdev);
2167 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002168}
2169
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002170static void le_enable_complete(struct hci_dev *hdev, u8 status)
2171{
2172 struct cmd_lookup match = { NULL, hdev };
2173
2174 if (status) {
2175 u8 mgmt_err = mgmt_status(status);
2176
2177 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2178 &mgmt_err);
2179 return;
2180 }
2181
2182 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2183
2184 new_settings(hdev, match.sk);
2185
2186 if (match.sk)
2187 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002188
2189 /* Make sure the controller has a good default for
2190 * advertising data. Restrict the update to when LE
2191 * has actually been enabled. During power on, the
2192 * update in powered_update_hci will take care of it.
2193 */
2194 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2195 struct hci_request req;
2196
2197 hci_dev_lock(hdev);
2198
2199 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002200 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002201 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002202 hci_req_run(&req, NULL);
2203
Johan Hedberga70f4b52014-07-07 15:19:50 +03002204 hci_update_background_scan(hdev);
2205
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002206 hci_dev_unlock(hdev);
2207 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002208}
2209
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002210static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002211{
2212 struct mgmt_mode *cp = data;
2213 struct hci_cp_write_le_host_supported hci_cp;
2214 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002215 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002216 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002217 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002218
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002219 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002220
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002221 if (!lmp_le_capable(hdev))
2222 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2223 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002224
Johan Hedberga7e80f22013-01-09 16:05:19 +02002225 if (cp->val != 0x00 && cp->val != 0x01)
2226 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2227 MGMT_STATUS_INVALID_PARAMS);
2228
Johan Hedbergc73eee92013-04-19 18:35:21 +03002229 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002230 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002231 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2232 MGMT_STATUS_REJECTED);
2233
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002234 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002235
2236 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002237 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002238
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002239 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002240 bool changed = false;
2241
2242 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2243 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2244 changed = true;
2245 }
2246
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002247 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2248 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002249 changed = true;
2250 }
2251
Johan Hedberg06199cf2012-02-22 16:37:11 +02002252 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2253 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002254 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002255
2256 if (changed)
2257 err = new_settings(hdev, sk);
2258
Johan Hedberg1de028c2012-02-29 19:55:35 -08002259 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002260 }
2261
Johan Hedberg4375f102013-09-25 13:26:10 +03002262 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2263 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002264 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002265 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002266 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002267 }
2268
2269 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2270 if (!cmd) {
2271 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002272 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002273 }
2274
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002275 hci_req_init(&req, hdev);
2276
Johan Hedberg06199cf2012-02-22 16:37:11 +02002277 memset(&hci_cp, 0, sizeof(hci_cp));
2278
2279 if (val) {
2280 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002281 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002282 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002283 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002284 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002285 }
2286
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002287 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2288 &hci_cp);
2289
2290 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302291 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002292 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002293
Johan Hedberg1de028c2012-02-29 19:55:35 -08002294unlock:
2295 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002296 return err;
2297}
2298
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002299/* This is a helper function to test for pending mgmt commands that can
2300 * cause CoD or EIR HCI commands. We can only allow one such pending
2301 * mgmt command at a time since otherwise we cannot easily track what
2302 * the current values are, will be, and based on that calculate if a new
2303 * HCI command needs to be sent and if yes with what value.
2304 */
2305static bool pending_eir_or_class(struct hci_dev *hdev)
2306{
2307 struct pending_cmd *cmd;
2308
2309 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2310 switch (cmd->opcode) {
2311 case MGMT_OP_ADD_UUID:
2312 case MGMT_OP_REMOVE_UUID:
2313 case MGMT_OP_SET_DEV_CLASS:
2314 case MGMT_OP_SET_POWERED:
2315 return true;
2316 }
2317 }
2318
2319 return false;
2320}
2321
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002322static const u8 bluetooth_base_uuid[] = {
2323 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2324 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2325};
2326
2327static u8 get_uuid_size(const u8 *uuid)
2328{
2329 u32 val;
2330
2331 if (memcmp(uuid, bluetooth_base_uuid, 12))
2332 return 128;
2333
2334 val = get_unaligned_le32(&uuid[12]);
2335 if (val > 0xffff)
2336 return 32;
2337
2338 return 16;
2339}
2340
Johan Hedberg92da6092013-03-15 17:06:55 -05002341static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2342{
2343 struct pending_cmd *cmd;
2344
2345 hci_dev_lock(hdev);
2346
2347 cmd = mgmt_pending_find(mgmt_op, hdev);
2348 if (!cmd)
2349 goto unlock;
2350
2351 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2352 hdev->dev_class, 3);
2353
2354 mgmt_pending_remove(cmd);
2355
2356unlock:
2357 hci_dev_unlock(hdev);
2358}
2359
2360static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2361{
2362 BT_DBG("status 0x%02x", status);
2363
2364 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2365}
2366
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002367static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002368{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002369 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002370 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002371 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002372 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002373 int err;
2374
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002375 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002376
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002377 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002378
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002379 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002380 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002381 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002382 goto failed;
2383 }
2384
Andre Guedes92c4c202012-06-07 19:05:44 -03002385 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002386 if (!uuid) {
2387 err = -ENOMEM;
2388 goto failed;
2389 }
2390
2391 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002392 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002393 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002394
Johan Hedbergde66aa62013-01-27 00:31:27 +02002395 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002396
Johan Hedberg890ea892013-03-15 17:06:52 -05002397 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002398
Johan Hedberg890ea892013-03-15 17:06:52 -05002399 update_class(&req);
2400 update_eir(&req);
2401
Johan Hedberg92da6092013-03-15 17:06:55 -05002402 err = hci_req_run(&req, add_uuid_complete);
2403 if (err < 0) {
2404 if (err != -ENODATA)
2405 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002406
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002407 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002408 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002409 goto failed;
2410 }
2411
2412 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002413 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002414 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002415 goto failed;
2416 }
2417
2418 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002419
2420failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002421 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422 return err;
2423}
2424
Johan Hedberg24b78d02012-02-23 23:24:30 +02002425static bool enable_service_cache(struct hci_dev *hdev)
2426{
2427 if (!hdev_is_powered(hdev))
2428 return false;
2429
2430 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002431 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2432 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002433 return true;
2434 }
2435
2436 return false;
2437}
2438
Johan Hedberg92da6092013-03-15 17:06:55 -05002439static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2440{
2441 BT_DBG("status 0x%02x", status);
2442
2443 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2444}
2445
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002446static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002447 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002448{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002449 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002450 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002451 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002452 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 -05002453 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002454 int err, found;
2455
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002456 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002457
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002458 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002459
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002460 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002461 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002462 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002463 goto unlock;
2464 }
2465
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002466 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002467 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002468
Johan Hedberg24b78d02012-02-23 23:24:30 +02002469 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002470 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002471 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002472 goto unlock;
2473 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002474
Johan Hedberg9246a862012-02-23 21:33:16 +02002475 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002476 }
2477
2478 found = 0;
2479
Johan Hedberg056341c2013-01-27 00:31:30 +02002480 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2482 continue;
2483
2484 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002485 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002486 found++;
2487 }
2488
2489 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002490 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002491 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002492 goto unlock;
2493 }
2494
Johan Hedberg9246a862012-02-23 21:33:16 +02002495update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002496 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002497
Johan Hedberg890ea892013-03-15 17:06:52 -05002498 update_class(&req);
2499 update_eir(&req);
2500
Johan Hedberg92da6092013-03-15 17:06:55 -05002501 err = hci_req_run(&req, remove_uuid_complete);
2502 if (err < 0) {
2503 if (err != -ENODATA)
2504 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002505
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002506 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002507 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002508 goto unlock;
2509 }
2510
2511 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002512 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002513 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002514 goto unlock;
2515 }
2516
2517 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002518
2519unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002520 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002521 return err;
2522}
2523
Johan Hedberg92da6092013-03-15 17:06:55 -05002524static void set_class_complete(struct hci_dev *hdev, u8 status)
2525{
2526 BT_DBG("status 0x%02x", status);
2527
2528 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2529}
2530
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002531static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002532 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002533{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002534 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002535 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002536 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002537 int err;
2538
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002539 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002540
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002541 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002542 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2543 MGMT_STATUS_NOT_SUPPORTED);
2544
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002545 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002546
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002547 if (pending_eir_or_class(hdev)) {
2548 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2549 MGMT_STATUS_BUSY);
2550 goto unlock;
2551 }
2552
2553 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2554 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2555 MGMT_STATUS_INVALID_PARAMS);
2556 goto unlock;
2557 }
2558
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002559 hdev->major_class = cp->major;
2560 hdev->minor_class = cp->minor;
2561
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002562 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002563 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002564 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002565 goto unlock;
2566 }
2567
Johan Hedberg890ea892013-03-15 17:06:52 -05002568 hci_req_init(&req, hdev);
2569
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002570 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002571 hci_dev_unlock(hdev);
2572 cancel_delayed_work_sync(&hdev->service_cache);
2573 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002574 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002575 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002576
Johan Hedberg890ea892013-03-15 17:06:52 -05002577 update_class(&req);
2578
Johan Hedberg92da6092013-03-15 17:06:55 -05002579 err = hci_req_run(&req, set_class_complete);
2580 if (err < 0) {
2581 if (err != -ENODATA)
2582 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002584 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002585 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002586 goto unlock;
2587 }
2588
2589 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002590 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002591 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002592 goto unlock;
2593 }
2594
2595 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002596
Johan Hedbergb5235a62012-02-21 14:32:24 +02002597unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002598 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002599 return err;
2600}
2601
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002602static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002603 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002604{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002605 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002606 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2607 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002608 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002609 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002610 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002611
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002612 BT_DBG("request for %s", hdev->name);
2613
2614 if (!lmp_bredr_capable(hdev))
2615 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2616 MGMT_STATUS_NOT_SUPPORTED);
2617
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002618 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002619 if (key_count > max_key_count) {
2620 BT_ERR("load_link_keys: too big key_count value %u",
2621 key_count);
2622 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2623 MGMT_STATUS_INVALID_PARAMS);
2624 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002625
Johan Hedberg86742e12011-11-07 23:13:38 +02002626 expected_len = sizeof(*cp) + key_count *
2627 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002628 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002629 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002630 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002631 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002632 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002633 }
2634
Johan Hedberg4ae14302013-01-20 14:27:13 +02002635 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2636 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2637 MGMT_STATUS_INVALID_PARAMS);
2638
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002639 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002640 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002641
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002642 for (i = 0; i < key_count; i++) {
2643 struct mgmt_link_key_info *key = &cp->keys[i];
2644
Marcel Holtmann8e991132014-01-10 02:07:25 -08002645 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002646 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2647 MGMT_STATUS_INVALID_PARAMS);
2648 }
2649
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002650 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002651
2652 hci_link_keys_clear(hdev);
2653
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002654 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002655 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2656 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002657 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002658 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2659 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002660
2661 if (changed)
2662 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002663
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002664 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002665 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002666
Johan Hedberg58e92932014-06-24 14:00:26 +03002667 /* Always ignore debug keys and require a new pairing if
2668 * the user wants to use them.
2669 */
2670 if (key->type == HCI_LK_DEBUG_COMBINATION)
2671 continue;
2672
Johan Hedberg7652ff62014-06-24 13:15:49 +03002673 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2674 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002675 }
2676
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002677 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002678
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002679 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002680
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002681 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682}
2683
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002684static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002685 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002686{
2687 struct mgmt_ev_device_unpaired ev;
2688
2689 bacpy(&ev.addr.bdaddr, bdaddr);
2690 ev.addr.type = addr_type;
2691
2692 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002693 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002694}
2695
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002696static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002697 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002698{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002699 struct mgmt_cp_unpair_device *cp = data;
2700 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002701 struct hci_cp_disconnect dc;
2702 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002704 int err;
2705
Johan Hedberga8a1d192011-11-10 15:54:38 +02002706 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002707 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2708 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002709
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002710 if (!bdaddr_type_is_valid(cp->addr.type))
2711 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2712 MGMT_STATUS_INVALID_PARAMS,
2713 &rp, sizeof(rp));
2714
Johan Hedberg118da702013-01-20 14:27:20 +02002715 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2716 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2717 MGMT_STATUS_INVALID_PARAMS,
2718 &rp, sizeof(rp));
2719
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002720 hci_dev_lock(hdev);
2721
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002722 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002723 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002724 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002725 goto unlock;
2726 }
2727
Johan Hedberge0b2b272014-02-18 17:14:31 +02002728 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002729 /* If disconnection is requested, then look up the
2730 * connection. If the remote device is connected, it
2731 * will be later used to terminate the link.
2732 *
2733 * Setting it to NULL explicitly will cause no
2734 * termination of the link.
2735 */
2736 if (cp->disconnect)
2737 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2738 &cp->addr.bdaddr);
2739 else
2740 conn = NULL;
2741
Johan Hedberg124f6e32012-02-09 13:50:12 +02002742 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002743 } else {
2744 u8 addr_type;
2745
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002746 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2747 &cp->addr.bdaddr);
2748 if (conn) {
2749 /* Defer clearing up the connection parameters
2750 * until closing to give a chance of keeping
2751 * them if a repairing happens.
2752 */
2753 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2754
2755 /* If disconnection is not requested, then
2756 * clear the connection variable so that the
2757 * link is not terminated.
2758 */
2759 if (!cp->disconnect)
2760 conn = NULL;
2761 }
2762
Johan Hedberge0b2b272014-02-18 17:14:31 +02002763 if (cp->addr.type == BDADDR_LE_PUBLIC)
2764 addr_type = ADDR_LE_DEV_PUBLIC;
2765 else
2766 addr_type = ADDR_LE_DEV_RANDOM;
2767
Johan Hedberga7ec7332014-02-18 17:14:35 +02002768 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2769
Johan Hedberge0b2b272014-02-18 17:14:31 +02002770 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2771 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002772
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002773 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002774 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002775 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002776 goto unlock;
2777 }
2778
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002779 /* If the connection variable is set, then termination of the
2780 * link is requested.
2781 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002782 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002783 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002784 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002785 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002786 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002787 }
2788
Johan Hedberg124f6e32012-02-09 13:50:12 +02002789 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002790 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002791 if (!cmd) {
2792 err = -ENOMEM;
2793 goto unlock;
2794 }
2795
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002796 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002797 dc.reason = 0x13; /* Remote User Terminated Connection */
2798 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2799 if (err < 0)
2800 mgmt_pending_remove(cmd);
2801
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002802unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002803 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002804 return err;
2805}
2806
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002807static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002808 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002809{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002810 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002811 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002812 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002813 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002814 int err;
2815
2816 BT_DBG("");
2817
Johan Hedberg06a63b12013-01-20 14:27:21 +02002818 memset(&rp, 0, sizeof(rp));
2819 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2820 rp.addr.type = cp->addr.type;
2821
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002822 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002823 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2824 MGMT_STATUS_INVALID_PARAMS,
2825 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002826
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002827 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002828
2829 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002830 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2831 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002832 goto failed;
2833 }
2834
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002835 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002836 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2837 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002838 goto failed;
2839 }
2840
Andre Guedes591f47f2012-04-24 21:02:49 -03002841 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002842 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2843 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002844 else
2845 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002846
Vishal Agarwalf9607272012-06-13 05:32:43 +05302847 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002848 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2849 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002850 goto failed;
2851 }
2852
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002853 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002854 if (!cmd) {
2855 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002856 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002857 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002858
Johan Hedberge3f2f922014-08-18 20:33:33 +03002859 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002860 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002861 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002862
2863failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002864 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002865 return err;
2866}
2867
Andre Guedes57c14772012-04-24 21:02:50 -03002868static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002869{
2870 switch (link_type) {
2871 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002872 switch (addr_type) {
2873 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002874 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002875
Johan Hedberg48264f02011-11-09 13:58:58 +02002876 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002877 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002878 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002879 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002880
Johan Hedberg4c659c32011-11-07 23:13:39 +02002881 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002882 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002883 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002884 }
2885}
2886
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002887static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2888 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002889{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002890 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002891 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002892 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002893 int err;
2894 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002895
2896 BT_DBG("");
2897
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002898 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002899
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002900 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002901 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002902 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002903 goto unlock;
2904 }
2905
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002906 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002907 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2908 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002909 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002910 }
2911
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002912 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002913 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002914 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002915 err = -ENOMEM;
2916 goto unlock;
2917 }
2918
Johan Hedberg2784eb42011-01-21 13:56:35 +02002919 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002920 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002921 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2922 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002923 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002924 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002925 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002926 continue;
2927 i++;
2928 }
2929
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002930 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002931
Johan Hedberg4c659c32011-11-07 23:13:39 +02002932 /* Recalculate length in case of filtered SCO connections, etc */
2933 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002934
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002935 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002936 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002937
Johan Hedberga38528f2011-01-22 06:46:43 +02002938 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002939
2940unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002941 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002942 return err;
2943}
2944
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002945static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002946 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002947{
2948 struct pending_cmd *cmd;
2949 int err;
2950
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002951 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002952 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002953 if (!cmd)
2954 return -ENOMEM;
2955
Johan Hedbergd8457692012-02-17 14:24:57 +02002956 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002957 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002958 if (err < 0)
2959 mgmt_pending_remove(cmd);
2960
2961 return err;
2962}
2963
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002964static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002965 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002966{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002967 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002968 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002969 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002970 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002971 int err;
2972
2973 BT_DBG("");
2974
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002975 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002976
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002977 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002978 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002980 goto failed;
2981 }
2982
Johan Hedbergd8457692012-02-17 14:24:57 +02002983 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002984 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002985 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002986 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002987 goto failed;
2988 }
2989
2990 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002991 struct mgmt_cp_pin_code_neg_reply ncp;
2992
2993 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002994
2995 BT_ERR("PIN code is not 16 bytes long");
2996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002997 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002998 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002999 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003000 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003001
3002 goto failed;
3003 }
3004
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003005 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003006 if (!cmd) {
3007 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003008 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003009 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003010
Johan Hedbergd8457692012-02-17 14:24:57 +02003011 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003012 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003013 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003014
3015 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3016 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003017 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003018
3019failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003020 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003021 return err;
3022}
3023
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003024static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3025 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003026{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003027 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003028
3029 BT_DBG("");
3030
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003031 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3032 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3033 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3034
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003035 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003036
3037 hdev->io_capability = cp->io_capability;
3038
3039 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003040 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003041
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003042 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003043
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003044 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3045 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003046}
3047
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003048static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003049{
3050 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003051 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003052
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003053 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003054 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3055 continue;
3056
Johan Hedberge9a416b2011-02-19 12:05:56 -03003057 if (cmd->user_data != conn)
3058 continue;
3059
3060 return cmd;
3061 }
3062
3063 return NULL;
3064}
3065
3066static void pairing_complete(struct pending_cmd *cmd, u8 status)
3067{
3068 struct mgmt_rp_pair_device rp;
3069 struct hci_conn *conn = cmd->user_data;
3070
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003071 bacpy(&rp.addr.bdaddr, &conn->dst);
3072 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003073
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003074 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003075 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003076
3077 /* So we don't get further callbacks for this connection */
3078 conn->connect_cfm_cb = NULL;
3079 conn->security_cfm_cb = NULL;
3080 conn->disconn_cfm_cb = NULL;
3081
David Herrmann76a68ba2013-04-06 20:28:37 +02003082 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003083 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003084
Johan Hedberga664b5b2011-02-19 12:06:02 -03003085 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003086
3087 /* The device is paired so there is no need to remove
3088 * its connection parameters anymore.
3089 */
3090 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003091}
3092
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003093void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3094{
3095 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3096 struct pending_cmd *cmd;
3097
3098 cmd = find_pairing(conn);
3099 if (cmd)
3100 pairing_complete(cmd, status);
3101}
3102
Johan Hedberge9a416b2011-02-19 12:05:56 -03003103static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3104{
3105 struct pending_cmd *cmd;
3106
3107 BT_DBG("status %u", status);
3108
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003109 cmd = find_pairing(conn);
3110 if (!cmd)
3111 BT_DBG("Unable to find a pending command");
3112 else
Johan Hedberge2113262012-02-18 15:20:03 +02003113 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003114}
3115
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003116static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303117{
3118 struct pending_cmd *cmd;
3119
3120 BT_DBG("status %u", status);
3121
3122 if (!status)
3123 return;
3124
3125 cmd = find_pairing(conn);
3126 if (!cmd)
3127 BT_DBG("Unable to find a pending command");
3128 else
3129 pairing_complete(cmd, mgmt_status(status));
3130}
3131
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003132static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003133 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003134{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003135 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003136 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137 struct pending_cmd *cmd;
3138 u8 sec_level, auth_type;
3139 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003140 int err;
3141
3142 BT_DBG("");
3143
Szymon Jancf950a30e2013-01-18 12:48:07 +01003144 memset(&rp, 0, sizeof(rp));
3145 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3146 rp.addr.type = cp->addr.type;
3147
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003148 if (!bdaddr_type_is_valid(cp->addr.type))
3149 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3150 MGMT_STATUS_INVALID_PARAMS,
3151 &rp, sizeof(rp));
3152
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003153 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3154 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3155 MGMT_STATUS_INVALID_PARAMS,
3156 &rp, sizeof(rp));
3157
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003158 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003159
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003160 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003161 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3162 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003163 goto unlock;
3164 }
3165
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003166 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003167 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003168
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003169 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003170 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3171 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003172 } else {
3173 u8 addr_type;
3174
3175 /* Convert from L2CAP channel address type to HCI address type
3176 */
3177 if (cp->addr.type == BDADDR_LE_PUBLIC)
3178 addr_type = ADDR_LE_DEV_PUBLIC;
3179 else
3180 addr_type = ADDR_LE_DEV_RANDOM;
3181
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003182 /* When pairing a new device, it is expected to remember
3183 * this device for future connections. Adding the connection
3184 * parameter information ahead of time allows tracking
3185 * of the slave preferred values and will speed up any
3186 * further connection establishment.
3187 *
3188 * If connection parameters already exist, then they
3189 * will be kept and this function does nothing.
3190 */
3191 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3192
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003193 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003194 sec_level, HCI_LE_CONN_TIMEOUT,
3195 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003196 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003197
Ville Tervo30e76272011-02-22 16:10:53 -03003198 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003199 int status;
3200
3201 if (PTR_ERR(conn) == -EBUSY)
3202 status = MGMT_STATUS_BUSY;
3203 else
3204 status = MGMT_STATUS_CONNECT_FAILED;
3205
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003206 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003207 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003208 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003209 goto unlock;
3210 }
3211
3212 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003213 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003214 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003215 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003216 goto unlock;
3217 }
3218
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003219 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003220 if (!cmd) {
3221 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003222 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003223 goto unlock;
3224 }
3225
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003226 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003227 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003228 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003229 conn->security_cfm_cb = pairing_complete_cb;
3230 conn->disconn_cfm_cb = pairing_complete_cb;
3231 } else {
3232 conn->connect_cfm_cb = le_pairing_complete_cb;
3233 conn->security_cfm_cb = le_pairing_complete_cb;
3234 conn->disconn_cfm_cb = le_pairing_complete_cb;
3235 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003236
Johan Hedberge9a416b2011-02-19 12:05:56 -03003237 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003238 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003239
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003240 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003241 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003242 pairing_complete(cmd, 0);
3243
3244 err = 0;
3245
3246unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003247 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003248 return err;
3249}
3250
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003251static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3252 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003253{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003254 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003255 struct pending_cmd *cmd;
3256 struct hci_conn *conn;
3257 int err;
3258
3259 BT_DBG("");
3260
Johan Hedberg28424702012-02-02 04:02:29 +02003261 hci_dev_lock(hdev);
3262
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003263 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003264 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003265 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003266 goto unlock;
3267 }
3268
Johan Hedberg28424702012-02-02 04:02:29 +02003269 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3270 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003271 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003272 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003273 goto unlock;
3274 }
3275
3276 conn = cmd->user_data;
3277
3278 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003279 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003280 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003281 goto unlock;
3282 }
3283
3284 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3285
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003286 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003287 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003288unlock:
3289 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003290 return err;
3291}
3292
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003293static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003294 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003295 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003296{
Johan Hedberga5c29682011-02-19 12:05:57 -03003297 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003298 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003299 int err;
3300
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003301 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003302
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003303 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003304 err = cmd_complete(sk, hdev->id, mgmt_op,
3305 MGMT_STATUS_NOT_POWERED, addr,
3306 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003307 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003308 }
3309
Johan Hedberg1707c602013-03-15 17:07:15 -05003310 if (addr->type == BDADDR_BREDR)
3311 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003312 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003313 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003314
Johan Hedberg272d90d2012-02-09 15:26:12 +02003315 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003316 err = cmd_complete(sk, hdev->id, mgmt_op,
3317 MGMT_STATUS_NOT_CONNECTED, addr,
3318 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003319 goto done;
3320 }
3321
Johan Hedberg1707c602013-03-15 17:07:15 -05003322 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003323 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003324 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003325 err = cmd_complete(sk, hdev->id, mgmt_op,
3326 MGMT_STATUS_SUCCESS, addr,
3327 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003328 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003329 err = cmd_complete(sk, hdev->id, mgmt_op,
3330 MGMT_STATUS_FAILED, addr,
3331 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003332
Brian Gix47c15e22011-11-16 13:53:14 -08003333 goto done;
3334 }
3335
Johan Hedberg1707c602013-03-15 17:07:15 -05003336 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003337 if (!cmd) {
3338 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003339 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003340 }
3341
Brian Gix0df4c182011-11-16 13:53:13 -08003342 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003343 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3344 struct hci_cp_user_passkey_reply cp;
3345
Johan Hedberg1707c602013-03-15 17:07:15 -05003346 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003347 cp.passkey = passkey;
3348 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3349 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003350 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3351 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003352
Johan Hedberga664b5b2011-02-19 12:06:02 -03003353 if (err < 0)
3354 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003355
Brian Gix0df4c182011-11-16 13:53:13 -08003356done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003357 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003358 return err;
3359}
3360
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303361static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3362 void *data, u16 len)
3363{
3364 struct mgmt_cp_pin_code_neg_reply *cp = data;
3365
3366 BT_DBG("");
3367
Johan Hedberg1707c602013-03-15 17:07:15 -05003368 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303369 MGMT_OP_PIN_CODE_NEG_REPLY,
3370 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3371}
3372
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003373static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3374 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003375{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003376 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003377
3378 BT_DBG("");
3379
3380 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003381 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003382 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003383
Johan Hedberg1707c602013-03-15 17:07:15 -05003384 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003385 MGMT_OP_USER_CONFIRM_REPLY,
3386 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003387}
3388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003389static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003390 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003391{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003392 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003393
3394 BT_DBG("");
3395
Johan Hedberg1707c602013-03-15 17:07:15 -05003396 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003397 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3398 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003399}
3400
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003401static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3402 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003403{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003404 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003405
3406 BT_DBG("");
3407
Johan Hedberg1707c602013-03-15 17:07:15 -05003408 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003409 MGMT_OP_USER_PASSKEY_REPLY,
3410 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003411}
3412
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003413static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003414 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003415{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003416 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003417
3418 BT_DBG("");
3419
Johan Hedberg1707c602013-03-15 17:07:15 -05003420 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003421 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3422 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003423}
3424
Johan Hedberg13928972013-03-15 17:07:00 -05003425static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003426{
Johan Hedberg13928972013-03-15 17:07:00 -05003427 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003428 struct hci_cp_write_local_name cp;
3429
Johan Hedberg13928972013-03-15 17:07:00 -05003430 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003431
Johan Hedberg890ea892013-03-15 17:06:52 -05003432 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003433}
3434
Johan Hedberg13928972013-03-15 17:07:00 -05003435static void set_name_complete(struct hci_dev *hdev, u8 status)
3436{
3437 struct mgmt_cp_set_local_name *cp;
3438 struct pending_cmd *cmd;
3439
3440 BT_DBG("status 0x%02x", status);
3441
3442 hci_dev_lock(hdev);
3443
3444 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3445 if (!cmd)
3446 goto unlock;
3447
3448 cp = cmd->param;
3449
3450 if (status)
3451 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3452 mgmt_status(status));
3453 else
3454 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3455 cp, sizeof(*cp));
3456
3457 mgmt_pending_remove(cmd);
3458
3459unlock:
3460 hci_dev_unlock(hdev);
3461}
3462
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003463static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003464 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003465{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003466 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003467 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003468 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003469 int err;
3470
3471 BT_DBG("");
3472
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003473 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003474
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003475 /* If the old values are the same as the new ones just return a
3476 * direct command complete event.
3477 */
3478 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3479 !memcmp(hdev->short_name, cp->short_name,
3480 sizeof(hdev->short_name))) {
3481 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3482 data, len);
3483 goto failed;
3484 }
3485
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003486 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003487
Johan Hedbergb5235a62012-02-21 14:32:24 +02003488 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003489 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003490
3491 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003492 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003493 if (err < 0)
3494 goto failed;
3495
3496 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003497 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003498
Johan Hedbergb5235a62012-02-21 14:32:24 +02003499 goto failed;
3500 }
3501
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003502 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003503 if (!cmd) {
3504 err = -ENOMEM;
3505 goto failed;
3506 }
3507
Johan Hedberg13928972013-03-15 17:07:00 -05003508 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3509
Johan Hedberg890ea892013-03-15 17:06:52 -05003510 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003511
3512 if (lmp_bredr_capable(hdev)) {
3513 update_name(&req);
3514 update_eir(&req);
3515 }
3516
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003517 /* The name is stored in the scan response data and so
3518 * no need to udpate the advertising data here.
3519 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003520 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003521 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003522
Johan Hedberg13928972013-03-15 17:07:00 -05003523 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003524 if (err < 0)
3525 mgmt_pending_remove(cmd);
3526
3527failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003528 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003529 return err;
3530}
3531
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003532static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003533 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003534{
Szymon Jancc35938b2011-03-22 13:12:21 +01003535 struct pending_cmd *cmd;
3536 int err;
3537
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003538 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003539
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003540 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003541
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003542 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003543 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003544 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003545 goto unlock;
3546 }
3547
Andre Guedes9a1a1992012-07-24 15:03:48 -03003548 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003549 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003550 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003551 goto unlock;
3552 }
3553
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003554 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003555 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003556 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003557 goto unlock;
3558 }
3559
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003560 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003561 if (!cmd) {
3562 err = -ENOMEM;
3563 goto unlock;
3564 }
3565
Johan Hedberg710f11c2014-05-26 11:21:22 +03003566 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003567 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3568 0, NULL);
3569 else
3570 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3571
Szymon Jancc35938b2011-03-22 13:12:21 +01003572 if (err < 0)
3573 mgmt_pending_remove(cmd);
3574
3575unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003576 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003577 return err;
3578}
3579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003580static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003581 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003582{
Szymon Janc2763eda2011-03-22 13:12:22 +01003583 int err;
3584
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003585 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003586
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003587 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003588
Marcel Holtmannec109112014-01-10 02:07:30 -08003589 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3590 struct mgmt_cp_add_remote_oob_data *cp = data;
3591 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003592
Johan Hedbergc19a4952014-11-17 20:52:19 +02003593 if (cp->addr.type != BDADDR_BREDR) {
3594 err = cmd_complete(sk, hdev->id,
3595 MGMT_OP_ADD_REMOTE_OOB_DATA,
3596 MGMT_STATUS_INVALID_PARAMS,
3597 &cp->addr, sizeof(cp->addr));
3598 goto unlock;
3599 }
3600
Marcel Holtmannec109112014-01-10 02:07:30 -08003601 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003602 cp->addr.type, cp->hash,
3603 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003604 if (err < 0)
3605 status = MGMT_STATUS_FAILED;
3606 else
3607 status = MGMT_STATUS_SUCCESS;
3608
3609 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3610 status, &cp->addr, sizeof(cp->addr));
3611 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3612 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003613 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003614 u8 status;
3615
Johan Hedbergc19a4952014-11-17 20:52:19 +02003616 if (cp->addr.type != BDADDR_BREDR) {
3617 err = cmd_complete(sk, hdev->id,
3618 MGMT_OP_ADD_REMOTE_OOB_DATA,
3619 MGMT_STATUS_INVALID_PARAMS,
3620 &cp->addr, sizeof(cp->addr));
3621 goto unlock;
3622 }
3623
Johan Hedberg86df9202014-10-26 20:52:27 +01003624 if (bdaddr_type_is_le(cp->addr.type)) {
3625 rand192 = NULL;
3626 hash192 = NULL;
3627 } else {
3628 rand192 = cp->rand192;
3629 hash192 = cp->hash192;
3630 }
3631
Johan Hedberg81328d52014-10-26 20:33:47 +01003632 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003633 cp->addr.type, hash192, rand192,
3634 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003635 if (err < 0)
3636 status = MGMT_STATUS_FAILED;
3637 else
3638 status = MGMT_STATUS_SUCCESS;
3639
3640 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3641 status, &cp->addr, sizeof(cp->addr));
3642 } else {
3643 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3644 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3645 MGMT_STATUS_INVALID_PARAMS);
3646 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003647
Johan Hedbergc19a4952014-11-17 20:52:19 +02003648unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003649 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003650 return err;
3651}
3652
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003653static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003654 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003655{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003656 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003657 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003658 int err;
3659
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003660 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003661
Johan Hedbergc19a4952014-11-17 20:52:19 +02003662 if (cp->addr.type != BDADDR_BREDR)
3663 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3664 MGMT_STATUS_INVALID_PARAMS,
3665 &cp->addr, sizeof(cp->addr));
3666
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003667 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003668
Johan Hedbergeedbd582014-11-15 09:34:23 +02003669 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3670 hci_remote_oob_data_clear(hdev);
3671 status = MGMT_STATUS_SUCCESS;
3672 goto done;
3673 }
3674
Johan Hedberg6928a922014-10-26 20:46:09 +01003675 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003676 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003677 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003678 else
Szymon Janca6785be2012-12-13 15:11:21 +01003679 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003680
Johan Hedbergeedbd582014-11-15 09:34:23 +02003681done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003682 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003683 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003684
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003685 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003686 return err;
3687}
3688
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003689static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3690{
3691 struct pending_cmd *cmd;
3692 u8 type;
3693 int err;
3694
3695 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3696
3697 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3698 if (!cmd)
3699 return -ENOENT;
3700
3701 type = hdev->discovery.type;
3702
3703 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3704 &type, sizeof(type));
3705 mgmt_pending_remove(cmd);
3706
3707 return err;
3708}
3709
Andre Guedes7c307722013-04-30 15:29:28 -03003710static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3711{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003712 unsigned long timeout = 0;
3713
Andre Guedes7c307722013-04-30 15:29:28 -03003714 BT_DBG("status %d", status);
3715
3716 if (status) {
3717 hci_dev_lock(hdev);
3718 mgmt_start_discovery_failed(hdev, status);
3719 hci_dev_unlock(hdev);
3720 return;
3721 }
3722
3723 hci_dev_lock(hdev);
3724 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3725 hci_dev_unlock(hdev);
3726
3727 switch (hdev->discovery.type) {
3728 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003729 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003730 break;
3731
3732 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003733 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003734 break;
3735
3736 case DISCOV_TYPE_BREDR:
3737 break;
3738
3739 default:
3740 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3741 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003742
3743 if (!timeout)
3744 return;
3745
3746 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003747}
3748
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003749static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003750 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003751{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003752 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003753 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003754 struct hci_cp_le_set_scan_param param_cp;
3755 struct hci_cp_le_set_scan_enable enable_cp;
3756 struct hci_cp_inquiry inq_cp;
3757 struct hci_request req;
3758 /* General inquiry access code (GIAC) */
3759 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003760 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003761 int err;
3762
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003763 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003764
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003765 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003766
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003767 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003768 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3769 MGMT_STATUS_NOT_POWERED,
3770 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003771 goto failed;
3772 }
3773
Andre Guedes642be6c2012-03-21 00:03:37 -03003774 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003775 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3776 MGMT_STATUS_BUSY, &cp->type,
3777 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003778 goto failed;
3779 }
3780
Johan Hedbergff9ef572012-01-04 14:23:45 +02003781 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Szymon Janca736abc2014-11-03 14:20:56 +01003782 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3783 MGMT_STATUS_BUSY, &cp->type,
3784 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003785 goto failed;
3786 }
3787
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003788 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003789 if (!cmd) {
3790 err = -ENOMEM;
3791 goto failed;
3792 }
3793
Andre Guedes4aab14e2012-02-17 20:39:36 -03003794 hdev->discovery.type = cp->type;
3795
Andre Guedes7c307722013-04-30 15:29:28 -03003796 hci_req_init(&req, hdev);
3797
Andre Guedes4aab14e2012-02-17 20:39:36 -03003798 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003799 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003800 status = mgmt_bredr_support(hdev);
3801 if (status) {
Szymon Janca736abc2014-11-03 14:20:56 +01003802 err = cmd_complete(sk, hdev->id,
3803 MGMT_OP_START_DISCOVERY, status,
3804 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003805 mgmt_pending_remove(cmd);
3806 goto failed;
3807 }
3808
Andre Guedes7c307722013-04-30 15:29:28 -03003809 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003810 err = cmd_complete(sk, hdev->id,
3811 MGMT_OP_START_DISCOVERY,
3812 MGMT_STATUS_BUSY, &cp->type,
3813 sizeof(cp->type));
Andre Guedes7c307722013-04-30 15:29:28 -03003814 mgmt_pending_remove(cmd);
3815 goto failed;
3816 }
3817
3818 hci_inquiry_cache_flush(hdev);
3819
3820 memset(&inq_cp, 0, sizeof(inq_cp));
3821 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003822 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003823 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003824 break;
3825
3826 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003827 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003828 status = mgmt_le_support(hdev);
3829 if (status) {
Szymon Janca736abc2014-11-03 14:20:56 +01003830 err = cmd_complete(sk, hdev->id,
3831 MGMT_OP_START_DISCOVERY, status,
3832 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003833 mgmt_pending_remove(cmd);
3834 goto failed;
3835 }
3836
Andre Guedes7c307722013-04-30 15:29:28 -03003837 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003838 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003839 err = cmd_complete(sk, hdev->id,
3840 MGMT_OP_START_DISCOVERY,
3841 MGMT_STATUS_NOT_SUPPORTED,
3842 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003843 mgmt_pending_remove(cmd);
3844 goto failed;
3845 }
3846
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003847 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3848 /* Don't let discovery abort an outgoing
3849 * connection attempt that's using directed
3850 * advertising.
3851 */
3852 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3853 BT_CONNECT)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003854 err = cmd_complete(sk, hdev->id,
3855 MGMT_OP_START_DISCOVERY,
3856 MGMT_STATUS_REJECTED,
3857 &cp->type,
3858 sizeof(cp->type));
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003859 mgmt_pending_remove(cmd);
3860 goto failed;
3861 }
3862
3863 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003864 }
3865
Andre Guedesc54c3862014-02-26 20:21:50 -03003866 /* If controller is scanning, it means the background scanning
3867 * is running. Thus, we should temporarily stop it in order to
3868 * set the discovery scanning parameters.
3869 */
3870 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3871 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003872
3873 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003874
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003875 /* All active scans will be done with either a resolvable
3876 * private address (when privacy feature has been enabled)
3877 * or unresolvable private address.
3878 */
3879 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003880 if (err < 0) {
Szymon Janca736abc2014-11-03 14:20:56 +01003881 err = cmd_complete(sk, hdev->id,
3882 MGMT_OP_START_DISCOVERY,
3883 MGMT_STATUS_FAILED,
3884 &cp->type, sizeof(cp->type));
Johan Hedbergd9483942014-02-23 19:42:24 +02003885 mgmt_pending_remove(cmd);
3886 goto failed;
3887 }
3888
Andre Guedes7c307722013-04-30 15:29:28 -03003889 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003890 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3891 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003892 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003893 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3894 &param_cp);
3895
3896 memset(&enable_cp, 0, sizeof(enable_cp));
3897 enable_cp.enable = LE_SCAN_ENABLE;
3898 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3899 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3900 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003901 break;
3902
Andre Guedesf39799f2012-02-17 20:39:35 -03003903 default:
Szymon Janca736abc2014-11-03 14:20:56 +01003904 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3905 MGMT_STATUS_INVALID_PARAMS,
3906 &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003907 mgmt_pending_remove(cmd);
3908 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003909 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003910
Andre Guedes7c307722013-04-30 15:29:28 -03003911 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003912 if (err < 0)
3913 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003914 else
3915 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003916
3917failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003918 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003919 return err;
3920}
3921
Andre Guedes1183fdc2013-04-30 15:29:35 -03003922static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3923{
3924 struct pending_cmd *cmd;
3925 int err;
3926
3927 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3928 if (!cmd)
3929 return -ENOENT;
3930
3931 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3932 &hdev->discovery.type, sizeof(hdev->discovery.type));
3933 mgmt_pending_remove(cmd);
3934
3935 return err;
3936}
3937
Andre Guedes0e05bba2013-04-30 15:29:33 -03003938static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3939{
3940 BT_DBG("status %d", status);
3941
3942 hci_dev_lock(hdev);
3943
3944 if (status) {
3945 mgmt_stop_discovery_failed(hdev, status);
3946 goto unlock;
3947 }
3948
3949 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3950
3951unlock:
3952 hci_dev_unlock(hdev);
3953}
3954
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003955static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003956 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003957{
Johan Hedbergd9306502012-02-20 23:25:18 +02003958 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003959 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003960 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003961 int err;
3962
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003963 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003964
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003965 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003966
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003967 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003968 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003969 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3970 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003971 goto unlock;
3972 }
3973
3974 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003975 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003976 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3977 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003978 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003979 }
3980
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003981 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003982 if (!cmd) {
3983 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003984 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003985 }
3986
Andre Guedes0e05bba2013-04-30 15:29:33 -03003987 hci_req_init(&req, hdev);
3988
Johan Hedberg21a60d32014-06-10 14:05:58 +03003989 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003990
Johan Hedberg21a60d32014-06-10 14:05:58 +03003991 err = hci_req_run(&req, stop_discovery_complete);
3992 if (!err) {
3993 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003994 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003995 }
3996
Johan Hedberg21a60d32014-06-10 14:05:58 +03003997 mgmt_pending_remove(cmd);
3998
3999 /* If no HCI commands were sent we're done */
4000 if (err == -ENODATA) {
4001 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4002 &mgmt_cp->type, sizeof(mgmt_cp->type));
4003 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4004 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004005
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004006unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004007 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004008 return err;
4009}
4010
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004011static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004012 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004013{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004014 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004015 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004016 int err;
4017
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004018 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004019
Johan Hedberg561aafb2012-01-04 13:31:59 +02004020 hci_dev_lock(hdev);
4021
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004022 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004023 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4024 MGMT_STATUS_FAILED, &cp->addr,
4025 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004026 goto failed;
4027 }
4028
Johan Hedberga198e7b2012-02-17 14:27:06 +02004029 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004030 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004031 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4032 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4033 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004034 goto failed;
4035 }
4036
4037 if (cp->name_known) {
4038 e->name_state = NAME_KNOWN;
4039 list_del(&e->list);
4040 } else {
4041 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004042 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004043 }
4044
Johan Hedberge3846622013-01-09 15:29:33 +02004045 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4046 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004047
4048failed:
4049 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004050 return err;
4051}
4052
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004053static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004054 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004055{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004056 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004057 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004058 int err;
4059
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004060 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004061
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004062 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004063 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4064 MGMT_STATUS_INVALID_PARAMS,
4065 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004066
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004067 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004068
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004069 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4070 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004071 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004072 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004073 goto done;
4074 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004075
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004076 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4077 sk);
4078 status = MGMT_STATUS_SUCCESS;
4079
4080done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004081 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004082 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004083
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004084 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004085
4086 return err;
4087}
4088
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004089static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004090 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004091{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004092 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004093 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004094 int err;
4095
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004096 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004097
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004098 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004099 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4100 MGMT_STATUS_INVALID_PARAMS,
4101 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004102
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004103 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004104
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004105 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4106 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004107 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004108 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004109 goto done;
4110 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004111
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004112 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4113 sk);
4114 status = MGMT_STATUS_SUCCESS;
4115
4116done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004117 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004118 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004119
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004120 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004121
4122 return err;
4123}
4124
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004125static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4126 u16 len)
4127{
4128 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004129 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004130 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004131 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004132
4133 BT_DBG("%s", hdev->name);
4134
Szymon Jancc72d4b82012-03-16 16:02:57 +01004135 source = __le16_to_cpu(cp->source);
4136
4137 if (source > 0x0002)
4138 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4139 MGMT_STATUS_INVALID_PARAMS);
4140
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004141 hci_dev_lock(hdev);
4142
Szymon Jancc72d4b82012-03-16 16:02:57 +01004143 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004144 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4145 hdev->devid_product = __le16_to_cpu(cp->product);
4146 hdev->devid_version = __le16_to_cpu(cp->version);
4147
4148 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4149
Johan Hedberg890ea892013-03-15 17:06:52 -05004150 hci_req_init(&req, hdev);
4151 update_eir(&req);
4152 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004153
4154 hci_dev_unlock(hdev);
4155
4156 return err;
4157}
4158
Johan Hedberg4375f102013-09-25 13:26:10 +03004159static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4160{
4161 struct cmd_lookup match = { NULL, hdev };
4162
4163 if (status) {
4164 u8 mgmt_err = mgmt_status(status);
4165
4166 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4167 cmd_status_rsp, &mgmt_err);
4168 return;
4169 }
4170
Johan Hedbergc93bd152014-07-08 15:07:48 +03004171 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4172 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4173 else
4174 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4175
Johan Hedberg4375f102013-09-25 13:26:10 +03004176 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4177 &match);
4178
4179 new_settings(hdev, match.sk);
4180
4181 if (match.sk)
4182 sock_put(match.sk);
4183}
4184
Marcel Holtmann21b51872013-10-10 09:47:53 -07004185static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4186 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004187{
4188 struct mgmt_mode *cp = data;
4189 struct pending_cmd *cmd;
4190 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004191 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004192 int err;
4193
4194 BT_DBG("request for %s", hdev->name);
4195
Johan Hedberge6fe7982013-10-02 15:45:22 +03004196 status = mgmt_le_support(hdev);
4197 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004198 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004199 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004200
4201 if (cp->val != 0x00 && cp->val != 0x01)
4202 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4203 MGMT_STATUS_INVALID_PARAMS);
4204
4205 hci_dev_lock(hdev);
4206
4207 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004208 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004209
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004210 /* The following conditions are ones which mean that we should
4211 * not do any HCI communication but directly send a mgmt
4212 * response to user space (after toggling the flag if
4213 * necessary).
4214 */
4215 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004216 hci_conn_num(hdev, LE_LINK) > 0 ||
4217 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4218 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004219 bool changed = false;
4220
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004221 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4222 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004223 changed = true;
4224 }
4225
4226 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4227 if (err < 0)
4228 goto unlock;
4229
4230 if (changed)
4231 err = new_settings(hdev, sk);
4232
4233 goto unlock;
4234 }
4235
4236 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4237 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4238 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4239 MGMT_STATUS_BUSY);
4240 goto unlock;
4241 }
4242
4243 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4244 if (!cmd) {
4245 err = -ENOMEM;
4246 goto unlock;
4247 }
4248
4249 hci_req_init(&req, hdev);
4250
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004251 if (val)
4252 enable_advertising(&req);
4253 else
4254 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004255
4256 err = hci_req_run(&req, set_advertising_complete);
4257 if (err < 0)
4258 mgmt_pending_remove(cmd);
4259
4260unlock:
4261 hci_dev_unlock(hdev);
4262 return err;
4263}
4264
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004265static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4266 void *data, u16 len)
4267{
4268 struct mgmt_cp_set_static_address *cp = data;
4269 int err;
4270
4271 BT_DBG("%s", hdev->name);
4272
Marcel Holtmann62af4442013-10-02 22:10:32 -07004273 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004274 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004275 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004276
4277 if (hdev_is_powered(hdev))
4278 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4279 MGMT_STATUS_REJECTED);
4280
4281 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4282 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4283 return cmd_status(sk, hdev->id,
4284 MGMT_OP_SET_STATIC_ADDRESS,
4285 MGMT_STATUS_INVALID_PARAMS);
4286
4287 /* Two most significant bits shall be set */
4288 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4289 return cmd_status(sk, hdev->id,
4290 MGMT_OP_SET_STATIC_ADDRESS,
4291 MGMT_STATUS_INVALID_PARAMS);
4292 }
4293
4294 hci_dev_lock(hdev);
4295
4296 bacpy(&hdev->static_addr, &cp->bdaddr);
4297
4298 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4299
4300 hci_dev_unlock(hdev);
4301
4302 return err;
4303}
4304
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004305static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4306 void *data, u16 len)
4307{
4308 struct mgmt_cp_set_scan_params *cp = data;
4309 __u16 interval, window;
4310 int err;
4311
4312 BT_DBG("%s", hdev->name);
4313
4314 if (!lmp_le_capable(hdev))
4315 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4316 MGMT_STATUS_NOT_SUPPORTED);
4317
4318 interval = __le16_to_cpu(cp->interval);
4319
4320 if (interval < 0x0004 || interval > 0x4000)
4321 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4322 MGMT_STATUS_INVALID_PARAMS);
4323
4324 window = __le16_to_cpu(cp->window);
4325
4326 if (window < 0x0004 || window > 0x4000)
4327 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4328 MGMT_STATUS_INVALID_PARAMS);
4329
Marcel Holtmann899e1072013-10-14 09:55:32 -07004330 if (window > interval)
4331 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4332 MGMT_STATUS_INVALID_PARAMS);
4333
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004334 hci_dev_lock(hdev);
4335
4336 hdev->le_scan_interval = interval;
4337 hdev->le_scan_window = window;
4338
4339 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4340
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004341 /* If background scan is running, restart it so new parameters are
4342 * loaded.
4343 */
4344 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4345 hdev->discovery.state == DISCOVERY_STOPPED) {
4346 struct hci_request req;
4347
4348 hci_req_init(&req, hdev);
4349
4350 hci_req_add_le_scan_disable(&req);
4351 hci_req_add_le_passive_scan(&req);
4352
4353 hci_req_run(&req, NULL);
4354 }
4355
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004356 hci_dev_unlock(hdev);
4357
4358 return err;
4359}
4360
Johan Hedberg33e38b32013-03-15 17:07:05 -05004361static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4362{
4363 struct pending_cmd *cmd;
4364
4365 BT_DBG("status 0x%02x", status);
4366
4367 hci_dev_lock(hdev);
4368
4369 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4370 if (!cmd)
4371 goto unlock;
4372
4373 if (status) {
4374 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4375 mgmt_status(status));
4376 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004377 struct mgmt_mode *cp = cmd->param;
4378
4379 if (cp->val)
4380 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4381 else
4382 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4383
Johan Hedberg33e38b32013-03-15 17:07:05 -05004384 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4385 new_settings(hdev, cmd->sk);
4386 }
4387
4388 mgmt_pending_remove(cmd);
4389
4390unlock:
4391 hci_dev_unlock(hdev);
4392}
4393
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004394static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004395 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004396{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004397 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004398 struct pending_cmd *cmd;
4399 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004400 int err;
4401
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004402 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004403
Johan Hedberg56f87902013-10-02 13:43:13 +03004404 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4405 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004406 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4407 MGMT_STATUS_NOT_SUPPORTED);
4408
Johan Hedberga7e80f22013-01-09 16:05:19 +02004409 if (cp->val != 0x00 && cp->val != 0x01)
4410 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4411 MGMT_STATUS_INVALID_PARAMS);
4412
Johan Hedberg5400c042012-02-21 16:40:33 +02004413 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004414 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004415 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004416
4417 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004418 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004419 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004420
4421 hci_dev_lock(hdev);
4422
Johan Hedberg05cbf292013-03-15 17:07:07 -05004423 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4424 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4425 MGMT_STATUS_BUSY);
4426 goto unlock;
4427 }
4428
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004429 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4430 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4431 hdev);
4432 goto unlock;
4433 }
4434
Johan Hedberg33e38b32013-03-15 17:07:05 -05004435 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4436 data, len);
4437 if (!cmd) {
4438 err = -ENOMEM;
4439 goto unlock;
4440 }
4441
4442 hci_req_init(&req, hdev);
4443
Johan Hedberg406d7802013-03-15 17:07:09 -05004444 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004445
4446 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004447 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004448 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004449 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004450 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004451 }
4452
Johan Hedberg33e38b32013-03-15 17:07:05 -05004453unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004454 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004455
Antti Julkuf6422ec2011-06-22 13:11:56 +03004456 return err;
4457}
4458
Johan Hedberg0663ca22013-10-02 13:43:14 +03004459static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4460{
4461 struct pending_cmd *cmd;
4462
4463 BT_DBG("status 0x%02x", status);
4464
4465 hci_dev_lock(hdev);
4466
4467 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4468 if (!cmd)
4469 goto unlock;
4470
4471 if (status) {
4472 u8 mgmt_err = mgmt_status(status);
4473
4474 /* We need to restore the flag if related HCI commands
4475 * failed.
4476 */
4477 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4478
4479 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4480 } else {
4481 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4482 new_settings(hdev, cmd->sk);
4483 }
4484
4485 mgmt_pending_remove(cmd);
4486
4487unlock:
4488 hci_dev_unlock(hdev);
4489}
4490
4491static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4492{
4493 struct mgmt_mode *cp = data;
4494 struct pending_cmd *cmd;
4495 struct hci_request req;
4496 int err;
4497
4498 BT_DBG("request for %s", hdev->name);
4499
4500 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4501 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4502 MGMT_STATUS_NOT_SUPPORTED);
4503
4504 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4505 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4506 MGMT_STATUS_REJECTED);
4507
4508 if (cp->val != 0x00 && cp->val != 0x01)
4509 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4510 MGMT_STATUS_INVALID_PARAMS);
4511
4512 hci_dev_lock(hdev);
4513
4514 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4515 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4516 goto unlock;
4517 }
4518
4519 if (!hdev_is_powered(hdev)) {
4520 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004521 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4522 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4523 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4524 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4525 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4526 }
4527
4528 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4529
4530 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4531 if (err < 0)
4532 goto unlock;
4533
4534 err = new_settings(hdev, sk);
4535 goto unlock;
4536 }
4537
4538 /* Reject disabling when powered on */
4539 if (!cp->val) {
4540 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4541 MGMT_STATUS_REJECTED);
4542 goto unlock;
4543 }
4544
4545 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4546 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4547 MGMT_STATUS_BUSY);
4548 goto unlock;
4549 }
4550
4551 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4552 if (!cmd) {
4553 err = -ENOMEM;
4554 goto unlock;
4555 }
4556
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004557 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004558 * generates the correct flags.
4559 */
4560 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4561
4562 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004563
Johan Hedberg432df052014-08-01 11:13:31 +03004564 write_fast_connectable(&req, false);
4565 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004566
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004567 /* Since only the advertising data flags will change, there
4568 * is no need to update the scan response data.
4569 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004570 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004571
Johan Hedberg0663ca22013-10-02 13:43:14 +03004572 err = hci_req_run(&req, set_bredr_complete);
4573 if (err < 0)
4574 mgmt_pending_remove(cmd);
4575
4576unlock:
4577 hci_dev_unlock(hdev);
4578 return err;
4579}
4580
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004581static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4582 void *data, u16 len)
4583{
4584 struct mgmt_mode *cp = data;
4585 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004586 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004587 int err;
4588
4589 BT_DBG("request for %s", hdev->name);
4590
Johan Hedberga3209692014-05-26 11:23:35 +03004591 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4592 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004593 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4594 MGMT_STATUS_NOT_SUPPORTED);
4595
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004596 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004597 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4598 MGMT_STATUS_INVALID_PARAMS);
4599
4600 hci_dev_lock(hdev);
4601
Johan Hedberga3209692014-05-26 11:23:35 +03004602 if (!hdev_is_powered(hdev) ||
4603 (!lmp_sc_capable(hdev) &&
4604 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4605 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004606 bool changed;
4607
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004608 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004609 changed = !test_and_set_bit(HCI_SC_ENABLED,
4610 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004611 if (cp->val == 0x02)
4612 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4613 else
4614 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4615 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004616 changed = test_and_clear_bit(HCI_SC_ENABLED,
4617 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004618 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4619 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004620
4621 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4622 if (err < 0)
4623 goto failed;
4624
4625 if (changed)
4626 err = new_settings(hdev, sk);
4627
4628 goto failed;
4629 }
4630
4631 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4632 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4633 MGMT_STATUS_BUSY);
4634 goto failed;
4635 }
4636
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004637 val = !!cp->val;
4638
4639 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4640 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004641 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4642 goto failed;
4643 }
4644
4645 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4646 if (!cmd) {
4647 err = -ENOMEM;
4648 goto failed;
4649 }
4650
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004651 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004652 if (err < 0) {
4653 mgmt_pending_remove(cmd);
4654 goto failed;
4655 }
4656
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004657 if (cp->val == 0x02)
4658 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4659 else
4660 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4661
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004662failed:
4663 hci_dev_unlock(hdev);
4664 return err;
4665}
4666
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004667static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4668 void *data, u16 len)
4669{
4670 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004671 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004672 int err;
4673
4674 BT_DBG("request for %s", hdev->name);
4675
Johan Hedbergb97109792014-06-24 14:00:28 +03004676 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004677 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4678 MGMT_STATUS_INVALID_PARAMS);
4679
4680 hci_dev_lock(hdev);
4681
4682 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004683 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4684 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004685 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004686 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4687 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004688
Johan Hedbergb97109792014-06-24 14:00:28 +03004689 if (cp->val == 0x02)
4690 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4691 &hdev->dev_flags);
4692 else
4693 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4694 &hdev->dev_flags);
4695
4696 if (hdev_is_powered(hdev) && use_changed &&
4697 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4698 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4699 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4700 sizeof(mode), &mode);
4701 }
4702
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004703 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4704 if (err < 0)
4705 goto unlock;
4706
4707 if (changed)
4708 err = new_settings(hdev, sk);
4709
4710unlock:
4711 hci_dev_unlock(hdev);
4712 return err;
4713}
4714
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004715static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4716 u16 len)
4717{
4718 struct mgmt_cp_set_privacy *cp = cp_data;
4719 bool changed;
4720 int err;
4721
4722 BT_DBG("request for %s", hdev->name);
4723
4724 if (!lmp_le_capable(hdev))
4725 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4726 MGMT_STATUS_NOT_SUPPORTED);
4727
4728 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4729 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4730 MGMT_STATUS_INVALID_PARAMS);
4731
4732 if (hdev_is_powered(hdev))
4733 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4734 MGMT_STATUS_REJECTED);
4735
4736 hci_dev_lock(hdev);
4737
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004738 /* If user space supports this command it is also expected to
4739 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4740 */
4741 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4742
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004743 if (cp->privacy) {
4744 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4745 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4746 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4747 } else {
4748 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4749 memset(hdev->irk, 0, sizeof(hdev->irk));
4750 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4751 }
4752
4753 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4754 if (err < 0)
4755 goto unlock;
4756
4757 if (changed)
4758 err = new_settings(hdev, sk);
4759
4760unlock:
4761 hci_dev_unlock(hdev);
4762 return err;
4763}
4764
Johan Hedberg41edf162014-02-18 10:19:35 +02004765static bool irk_is_valid(struct mgmt_irk_info *irk)
4766{
4767 switch (irk->addr.type) {
4768 case BDADDR_LE_PUBLIC:
4769 return true;
4770
4771 case BDADDR_LE_RANDOM:
4772 /* Two most significant bits shall be set */
4773 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4774 return false;
4775 return true;
4776 }
4777
4778 return false;
4779}
4780
4781static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4782 u16 len)
4783{
4784 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004785 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4786 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004787 u16 irk_count, expected_len;
4788 int i, err;
4789
4790 BT_DBG("request for %s", hdev->name);
4791
4792 if (!lmp_le_capable(hdev))
4793 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4794 MGMT_STATUS_NOT_SUPPORTED);
4795
4796 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004797 if (irk_count > max_irk_count) {
4798 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4799 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4800 MGMT_STATUS_INVALID_PARAMS);
4801 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004802
4803 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4804 if (expected_len != len) {
4805 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004806 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004807 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4808 MGMT_STATUS_INVALID_PARAMS);
4809 }
4810
4811 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4812
4813 for (i = 0; i < irk_count; i++) {
4814 struct mgmt_irk_info *key = &cp->irks[i];
4815
4816 if (!irk_is_valid(key))
4817 return cmd_status(sk, hdev->id,
4818 MGMT_OP_LOAD_IRKS,
4819 MGMT_STATUS_INVALID_PARAMS);
4820 }
4821
4822 hci_dev_lock(hdev);
4823
4824 hci_smp_irks_clear(hdev);
4825
4826 for (i = 0; i < irk_count; i++) {
4827 struct mgmt_irk_info *irk = &cp->irks[i];
4828 u8 addr_type;
4829
4830 if (irk->addr.type == BDADDR_LE_PUBLIC)
4831 addr_type = ADDR_LE_DEV_PUBLIC;
4832 else
4833 addr_type = ADDR_LE_DEV_RANDOM;
4834
4835 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4836 BDADDR_ANY);
4837 }
4838
4839 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4840
4841 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4842
4843 hci_dev_unlock(hdev);
4844
4845 return err;
4846}
4847
Johan Hedberg3f706b72013-01-20 14:27:16 +02004848static bool ltk_is_valid(struct mgmt_ltk_info *key)
4849{
4850 if (key->master != 0x00 && key->master != 0x01)
4851 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004852
4853 switch (key->addr.type) {
4854 case BDADDR_LE_PUBLIC:
4855 return true;
4856
4857 case BDADDR_LE_RANDOM:
4858 /* Two most significant bits shall be set */
4859 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4860 return false;
4861 return true;
4862 }
4863
4864 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004865}
4866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004867static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004868 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004869{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004870 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004871 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4872 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004873 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004874 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004875
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004876 BT_DBG("request for %s", hdev->name);
4877
4878 if (!lmp_le_capable(hdev))
4879 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4880 MGMT_STATUS_NOT_SUPPORTED);
4881
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004882 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004883 if (key_count > max_key_count) {
4884 BT_ERR("load_ltks: too big key_count value %u", key_count);
4885 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4886 MGMT_STATUS_INVALID_PARAMS);
4887 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004888
4889 expected_len = sizeof(*cp) + key_count *
4890 sizeof(struct mgmt_ltk_info);
4891 if (expected_len != len) {
4892 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004893 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004894 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004895 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004896 }
4897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004898 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004899
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004900 for (i = 0; i < key_count; i++) {
4901 struct mgmt_ltk_info *key = &cp->keys[i];
4902
Johan Hedberg3f706b72013-01-20 14:27:16 +02004903 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004904 return cmd_status(sk, hdev->id,
4905 MGMT_OP_LOAD_LONG_TERM_KEYS,
4906 MGMT_STATUS_INVALID_PARAMS);
4907 }
4908
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004909 hci_dev_lock(hdev);
4910
4911 hci_smp_ltks_clear(hdev);
4912
4913 for (i = 0; i < key_count; i++) {
4914 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004915 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004916
4917 if (key->addr.type == BDADDR_LE_PUBLIC)
4918 addr_type = ADDR_LE_DEV_PUBLIC;
4919 else
4920 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004921
Johan Hedberg61b43352014-05-29 19:36:53 +03004922 switch (key->type) {
4923 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004924 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03004925 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03004926 break;
4927 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004928 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03004929 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03004930 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03004931 case MGMT_LTK_P256_UNAUTH:
4932 authenticated = 0x00;
4933 type = SMP_LTK_P256;
4934 break;
4935 case MGMT_LTK_P256_AUTH:
4936 authenticated = 0x01;
4937 type = SMP_LTK_P256;
4938 break;
4939 case MGMT_LTK_P256_DEBUG:
4940 authenticated = 0x00;
4941 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03004942 default:
4943 continue;
4944 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004945
Johan Hedberg35d70272014-02-19 14:57:47 +02004946 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004947 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004948 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004949 }
4950
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004951 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4952 NULL, 0);
4953
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004954 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004955
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004956 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004957}
4958
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004959struct cmd_conn_lookup {
4960 struct hci_conn *conn;
4961 bool valid_tx_power;
4962 u8 mgmt_status;
4963};
4964
4965static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4966{
4967 struct cmd_conn_lookup *match = data;
4968 struct mgmt_cp_get_conn_info *cp;
4969 struct mgmt_rp_get_conn_info rp;
4970 struct hci_conn *conn = cmd->user_data;
4971
4972 if (conn != match->conn)
4973 return;
4974
4975 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4976
4977 memset(&rp, 0, sizeof(rp));
4978 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4979 rp.addr.type = cp->addr.type;
4980
4981 if (!match->mgmt_status) {
4982 rp.rssi = conn->rssi;
4983
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004984 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004985 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004986 rp.max_tx_power = conn->max_tx_power;
4987 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004988 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004989 rp.max_tx_power = HCI_TX_POWER_INVALID;
4990 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004991 }
4992
4993 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4994 match->mgmt_status, &rp, sizeof(rp));
4995
4996 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03004997 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004998
4999 mgmt_pending_remove(cmd);
5000}
5001
5002static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5003{
5004 struct hci_cp_read_rssi *cp;
5005 struct hci_conn *conn;
5006 struct cmd_conn_lookup match;
5007 u16 handle;
5008
5009 BT_DBG("status 0x%02x", status);
5010
5011 hci_dev_lock(hdev);
5012
5013 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005014 * otherwise we assume it's not valid. At the moment we assume that
5015 * either both or none of current and max values are valid to keep code
5016 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005017 */
5018 match.valid_tx_power = !status;
5019
5020 /* Commands sent in request are either Read RSSI or Read Transmit Power
5021 * Level so we check which one was last sent to retrieve connection
5022 * handle. Both commands have handle as first parameter so it's safe to
5023 * cast data on the same command struct.
5024 *
5025 * First command sent is always Read RSSI and we fail only if it fails.
5026 * In other case we simply override error to indicate success as we
5027 * already remembered if TX power value is actually valid.
5028 */
5029 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5030 if (!cp) {
5031 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5032 status = 0;
5033 }
5034
5035 if (!cp) {
5036 BT_ERR("invalid sent_cmd in response");
5037 goto unlock;
5038 }
5039
5040 handle = __le16_to_cpu(cp->handle);
5041 conn = hci_conn_hash_lookup_handle(hdev, handle);
5042 if (!conn) {
5043 BT_ERR("unknown handle (%d) in response", handle);
5044 goto unlock;
5045 }
5046
5047 match.conn = conn;
5048 match.mgmt_status = mgmt_status(status);
5049
5050 /* Cache refresh is complete, now reply for mgmt request for given
5051 * connection only.
5052 */
5053 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5054 get_conn_info_complete, &match);
5055
5056unlock:
5057 hci_dev_unlock(hdev);
5058}
5059
5060static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5061 u16 len)
5062{
5063 struct mgmt_cp_get_conn_info *cp = data;
5064 struct mgmt_rp_get_conn_info rp;
5065 struct hci_conn *conn;
5066 unsigned long conn_info_age;
5067 int err = 0;
5068
5069 BT_DBG("%s", hdev->name);
5070
5071 memset(&rp, 0, sizeof(rp));
5072 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5073 rp.addr.type = cp->addr.type;
5074
5075 if (!bdaddr_type_is_valid(cp->addr.type))
5076 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5077 MGMT_STATUS_INVALID_PARAMS,
5078 &rp, sizeof(rp));
5079
5080 hci_dev_lock(hdev);
5081
5082 if (!hdev_is_powered(hdev)) {
5083 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5084 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5085 goto unlock;
5086 }
5087
5088 if (cp->addr.type == BDADDR_BREDR)
5089 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5090 &cp->addr.bdaddr);
5091 else
5092 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5093
5094 if (!conn || conn->state != BT_CONNECTED) {
5095 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5096 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5097 goto unlock;
5098 }
5099
5100 /* To avoid client trying to guess when to poll again for information we
5101 * calculate conn info age as random value between min/max set in hdev.
5102 */
5103 conn_info_age = hdev->conn_info_min_age +
5104 prandom_u32_max(hdev->conn_info_max_age -
5105 hdev->conn_info_min_age);
5106
5107 /* Query controller to refresh cached values if they are too old or were
5108 * never read.
5109 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005110 if (time_after(jiffies, conn->conn_info_timestamp +
5111 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005112 !conn->conn_info_timestamp) {
5113 struct hci_request req;
5114 struct hci_cp_read_tx_power req_txp_cp;
5115 struct hci_cp_read_rssi req_rssi_cp;
5116 struct pending_cmd *cmd;
5117
5118 hci_req_init(&req, hdev);
5119 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5120 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5121 &req_rssi_cp);
5122
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005123 /* For LE links TX power does not change thus we don't need to
5124 * query for it once value is known.
5125 */
5126 if (!bdaddr_type_is_le(cp->addr.type) ||
5127 conn->tx_power == HCI_TX_POWER_INVALID) {
5128 req_txp_cp.handle = cpu_to_le16(conn->handle);
5129 req_txp_cp.type = 0x00;
5130 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5131 sizeof(req_txp_cp), &req_txp_cp);
5132 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005133
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005134 /* Max TX power needs to be read only once per connection */
5135 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5136 req_txp_cp.handle = cpu_to_le16(conn->handle);
5137 req_txp_cp.type = 0x01;
5138 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5139 sizeof(req_txp_cp), &req_txp_cp);
5140 }
5141
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005142 err = hci_req_run(&req, conn_info_refresh_complete);
5143 if (err < 0)
5144 goto unlock;
5145
5146 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5147 data, len);
5148 if (!cmd) {
5149 err = -ENOMEM;
5150 goto unlock;
5151 }
5152
5153 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005154 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005155
5156 conn->conn_info_timestamp = jiffies;
5157 } else {
5158 /* Cache is valid, just reply with values cached in hci_conn */
5159 rp.rssi = conn->rssi;
5160 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005161 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005162
5163 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5164 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5165 }
5166
5167unlock:
5168 hci_dev_unlock(hdev);
5169 return err;
5170}
5171
Johan Hedberg95868422014-06-28 17:54:07 +03005172static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5173{
5174 struct mgmt_cp_get_clock_info *cp;
5175 struct mgmt_rp_get_clock_info rp;
5176 struct hci_cp_read_clock *hci_cp;
5177 struct pending_cmd *cmd;
5178 struct hci_conn *conn;
5179
5180 BT_DBG("%s status %u", hdev->name, status);
5181
5182 hci_dev_lock(hdev);
5183
5184 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5185 if (!hci_cp)
5186 goto unlock;
5187
5188 if (hci_cp->which) {
5189 u16 handle = __le16_to_cpu(hci_cp->handle);
5190 conn = hci_conn_hash_lookup_handle(hdev, handle);
5191 } else {
5192 conn = NULL;
5193 }
5194
5195 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5196 if (!cmd)
5197 goto unlock;
5198
5199 cp = cmd->param;
5200
5201 memset(&rp, 0, sizeof(rp));
5202 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5203
5204 if (status)
5205 goto send_rsp;
5206
5207 rp.local_clock = cpu_to_le32(hdev->clock);
5208
5209 if (conn) {
5210 rp.piconet_clock = cpu_to_le32(conn->clock);
5211 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5212 }
5213
5214send_rsp:
5215 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5216 &rp, sizeof(rp));
5217 mgmt_pending_remove(cmd);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005218 if (conn) {
Johan Hedberg95868422014-06-28 17:54:07 +03005219 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005220 hci_conn_put(conn);
5221 }
Johan Hedberg95868422014-06-28 17:54:07 +03005222
5223unlock:
5224 hci_dev_unlock(hdev);
5225}
5226
5227static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5228 u16 len)
5229{
5230 struct mgmt_cp_get_clock_info *cp = data;
5231 struct mgmt_rp_get_clock_info rp;
5232 struct hci_cp_read_clock hci_cp;
5233 struct pending_cmd *cmd;
5234 struct hci_request req;
5235 struct hci_conn *conn;
5236 int err;
5237
5238 BT_DBG("%s", hdev->name);
5239
5240 memset(&rp, 0, sizeof(rp));
5241 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5242 rp.addr.type = cp->addr.type;
5243
5244 if (cp->addr.type != BDADDR_BREDR)
5245 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5246 MGMT_STATUS_INVALID_PARAMS,
5247 &rp, sizeof(rp));
5248
5249 hci_dev_lock(hdev);
5250
5251 if (!hdev_is_powered(hdev)) {
5252 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5253 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5254 goto unlock;
5255 }
5256
5257 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5258 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5259 &cp->addr.bdaddr);
5260 if (!conn || conn->state != BT_CONNECTED) {
5261 err = cmd_complete(sk, hdev->id,
5262 MGMT_OP_GET_CLOCK_INFO,
5263 MGMT_STATUS_NOT_CONNECTED,
5264 &rp, sizeof(rp));
5265 goto unlock;
5266 }
5267 } else {
5268 conn = NULL;
5269 }
5270
5271 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5272 if (!cmd) {
5273 err = -ENOMEM;
5274 goto unlock;
5275 }
5276
5277 hci_req_init(&req, hdev);
5278
5279 memset(&hci_cp, 0, sizeof(hci_cp));
5280 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5281
5282 if (conn) {
5283 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005284 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005285
5286 hci_cp.handle = cpu_to_le16(conn->handle);
5287 hci_cp.which = 0x01; /* Piconet clock */
5288 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5289 }
5290
5291 err = hci_req_run(&req, get_clock_info_complete);
5292 if (err < 0)
5293 mgmt_pending_remove(cmd);
5294
5295unlock:
5296 hci_dev_unlock(hdev);
5297 return err;
5298}
5299
Marcel Holtmann8afef092014-06-29 22:28:34 +02005300static void device_added(struct sock *sk, struct hci_dev *hdev,
5301 bdaddr_t *bdaddr, u8 type, u8 action)
5302{
5303 struct mgmt_ev_device_added ev;
5304
5305 bacpy(&ev.addr.bdaddr, bdaddr);
5306 ev.addr.type = type;
5307 ev.action = action;
5308
5309 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5310}
5311
Marcel Holtmann2faade52014-06-29 19:44:03 +02005312static int add_device(struct sock *sk, struct hci_dev *hdev,
5313 void *data, u16 len)
5314{
5315 struct mgmt_cp_add_device *cp = data;
5316 u8 auto_conn, addr_type;
5317 int err;
5318
5319 BT_DBG("%s", hdev->name);
5320
Johan Hedberg66593582014-07-09 12:59:14 +03005321 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005322 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5323 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5324 MGMT_STATUS_INVALID_PARAMS,
5325 &cp->addr, sizeof(cp->addr));
5326
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005327 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005328 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5329 MGMT_STATUS_INVALID_PARAMS,
5330 &cp->addr, sizeof(cp->addr));
5331
5332 hci_dev_lock(hdev);
5333
Johan Hedberg66593582014-07-09 12:59:14 +03005334 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005335 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005336 if (cp->action != 0x01) {
5337 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5338 MGMT_STATUS_INVALID_PARAMS,
5339 &cp->addr, sizeof(cp->addr));
5340 goto unlock;
5341 }
5342
5343 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5344 cp->addr.type);
5345 if (err)
5346 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005347
Johan Hedberg432df052014-08-01 11:13:31 +03005348 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005349
Johan Hedberg66593582014-07-09 12:59:14 +03005350 goto added;
5351 }
5352
Marcel Holtmann2faade52014-06-29 19:44:03 +02005353 if (cp->addr.type == BDADDR_LE_PUBLIC)
5354 addr_type = ADDR_LE_DEV_PUBLIC;
5355 else
5356 addr_type = ADDR_LE_DEV_RANDOM;
5357
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005358 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005359 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005360 else if (cp->action == 0x01)
5361 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005362 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005363 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005364
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005365 /* If the connection parameters don't exist for this device,
5366 * they will be created and configured with defaults.
5367 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005368 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5369 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005370 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5371 MGMT_STATUS_FAILED,
5372 &cp->addr, sizeof(cp->addr));
5373 goto unlock;
5374 }
5375
Johan Hedberg66593582014-07-09 12:59:14 +03005376added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005377 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5378
Marcel Holtmann2faade52014-06-29 19:44:03 +02005379 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5380 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5381
5382unlock:
5383 hci_dev_unlock(hdev);
5384 return err;
5385}
5386
Marcel Holtmann8afef092014-06-29 22:28:34 +02005387static void device_removed(struct sock *sk, struct hci_dev *hdev,
5388 bdaddr_t *bdaddr, u8 type)
5389{
5390 struct mgmt_ev_device_removed ev;
5391
5392 bacpy(&ev.addr.bdaddr, bdaddr);
5393 ev.addr.type = type;
5394
5395 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5396}
5397
Marcel Holtmann2faade52014-06-29 19:44:03 +02005398static int remove_device(struct sock *sk, struct hci_dev *hdev,
5399 void *data, u16 len)
5400{
5401 struct mgmt_cp_remove_device *cp = data;
5402 int err;
5403
5404 BT_DBG("%s", hdev->name);
5405
5406 hci_dev_lock(hdev);
5407
5408 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005409 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005410 u8 addr_type;
5411
Johan Hedberg66593582014-07-09 12:59:14 +03005412 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005413 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5414 MGMT_STATUS_INVALID_PARAMS,
5415 &cp->addr, sizeof(cp->addr));
5416 goto unlock;
5417 }
5418
Johan Hedberg66593582014-07-09 12:59:14 +03005419 if (cp->addr.type == BDADDR_BREDR) {
5420 err = hci_bdaddr_list_del(&hdev->whitelist,
5421 &cp->addr.bdaddr,
5422 cp->addr.type);
5423 if (err) {
5424 err = cmd_complete(sk, hdev->id,
5425 MGMT_OP_REMOVE_DEVICE,
5426 MGMT_STATUS_INVALID_PARAMS,
5427 &cp->addr, sizeof(cp->addr));
5428 goto unlock;
5429 }
5430
Johan Hedberg432df052014-08-01 11:13:31 +03005431 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005432
Johan Hedberg66593582014-07-09 12:59:14 +03005433 device_removed(sk, hdev, &cp->addr.bdaddr,
5434 cp->addr.type);
5435 goto complete;
5436 }
5437
Marcel Holtmann2faade52014-06-29 19:44:03 +02005438 if (cp->addr.type == BDADDR_LE_PUBLIC)
5439 addr_type = ADDR_LE_DEV_PUBLIC;
5440 else
5441 addr_type = ADDR_LE_DEV_RANDOM;
5442
Johan Hedbergc71593d2014-07-02 17:37:28 +03005443 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5444 addr_type);
5445 if (!params) {
5446 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5447 MGMT_STATUS_INVALID_PARAMS,
5448 &cp->addr, sizeof(cp->addr));
5449 goto unlock;
5450 }
5451
5452 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5453 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5454 MGMT_STATUS_INVALID_PARAMS,
5455 &cp->addr, sizeof(cp->addr));
5456 goto unlock;
5457 }
5458
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005459 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005460 list_del(&params->list);
5461 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005462 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005463
5464 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005465 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005466 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005467 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005468
Marcel Holtmann2faade52014-06-29 19:44:03 +02005469 if (cp->addr.type) {
5470 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5471 MGMT_STATUS_INVALID_PARAMS,
5472 &cp->addr, sizeof(cp->addr));
5473 goto unlock;
5474 }
5475
Johan Hedberg66593582014-07-09 12:59:14 +03005476 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5477 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5478 list_del(&b->list);
5479 kfree(b);
5480 }
5481
Johan Hedberg432df052014-08-01 11:13:31 +03005482 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005483
Johan Hedberg19de0822014-07-06 13:06:51 +03005484 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5485 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5486 continue;
5487 device_removed(sk, hdev, &p->addr, p->addr_type);
5488 list_del(&p->action);
5489 list_del(&p->list);
5490 kfree(p);
5491 }
5492
5493 BT_DBG("All LE connection parameters were removed");
5494
5495 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005496 }
5497
Johan Hedberg66593582014-07-09 12:59:14 +03005498complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005499 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5500 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5501
5502unlock:
5503 hci_dev_unlock(hdev);
5504 return err;
5505}
5506
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005507static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5508 u16 len)
5509{
5510 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005511 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5512 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005513 u16 param_count, expected_len;
5514 int i;
5515
5516 if (!lmp_le_capable(hdev))
5517 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5518 MGMT_STATUS_NOT_SUPPORTED);
5519
5520 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005521 if (param_count > max_param_count) {
5522 BT_ERR("load_conn_param: too big param_count value %u",
5523 param_count);
5524 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5525 MGMT_STATUS_INVALID_PARAMS);
5526 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005527
5528 expected_len = sizeof(*cp) + param_count *
5529 sizeof(struct mgmt_conn_param);
5530 if (expected_len != len) {
5531 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5532 expected_len, len);
5533 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5534 MGMT_STATUS_INVALID_PARAMS);
5535 }
5536
5537 BT_DBG("%s param_count %u", hdev->name, param_count);
5538
5539 hci_dev_lock(hdev);
5540
5541 hci_conn_params_clear_disabled(hdev);
5542
5543 for (i = 0; i < param_count; i++) {
5544 struct mgmt_conn_param *param = &cp->params[i];
5545 struct hci_conn_params *hci_param;
5546 u16 min, max, latency, timeout;
5547 u8 addr_type;
5548
5549 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5550 param->addr.type);
5551
5552 if (param->addr.type == BDADDR_LE_PUBLIC) {
5553 addr_type = ADDR_LE_DEV_PUBLIC;
5554 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5555 addr_type = ADDR_LE_DEV_RANDOM;
5556 } else {
5557 BT_ERR("Ignoring invalid connection parameters");
5558 continue;
5559 }
5560
5561 min = le16_to_cpu(param->min_interval);
5562 max = le16_to_cpu(param->max_interval);
5563 latency = le16_to_cpu(param->latency);
5564 timeout = le16_to_cpu(param->timeout);
5565
5566 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5567 min, max, latency, timeout);
5568
5569 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5570 BT_ERR("Ignoring invalid connection parameters");
5571 continue;
5572 }
5573
5574 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5575 addr_type);
5576 if (!hci_param) {
5577 BT_ERR("Failed to add connection parameters");
5578 continue;
5579 }
5580
5581 hci_param->conn_min_interval = min;
5582 hci_param->conn_max_interval = max;
5583 hci_param->conn_latency = latency;
5584 hci_param->supervision_timeout = timeout;
5585 }
5586
5587 hci_dev_unlock(hdev);
5588
5589 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5590}
5591
Marcel Holtmanndbece372014-07-04 18:11:55 +02005592static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5593 void *data, u16 len)
5594{
5595 struct mgmt_cp_set_external_config *cp = data;
5596 bool changed;
5597 int err;
5598
5599 BT_DBG("%s", hdev->name);
5600
5601 if (hdev_is_powered(hdev))
5602 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5603 MGMT_STATUS_REJECTED);
5604
5605 if (cp->config != 0x00 && cp->config != 0x01)
5606 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5607 MGMT_STATUS_INVALID_PARAMS);
5608
5609 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5610 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5611 MGMT_STATUS_NOT_SUPPORTED);
5612
5613 hci_dev_lock(hdev);
5614
5615 if (cp->config)
5616 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5617 &hdev->dev_flags);
5618 else
5619 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5620 &hdev->dev_flags);
5621
5622 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5623 if (err < 0)
5624 goto unlock;
5625
5626 if (!changed)
5627 goto unlock;
5628
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005629 err = new_options(hdev, sk);
5630
Marcel Holtmanndbece372014-07-04 18:11:55 +02005631 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5632 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005633
5634 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5635 set_bit(HCI_CONFIG, &hdev->dev_flags);
5636 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5637
5638 queue_work(hdev->req_workqueue, &hdev->power_on);
5639 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005640 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005641 mgmt_index_added(hdev);
5642 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005643 }
5644
5645unlock:
5646 hci_dev_unlock(hdev);
5647 return err;
5648}
5649
Marcel Holtmann9713c172014-07-06 12:11:15 +02005650static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5651 void *data, u16 len)
5652{
5653 struct mgmt_cp_set_public_address *cp = data;
5654 bool changed;
5655 int err;
5656
5657 BT_DBG("%s", hdev->name);
5658
5659 if (hdev_is_powered(hdev))
5660 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5661 MGMT_STATUS_REJECTED);
5662
5663 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5664 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5665 MGMT_STATUS_INVALID_PARAMS);
5666
5667 if (!hdev->set_bdaddr)
5668 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5669 MGMT_STATUS_NOT_SUPPORTED);
5670
5671 hci_dev_lock(hdev);
5672
5673 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5674 bacpy(&hdev->public_addr, &cp->bdaddr);
5675
5676 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5677 if (err < 0)
5678 goto unlock;
5679
5680 if (!changed)
5681 goto unlock;
5682
5683 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5684 err = new_options(hdev, sk);
5685
5686 if (is_configured(hdev)) {
5687 mgmt_index_removed(hdev);
5688
5689 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5690
5691 set_bit(HCI_CONFIG, &hdev->dev_flags);
5692 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5693
5694 queue_work(hdev->req_workqueue, &hdev->power_on);
5695 }
5696
5697unlock:
5698 hci_dev_unlock(hdev);
5699 return err;
5700}
5701
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005702static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005703 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5704 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005705 bool var_len;
5706 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005707} mgmt_handlers[] = {
5708 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005709 { read_version, false, MGMT_READ_VERSION_SIZE },
5710 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5711 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5712 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5713 { set_powered, false, MGMT_SETTING_SIZE },
5714 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5715 { set_connectable, false, MGMT_SETTING_SIZE },
5716 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005717 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005718 { set_link_security, false, MGMT_SETTING_SIZE },
5719 { set_ssp, false, MGMT_SETTING_SIZE },
5720 { set_hs, false, MGMT_SETTING_SIZE },
5721 { set_le, false, MGMT_SETTING_SIZE },
5722 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5723 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5724 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5725 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5726 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5727 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5728 { disconnect, false, MGMT_DISCONNECT_SIZE },
5729 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5730 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5731 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5732 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5733 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5734 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5735 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5736 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5737 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5738 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5739 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5740 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005741 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005742 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5743 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5744 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5745 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5746 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5747 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005748 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005749 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005750 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005751 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005752 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005753 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005754 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005755 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005756 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005757 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005758 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005759 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5760 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005761 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5762 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005763 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005764 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005765 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005766};
5767
Johan Hedberg03811012010-12-08 00:21:06 +02005768int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5769{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005770 void *buf;
5771 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005772 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005773 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005774 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005775 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005776 int err;
5777
5778 BT_DBG("got %zu bytes", msglen);
5779
5780 if (msglen < sizeof(*hdr))
5781 return -EINVAL;
5782
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005783 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005784 if (!buf)
5785 return -ENOMEM;
5786
5787 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5788 err = -EFAULT;
5789 goto done;
5790 }
5791
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005792 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005793 opcode = __le16_to_cpu(hdr->opcode);
5794 index = __le16_to_cpu(hdr->index);
5795 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005796
5797 if (len != msglen - sizeof(*hdr)) {
5798 err = -EINVAL;
5799 goto done;
5800 }
5801
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005802 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005803 hdev = hci_dev_get(index);
5804 if (!hdev) {
5805 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005806 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005807 goto done;
5808 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005809
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005810 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005811 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005812 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005813 err = cmd_status(sk, index, opcode,
5814 MGMT_STATUS_INVALID_INDEX);
5815 goto done;
5816 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005817
5818 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005819 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005820 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5821 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005822 err = cmd_status(sk, index, opcode,
5823 MGMT_STATUS_INVALID_INDEX);
5824 goto done;
5825 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005826 }
5827
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005828 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005829 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005830 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005831 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005832 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005833 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005834 }
5835
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005836 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5837 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5838 err = cmd_status(sk, index, opcode,
5839 MGMT_STATUS_INVALID_INDEX);
5840 goto done;
5841 }
5842
5843 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5844 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005845 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005846 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005847 goto done;
5848 }
5849
Johan Hedbergbe22b542012-03-01 22:24:41 +02005850 handler = &mgmt_handlers[opcode];
5851
5852 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005853 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005854 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005855 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005856 goto done;
5857 }
5858
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005859 if (hdev)
5860 mgmt_init_hdev(sk, hdev);
5861
5862 cp = buf + sizeof(*hdr);
5863
Johan Hedbergbe22b542012-03-01 22:24:41 +02005864 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005865 if (err < 0)
5866 goto done;
5867
Johan Hedberg03811012010-12-08 00:21:06 +02005868 err = msglen;
5869
5870done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005871 if (hdev)
5872 hci_dev_put(hdev);
5873
Johan Hedberg03811012010-12-08 00:21:06 +02005874 kfree(buf);
5875 return err;
5876}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005877
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005878void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005879{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005880 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005881 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005882
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005883 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5884 return;
5885
5886 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5887 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5888 else
5889 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005890}
5891
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005892void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005893{
Johan Hedberg5f159032012-03-02 03:13:19 +02005894 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005895
Marcel Holtmann1514b892013-10-06 08:25:01 -07005896 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005897 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005898
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005899 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5900 return;
5901
Johan Hedberg744cf192011-11-08 20:40:14 +02005902 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005903
Marcel Holtmannedd38962014-07-02 21:30:55 +02005904 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5905 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5906 else
5907 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005908}
5909
Andre Guedes6046dc32014-02-26 20:21:51 -03005910/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005911static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005912{
5913 struct hci_conn_params *p;
5914
5915 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005916 /* Needed for AUTO_OFF case where might not "really"
5917 * have been powered off.
5918 */
5919 list_del_init(&p->action);
5920
5921 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005922 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03005923 case HCI_AUTO_CONN_ALWAYS:
5924 list_add(&p->action, &hdev->pend_le_conns);
5925 break;
5926 case HCI_AUTO_CONN_REPORT:
5927 list_add(&p->action, &hdev->pend_le_reports);
5928 break;
5929 default:
5930 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005931 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005932 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005933
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005934 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005935}
5936
Johan Hedberg229ab392013-03-15 17:06:53 -05005937static void powered_complete(struct hci_dev *hdev, u8 status)
5938{
5939 struct cmd_lookup match = { NULL, hdev };
5940
5941 BT_DBG("status 0x%02x", status);
5942
5943 hci_dev_lock(hdev);
5944
Johan Hedbergd7347f32014-07-04 12:37:23 +03005945 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005946
Johan Hedberg229ab392013-03-15 17:06:53 -05005947 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5948
5949 new_settings(hdev, match.sk);
5950
5951 hci_dev_unlock(hdev);
5952
5953 if (match.sk)
5954 sock_put(match.sk);
5955}
5956
Johan Hedberg70da6242013-03-15 17:06:51 -05005957static int powered_update_hci(struct hci_dev *hdev)
5958{
Johan Hedberg890ea892013-03-15 17:06:52 -05005959 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005960 u8 link_sec;
5961
Johan Hedberg890ea892013-03-15 17:06:52 -05005962 hci_req_init(&req, hdev);
5963
Johan Hedberg70da6242013-03-15 17:06:51 -05005964 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5965 !lmp_host_ssp_capable(hdev)) {
5966 u8 ssp = 1;
5967
Johan Hedberg890ea892013-03-15 17:06:52 -05005968 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005969 }
5970
Johan Hedbergc73eee92013-04-19 18:35:21 +03005971 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5972 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005973 struct hci_cp_write_le_host_supported cp;
5974
Marcel Holtmann32226e42014-07-24 20:04:16 +02005975 cp.le = 0x01;
5976 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05005977
5978 /* Check first if we already have the right
5979 * host state (host features set)
5980 */
5981 if (cp.le != lmp_host_le_capable(hdev) ||
5982 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005983 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5984 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005985 }
5986
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005987 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005988 /* Make sure the controller has a good default for
5989 * advertising data. This also applies to the case
5990 * where BR/EDR was toggled during the AUTO_OFF phase.
5991 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005992 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005993 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005994 update_scan_rsp_data(&req);
5995 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005996
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005997 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5998 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005999 }
6000
Johan Hedberg70da6242013-03-15 17:06:51 -05006001 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6002 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006003 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6004 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006005
6006 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006007 write_fast_connectable(&req, false);
6008 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006009 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006010 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006011 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006012 }
6013
Johan Hedberg229ab392013-03-15 17:06:53 -05006014 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006015}
6016
Johan Hedberg744cf192011-11-08 20:40:14 +02006017int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006018{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006019 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006020 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6021 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006022 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006023
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006024 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6025 return 0;
6026
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006027 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006028 if (powered_update_hci(hdev) == 0)
6029 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006030
Johan Hedberg229ab392013-03-15 17:06:53 -05006031 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6032 &match);
6033 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006034 }
6035
Johan Hedberg229ab392013-03-15 17:06:53 -05006036 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6037 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
6038
6039 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6040 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6041 zero_cod, sizeof(zero_cod), NULL);
6042
6043new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006044 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006045
6046 if (match.sk)
6047 sock_put(match.sk);
6048
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006049 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006050}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006051
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006052void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006053{
6054 struct pending_cmd *cmd;
6055 u8 status;
6056
6057 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6058 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006059 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006060
6061 if (err == -ERFKILL)
6062 status = MGMT_STATUS_RFKILLED;
6063 else
6064 status = MGMT_STATUS_FAILED;
6065
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006066 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006067
6068 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006069}
6070
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006071void mgmt_discoverable_timeout(struct hci_dev *hdev)
6072{
6073 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006074
6075 hci_dev_lock(hdev);
6076
6077 /* When discoverable timeout triggers, then just make sure
6078 * the limited discoverable flag is cleared. Even in the case
6079 * of a timeout triggered from general discoverable, it is
6080 * safe to unconditionally clear the flag.
6081 */
6082 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006083 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006084
6085 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006086 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6087 u8 scan = SCAN_PAGE;
6088 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6089 sizeof(scan), &scan);
6090 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006091 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006092 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006093 hci_req_run(&req, NULL);
6094
6095 hdev->discov_timeout = 0;
6096
Johan Hedberg9a43e252013-10-20 19:00:07 +03006097 new_settings(hdev, NULL);
6098
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006099 hci_dev_unlock(hdev);
6100}
6101
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006102void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6103 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006104{
Johan Hedberg86742e12011-11-07 23:13:38 +02006105 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006106
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006107 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006108
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006109 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006110 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006111 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006112 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006113 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006114 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006115
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006116 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006117}
Johan Hedbergf7520542011-01-20 12:34:39 +02006118
Johan Hedbergd7b25452014-05-23 13:19:53 +03006119static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6120{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006121 switch (ltk->type) {
6122 case SMP_LTK:
6123 case SMP_LTK_SLAVE:
6124 if (ltk->authenticated)
6125 return MGMT_LTK_AUTHENTICATED;
6126 return MGMT_LTK_UNAUTHENTICATED;
6127 case SMP_LTK_P256:
6128 if (ltk->authenticated)
6129 return MGMT_LTK_P256_AUTH;
6130 return MGMT_LTK_P256_UNAUTH;
6131 case SMP_LTK_P256_DEBUG:
6132 return MGMT_LTK_P256_DEBUG;
6133 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006134
6135 return MGMT_LTK_UNAUTHENTICATED;
6136}
6137
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006138void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006139{
6140 struct mgmt_ev_new_long_term_key ev;
6141
6142 memset(&ev, 0, sizeof(ev));
6143
Marcel Holtmann5192d302014-02-19 17:11:58 -08006144 /* Devices using resolvable or non-resolvable random addresses
6145 * without providing an indentity resolving key don't require
6146 * to store long term keys. Their addresses will change the
6147 * next time around.
6148 *
6149 * Only when a remote device provides an identity address
6150 * make sure the long term key is stored. If the remote
6151 * identity is known, the long term keys are internally
6152 * mapped to the identity address. So allow static random
6153 * and public addresses here.
6154 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006155 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6156 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6157 ev.store_hint = 0x00;
6158 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006159 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006160
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006161 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006162 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006163 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006164 ev.key.enc_size = key->enc_size;
6165 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006166 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006167
Johan Hedberg2ceba532014-06-16 19:25:16 +03006168 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006169 ev.key.master = 1;
6170
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006171 memcpy(ev.key.val, key->val, sizeof(key->val));
6172
Marcel Holtmann083368f2013-10-15 14:26:29 -07006173 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006174}
6175
Johan Hedberg95fbac82014-02-19 15:18:31 +02006176void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6177{
6178 struct mgmt_ev_new_irk ev;
6179
6180 memset(&ev, 0, sizeof(ev));
6181
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006182 /* For identity resolving keys from devices that are already
6183 * using a public address or static random address, do not
6184 * ask for storing this key. The identity resolving key really
6185 * is only mandatory for devices using resovlable random
6186 * addresses.
6187 *
6188 * Storing all identity resolving keys has the downside that
6189 * they will be also loaded on next boot of they system. More
6190 * identity resolving keys, means more time during scanning is
6191 * needed to actually resolve these addresses.
6192 */
6193 if (bacmp(&irk->rpa, BDADDR_ANY))
6194 ev.store_hint = 0x01;
6195 else
6196 ev.store_hint = 0x00;
6197
Johan Hedberg95fbac82014-02-19 15:18:31 +02006198 bacpy(&ev.rpa, &irk->rpa);
6199 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6200 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6201 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6202
6203 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6204}
6205
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006206void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6207 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006208{
6209 struct mgmt_ev_new_csrk ev;
6210
6211 memset(&ev, 0, sizeof(ev));
6212
6213 /* Devices using resolvable or non-resolvable random addresses
6214 * without providing an indentity resolving key don't require
6215 * to store signature resolving keys. Their addresses will change
6216 * the next time around.
6217 *
6218 * Only when a remote device provides an identity address
6219 * make sure the signature resolving key is stored. So allow
6220 * static random and public addresses here.
6221 */
6222 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6223 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6224 ev.store_hint = 0x00;
6225 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006226 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006227
6228 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6229 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6230 ev.key.master = csrk->master;
6231 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6232
6233 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6234}
6235
Andre Guedesffb5a8272014-07-01 18:10:11 -03006236void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006237 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6238 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006239{
6240 struct mgmt_ev_new_conn_param ev;
6241
Johan Hedbergc103aea2014-07-02 17:37:34 +03006242 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6243 return;
6244
Andre Guedesffb5a8272014-07-01 18:10:11 -03006245 memset(&ev, 0, sizeof(ev));
6246 bacpy(&ev.addr.bdaddr, bdaddr);
6247 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006248 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006249 ev.min_interval = cpu_to_le16(min_interval);
6250 ev.max_interval = cpu_to_le16(max_interval);
6251 ev.latency = cpu_to_le16(latency);
6252 ev.timeout = cpu_to_le16(timeout);
6253
6254 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6255}
6256
Marcel Holtmann94933992013-10-15 10:26:39 -07006257static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6258 u8 data_len)
6259{
6260 eir[eir_len++] = sizeof(type) + data_len;
6261 eir[eir_len++] = type;
6262 memcpy(&eir[eir_len], data, data_len);
6263 eir_len += data_len;
6264
6265 return eir_len;
6266}
6267
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006268void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6269 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006270{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006271 char buf[512];
6272 struct mgmt_ev_device_connected *ev = (void *) buf;
6273 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006274
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006275 bacpy(&ev->addr.bdaddr, &conn->dst);
6276 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006277
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006278 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006279
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006280 /* We must ensure that the EIR Data fields are ordered and
6281 * unique. Keep it simple for now and avoid the problem by not
6282 * adding any BR/EDR data to the LE adv.
6283 */
6284 if (conn->le_adv_data_len > 0) {
6285 memcpy(&ev->eir[eir_len],
6286 conn->le_adv_data, conn->le_adv_data_len);
6287 eir_len = conn->le_adv_data_len;
6288 } else {
6289 if (name_len > 0)
6290 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6291 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006292
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006293 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006294 eir_len = eir_append_data(ev->eir, eir_len,
6295 EIR_CLASS_OF_DEV,
6296 conn->dev_class, 3);
6297 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006298
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006299 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006300
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006301 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6302 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006303}
6304
Johan Hedberg8962ee72011-01-20 12:40:27 +02006305static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6306{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006307 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006308 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006309 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006310
Johan Hedberg88c3df12012-02-09 14:27:38 +02006311 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6312 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006313
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006314 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006315 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006316
6317 *sk = cmd->sk;
6318 sock_hold(*sk);
6319
Johan Hedberga664b5b2011-02-19 12:06:02 -03006320 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006321}
6322
Johan Hedberg124f6e32012-02-09 13:50:12 +02006323static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006324{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006325 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006326 struct mgmt_cp_unpair_device *cp = cmd->param;
6327 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006328
6329 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006330 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6331 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006332
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006333 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6334
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006335 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006336
6337 mgmt_pending_remove(cmd);
6338}
6339
Johan Hedberg84c61d92014-08-01 11:13:30 +03006340bool mgmt_powering_down(struct hci_dev *hdev)
6341{
6342 struct pending_cmd *cmd;
6343 struct mgmt_mode *cp;
6344
6345 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6346 if (!cmd)
6347 return false;
6348
6349 cp = cmd->param;
6350 if (!cp->val)
6351 return true;
6352
6353 return false;
6354}
6355
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006356void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006357 u8 link_type, u8 addr_type, u8 reason,
6358 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006359{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006360 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006361 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006362
Johan Hedberg84c61d92014-08-01 11:13:30 +03006363 /* The connection is still in hci_conn_hash so test for 1
6364 * instead of 0 to know if this is the last one.
6365 */
6366 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6367 cancel_delayed_work(&hdev->power_off);
6368 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006369 }
6370
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006371 if (!mgmt_connected)
6372 return;
6373
Andre Guedes57eb7762013-10-30 19:01:41 -03006374 if (link_type != ACL_LINK && link_type != LE_LINK)
6375 return;
6376
Johan Hedberg744cf192011-11-08 20:40:14 +02006377 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006378
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006379 bacpy(&ev.addr.bdaddr, bdaddr);
6380 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6381 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006382
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006383 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006384
6385 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006386 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006387
Johan Hedberg124f6e32012-02-09 13:50:12 +02006388 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006389 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006390}
6391
Marcel Holtmann78929242013-10-06 23:55:47 -07006392void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6393 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006394{
Andre Guedes3655bba2013-10-30 19:01:40 -03006395 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6396 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006397 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006398 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006399
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006400 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6401 hdev);
6402
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006403 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006404 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006405 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006406
Andre Guedes3655bba2013-10-30 19:01:40 -03006407 cp = cmd->param;
6408
6409 if (bacmp(bdaddr, &cp->addr.bdaddr))
6410 return;
6411
6412 if (cp->addr.type != bdaddr_type)
6413 return;
6414
Johan Hedberg88c3df12012-02-09 14:27:38 +02006415 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006416 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006417
Marcel Holtmann78929242013-10-06 23:55:47 -07006418 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6419 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006420
Johan Hedberga664b5b2011-02-19 12:06:02 -03006421 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006422}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006423
Marcel Holtmann445608d2013-10-06 23:55:48 -07006424void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6425 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006426{
6427 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006428
Johan Hedberg84c61d92014-08-01 11:13:30 +03006429 /* The connection is still in hci_conn_hash so test for 1
6430 * instead of 0 to know if this is the last one.
6431 */
6432 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6433 cancel_delayed_work(&hdev->power_off);
6434 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006435 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006436
Johan Hedberg4c659c32011-11-07 23:13:39 +02006437 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006438 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006439 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006440
Marcel Holtmann445608d2013-10-06 23:55:48 -07006441 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006442}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006443
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006444void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006445{
6446 struct mgmt_ev_pin_code_request ev;
6447
Johan Hedbergd8457692012-02-17 14:24:57 +02006448 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006449 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006450 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006451
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006452 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006453}
6454
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006455void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6456 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006457{
6458 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006459 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006460
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006461 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006462 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006463 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006464
Johan Hedbergd8457692012-02-17 14:24:57 +02006465 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006466 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006467
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006468 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6469 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006470
Johan Hedberga664b5b2011-02-19 12:06:02 -03006471 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006472}
6473
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006474void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6475 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006476{
6477 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006478 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006479
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006480 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006481 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006482 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006483
Johan Hedbergd8457692012-02-17 14:24:57 +02006484 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006485 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006486
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006487 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6488 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006489
Johan Hedberga664b5b2011-02-19 12:06:02 -03006490 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006491}
Johan Hedberga5c29682011-02-19 12:05:57 -03006492
Johan Hedberg744cf192011-11-08 20:40:14 +02006493int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006494 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006495 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006496{
6497 struct mgmt_ev_user_confirm_request ev;
6498
Johan Hedberg744cf192011-11-08 20:40:14 +02006499 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006500
Johan Hedberg272d90d2012-02-09 15:26:12 +02006501 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006502 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006503 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006504 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006505
Johan Hedberg744cf192011-11-08 20:40:14 +02006506 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006507 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006508}
6509
Johan Hedberg272d90d2012-02-09 15:26:12 +02006510int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006511 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006512{
6513 struct mgmt_ev_user_passkey_request ev;
6514
6515 BT_DBG("%s", hdev->name);
6516
Johan Hedberg272d90d2012-02-09 15:26:12 +02006517 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006518 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006519
6520 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006521 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006522}
6523
Brian Gix0df4c182011-11-16 13:53:13 -08006524static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006525 u8 link_type, u8 addr_type, u8 status,
6526 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006527{
6528 struct pending_cmd *cmd;
6529 struct mgmt_rp_user_confirm_reply rp;
6530 int err;
6531
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006532 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006533 if (!cmd)
6534 return -ENOENT;
6535
Johan Hedberg272d90d2012-02-09 15:26:12 +02006536 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006537 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006538 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006539 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006540
Johan Hedberga664b5b2011-02-19 12:06:02 -03006541 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006542
6543 return err;
6544}
6545
Johan Hedberg744cf192011-11-08 20:40:14 +02006546int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006547 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006548{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006549 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006550 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006551}
6552
Johan Hedberg272d90d2012-02-09 15:26:12 +02006553int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006554 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006555{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006556 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006557 status,
6558 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006559}
Johan Hedberg2a611692011-02-19 12:06:00 -03006560
Brian Gix604086b2011-11-23 08:28:33 -08006561int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006562 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006563{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006564 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006565 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006566}
6567
Johan Hedberg272d90d2012-02-09 15:26:12 +02006568int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006569 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006570{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006571 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006572 status,
6573 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006574}
6575
Johan Hedberg92a25252012-09-06 18:39:26 +03006576int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6577 u8 link_type, u8 addr_type, u32 passkey,
6578 u8 entered)
6579{
6580 struct mgmt_ev_passkey_notify ev;
6581
6582 BT_DBG("%s", hdev->name);
6583
6584 bacpy(&ev.addr.bdaddr, bdaddr);
6585 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6586 ev.passkey = __cpu_to_le32(passkey);
6587 ev.entered = entered;
6588
6589 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6590}
6591
Johan Hedberge1e930f2014-09-08 17:09:49 -07006592void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006593{
6594 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006595 struct pending_cmd *cmd;
6596 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006597
Johan Hedberge1e930f2014-09-08 17:09:49 -07006598 bacpy(&ev.addr.bdaddr, &conn->dst);
6599 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6600 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006601
Johan Hedberge1e930f2014-09-08 17:09:49 -07006602 cmd = find_pairing(conn);
6603
6604 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6605 cmd ? cmd->sk : NULL);
6606
6607 if (cmd)
6608 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006609}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006610
Marcel Holtmann464996a2013-10-15 14:26:24 -07006611void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006612{
6613 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006614 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006615
6616 if (status) {
6617 u8 mgmt_err = mgmt_status(status);
6618 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006619 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006620 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006621 }
6622
Marcel Holtmann464996a2013-10-15 14:26:24 -07006623 if (test_bit(HCI_AUTH, &hdev->flags))
6624 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6625 &hdev->dev_flags);
6626 else
6627 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6628 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006629
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006630 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006631 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006632
Johan Hedberg47990ea2012-02-22 11:58:37 +02006633 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006634 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006635
6636 if (match.sk)
6637 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006638}
6639
Johan Hedberg890ea892013-03-15 17:06:52 -05006640static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006641{
Johan Hedberg890ea892013-03-15 17:06:52 -05006642 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006643 struct hci_cp_write_eir cp;
6644
Johan Hedberg976eb202012-10-24 21:12:01 +03006645 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006646 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006647
Johan Hedbergc80da272012-02-22 15:38:48 +02006648 memset(hdev->eir, 0, sizeof(hdev->eir));
6649
Johan Hedbergcacaf522012-02-21 00:52:42 +02006650 memset(&cp, 0, sizeof(cp));
6651
Johan Hedberg890ea892013-03-15 17:06:52 -05006652 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006653}
6654
Marcel Holtmann3e248562013-10-15 14:26:25 -07006655void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006656{
6657 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006658 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006659 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006660
6661 if (status) {
6662 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006663
6664 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006665 &hdev->dev_flags)) {
6666 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006667 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006668 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006669
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006670 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6671 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006672 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006673 }
6674
6675 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006676 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006677 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006678 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6679 if (!changed)
6680 changed = test_and_clear_bit(HCI_HS_ENABLED,
6681 &hdev->dev_flags);
6682 else
6683 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006684 }
6685
6686 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6687
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006688 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006689 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006690
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006691 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006692 sock_put(match.sk);
6693
Johan Hedberg890ea892013-03-15 17:06:52 -05006694 hci_req_init(&req, hdev);
6695
Johan Hedberg37699722014-06-24 14:00:27 +03006696 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6697 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6698 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6699 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006700 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006701 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006702 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006703 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006704
6705 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006706}
6707
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006708void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6709{
6710 struct cmd_lookup match = { NULL, hdev };
6711 bool changed = false;
6712
6713 if (status) {
6714 u8 mgmt_err = mgmt_status(status);
6715
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006716 if (enable) {
6717 if (test_and_clear_bit(HCI_SC_ENABLED,
6718 &hdev->dev_flags))
6719 new_settings(hdev, NULL);
6720 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6721 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006722
6723 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6724 cmd_status_rsp, &mgmt_err);
6725 return;
6726 }
6727
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006728 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006729 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006730 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006731 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006732 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6733 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006734
6735 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6736 settings_rsp, &match);
6737
6738 if (changed)
6739 new_settings(hdev, match.sk);
6740
6741 if (match.sk)
6742 sock_put(match.sk);
6743}
6744
Johan Hedberg92da6092013-03-15 17:06:55 -05006745static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006746{
6747 struct cmd_lookup *match = data;
6748
Johan Hedberg90e70452012-02-23 23:09:40 +02006749 if (match->sk == NULL) {
6750 match->sk = cmd->sk;
6751 sock_hold(match->sk);
6752 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006753}
6754
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006755void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6756 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006757{
Johan Hedberg90e70452012-02-23 23:09:40 +02006758 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006759
Johan Hedberg92da6092013-03-15 17:06:55 -05006760 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6761 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6762 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006763
6764 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006765 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6766 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006767
6768 if (match.sk)
6769 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006770}
6771
Marcel Holtmann7667da32013-10-15 14:26:27 -07006772void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006773{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006774 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006775 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006776
Johan Hedberg13928972013-03-15 17:07:00 -05006777 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006778 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006779
6780 memset(&ev, 0, sizeof(ev));
6781 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006782 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006783
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006784 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006785 if (!cmd) {
6786 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006787
Johan Hedberg13928972013-03-15 17:07:00 -05006788 /* If this is a HCI command related to powering on the
6789 * HCI dev don't send any mgmt signals.
6790 */
6791 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006792 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006793 }
6794
Marcel Holtmann7667da32013-10-15 14:26:27 -07006795 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6796 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006797}
Szymon Jancc35938b2011-03-22 13:12:21 +01006798
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006799void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006800 u8 *rand192, u8 *hash256, u8 *rand256,
6801 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006802{
6803 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006804
Johan Hedberg744cf192011-11-08 20:40:14 +02006805 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006806
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006807 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006808 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006809 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006810
6811 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006812 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6813 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006814 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006815 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006816 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006817
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006818 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006819 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006820
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006821 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006822 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006823
6824 cmd_complete(cmd->sk, hdev->id,
6825 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6826 &rp, sizeof(rp));
6827 } else {
6828 struct mgmt_rp_read_local_oob_data rp;
6829
6830 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006831 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006832
6833 cmd_complete(cmd->sk, hdev->id,
6834 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6835 &rp, sizeof(rp));
6836 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006837 }
6838
6839 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006840}
Johan Hedberge17acd42011-03-30 23:57:16 +03006841
Marcel Holtmann901801b2013-10-06 23:55:51 -07006842void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006843 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6844 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006845{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006846 char buf[512];
6847 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006848 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006849
Johan Hedberg75ce2082014-07-02 22:42:01 +03006850 /* Don't send events for a non-kernel initiated discovery. With
6851 * LE one exception is if we have pend_le_reports > 0 in which
6852 * case we're doing passive scanning and want these events.
6853 */
6854 if (!hci_discovery_active(hdev)) {
6855 if (link_type == ACL_LINK)
6856 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006857 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006858 return;
6859 }
Andre Guedes12602d02013-04-30 15:29:40 -03006860
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006861 /* Make sure that the buffer is big enough. The 5 extra bytes
6862 * are for the potential CoD field.
6863 */
6864 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006865 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006866
Johan Hedberg1dc06092012-01-15 21:01:23 +02006867 memset(buf, 0, sizeof(buf));
6868
Johan Hedberg841c5642014-07-07 12:45:54 +03006869 bacpy(&ev->addr.bdaddr, bdaddr);
6870 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006871 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006872 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006873
Johan Hedberg1dc06092012-01-15 21:01:23 +02006874 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006875 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006876
Johan Hedberg1dc06092012-01-15 21:01:23 +02006877 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6878 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006879 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006880
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006881 if (scan_rsp_len > 0)
6882 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6883
6884 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6885 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006886
Marcel Holtmann901801b2013-10-06 23:55:51 -07006887 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006888}
Johan Hedberga88a9652011-03-30 13:18:12 +03006889
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006890void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6891 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006892{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006893 struct mgmt_ev_device_found *ev;
6894 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6895 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006896
Johan Hedbergb644ba32012-01-17 21:48:47 +02006897 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006898
Johan Hedbergb644ba32012-01-17 21:48:47 +02006899 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006900
Johan Hedbergb644ba32012-01-17 21:48:47 +02006901 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006902 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006903 ev->rssi = rssi;
6904
6905 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006906 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006907
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006908 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006909
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006910 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006911}
Johan Hedberg314b2382011-04-27 10:29:57 -04006912
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006913void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006914{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006915 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006916 struct pending_cmd *cmd;
6917
Andre Guedes343fb142011-11-22 17:14:19 -03006918 BT_DBG("%s discovering %u", hdev->name, discovering);
6919
Johan Hedberg164a6e72011-11-01 17:06:44 +02006920 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006921 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006922 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006923 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006924
6925 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006926 u8 type = hdev->discovery.type;
6927
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006928 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6929 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006930 mgmt_pending_remove(cmd);
6931 }
6932
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006933 memset(&ev, 0, sizeof(ev));
6934 ev.type = hdev->discovery.type;
6935 ev.discovering = discovering;
6936
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006937 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006938}
Antti Julku5e762442011-08-25 16:48:02 +03006939
Marcel Holtmann5976e602013-10-06 04:08:14 -07006940static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6941{
6942 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006943}
6944
6945void mgmt_reenable_advertising(struct hci_dev *hdev)
6946{
6947 struct hci_request req;
6948
Marcel Holtmann5976e602013-10-06 04:08:14 -07006949 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6950 return;
6951
6952 hci_req_init(&req, hdev);
6953 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006954 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006955}