blob: b8554d429d889f97bd735cc62aaafce1e85bae5c [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200132#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
133 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
134
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135struct pending_cmd {
136 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200137 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100139 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300556 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200580 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200582
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200583 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
584 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585 settings |= MGMT_SETTING_CONFIGURATION;
586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587 return settings;
588}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200589
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200590static u32 get_current_settings(struct hci_dev *hdev)
591{
592 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200593
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200594 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100595 settings |= MGMT_SETTING_POWERED;
596
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200597 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200598 settings |= MGMT_SETTING_CONNECTABLE;
599
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500600 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
601 settings |= MGMT_SETTING_FAST_CONNECTABLE;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_DISCOVERABLE;
605
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300606 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300607 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200608
Johan Hedberg56f87902013-10-02 13:43:13 +0300609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_BREDR;
611
Johan Hedberg06199cf2012-02-22 16:37:11 +0200612 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200614
Johan Hedberg47990ea2012-02-22 11:58:37 +0200615 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200617
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200618 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200620
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200621 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
622 settings |= MGMT_SETTING_HS;
623
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200624 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300625 settings |= MGMT_SETTING_ADVERTISING;
626
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_SECURE_CONN;
629
Johan Hedberg0663b292014-06-24 13:15:50 +0300630 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800631 settings |= MGMT_SETTING_DEBUG_KEYS;
632
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200633 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
634 settings |= MGMT_SETTING_PRIVACY;
635
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200636 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200637}
638
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300639#define PNP_INFO_SVCLASS_ID 0x1200
640
Johan Hedberg213202e2013-01-27 00:31:33 +0200641static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
642{
643 u8 *ptr = data, *uuids_start = NULL;
644 struct bt_uuid *uuid;
645
646 if (len < 4)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 u16 uuid16;
651
652 if (uuid->size != 16)
653 continue;
654
655 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
656 if (uuid16 < 0x1100)
657 continue;
658
659 if (uuid16 == PNP_INFO_SVCLASS_ID)
660 continue;
661
662 if (!uuids_start) {
663 uuids_start = ptr;
664 uuids_start[0] = 1;
665 uuids_start[1] = EIR_UUID16_ALL;
666 ptr += 2;
667 }
668
669 /* Stop if not enough space to put next UUID */
670 if ((ptr - data) + sizeof(u16) > len) {
671 uuids_start[1] = EIR_UUID16_SOME;
672 break;
673 }
674
675 *ptr++ = (uuid16 & 0x00ff);
676 *ptr++ = (uuid16 & 0xff00) >> 8;
677 uuids_start[0] += sizeof(uuid16);
678 }
679
680 return ptr;
681}
682
Johan Hedbergcdf19632013-01-27 00:31:34 +0200683static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
684{
685 u8 *ptr = data, *uuids_start = NULL;
686 struct bt_uuid *uuid;
687
688 if (len < 6)
689 return ptr;
690
691 list_for_each_entry(uuid, &hdev->uuids, list) {
692 if (uuid->size != 32)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID32_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u32) > len) {
704 uuids_start[1] = EIR_UUID32_SOME;
705 break;
706 }
707
708 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
709 ptr += sizeof(u32);
710 uuids_start[0] += sizeof(u32);
711 }
712
713 return ptr;
714}
715
Johan Hedbergc00d5752013-01-27 00:31:35 +0200716static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 18)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 128)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID128_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + 16 > len) {
737 uuids_start[1] = EIR_UUID128_SOME;
738 break;
739 }
740
741 memcpy(ptr, uuid->uuid, 16);
742 ptr += 16;
743 uuids_start[0] += 16;
744 }
745
746 return ptr;
747}
748
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300749static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
750{
751 struct pending_cmd *cmd;
752
753 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
754 if (cmd->opcode == opcode)
755 return cmd;
756 }
757
758 return NULL;
759}
760
Johan Hedberg95868422014-06-28 17:54:07 +0300761static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
762 struct hci_dev *hdev,
763 const void *data)
764{
765 struct pending_cmd *cmd;
766
767 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
768 if (cmd->user_data != data)
769 continue;
770 if (cmd->opcode == opcode)
771 return cmd;
772 }
773
774 return NULL;
775}
776
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700777static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
778{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700779 u8 ad_len = 0;
780 size_t name_len;
781
782 name_len = strlen(hdev->dev_name);
783 if (name_len > 0) {
784 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
785
786 if (name_len > max_len) {
787 name_len = max_len;
788 ptr[1] = EIR_NAME_SHORT;
789 } else
790 ptr[1] = EIR_NAME_COMPLETE;
791
792 ptr[0] = name_len + 1;
793
794 memcpy(ptr + 2, hdev->dev_name, name_len);
795
796 ad_len += (name_len + 2);
797 ptr += (name_len + 2);
798 }
799
800 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700801}
802
803static void update_scan_rsp_data(struct hci_request *req)
804{
805 struct hci_dev *hdev = req->hdev;
806 struct hci_cp_le_set_scan_rsp_data cp;
807 u8 len;
808
Johan Hedberg7751ef12013-10-19 23:38:15 +0300809 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700810 return;
811
812 memset(&cp, 0, sizeof(cp));
813
814 len = create_scan_rsp_data(hdev, cp.data);
815
Johan Hedbergeb438b52013-10-16 15:31:07 +0300816 if (hdev->scan_rsp_data_len == len &&
817 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700818 return;
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
821 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822
823 cp.length = len;
824
825 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
826}
827
Johan Hedberg9a43e252013-10-20 19:00:07 +0300828static u8 get_adv_discov_flags(struct hci_dev *hdev)
829{
830 struct pending_cmd *cmd;
831
832 /* If there's a pending mgmt command the flags will not yet have
833 * their final values, so check for this first.
834 */
835 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
836 if (cmd) {
837 struct mgmt_mode *cp = cmd->param;
838 if (cp->val == 0x01)
839 return LE_AD_GENERAL;
840 else if (cp->val == 0x02)
841 return LE_AD_LIMITED;
842 } else {
843 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_LIMITED;
845 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_GENERAL;
847 }
848
849 return 0;
850}
851
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700852static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853{
854 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberg9a43e252013-10-20 19:00:07 +0300856 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberge8340042014-01-30 11:16:50 -0800858 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
861 if (flags) {
862 BT_DBG("adv flags 0x%02x", flags);
863
864 ptr[0] = 2;
865 ptr[1] = EIR_FLAGS;
866 ptr[2] = flags;
867
868 ad_len += 3;
869 ptr += 3;
870 }
871
872 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
873 ptr[0] = 2;
874 ptr[1] = EIR_TX_POWER;
875 ptr[2] = (u8) hdev->adv_tx_power;
876
877 ad_len += 3;
878 ptr += 3;
879 }
880
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700881 return ad_len;
882}
883
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700884static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885{
886 struct hci_dev *hdev = req->hdev;
887 struct hci_cp_le_set_adv_data cp;
888 u8 len;
889
Johan Hedberg10994ce2013-10-19 23:38:16 +0300890 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891 return;
892
893 memset(&cp, 0, sizeof(cp));
894
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700895 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896
897 if (hdev->adv_data_len == len &&
898 memcmp(cp.data, hdev->adv_data, len) == 0)
899 return;
900
901 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
902 hdev->adv_data_len = len;
903
904 cp.length = len;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
907}
908
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300909int mgmt_update_adv_data(struct hci_dev *hdev)
910{
911 struct hci_request req;
912
913 hci_req_init(&req, hdev);
914 update_adv_data(&req);
915
916 return hci_req_run(&req, NULL);
917}
918
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300919static void create_eir(struct hci_dev *hdev, u8 *data)
920{
921 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300922 size_t name_len;
923
924 name_len = strlen(hdev->dev_name);
925
926 if (name_len > 0) {
927 /* EIR Data type */
928 if (name_len > 48) {
929 name_len = 48;
930 ptr[1] = EIR_NAME_SHORT;
931 } else
932 ptr[1] = EIR_NAME_COMPLETE;
933
934 /* EIR Data length */
935 ptr[0] = name_len + 1;
936
937 memcpy(ptr + 2, hdev->dev_name, name_len);
938
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300939 ptr += (name_len + 2);
940 }
941
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100942 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700943 ptr[0] = 2;
944 ptr[1] = EIR_TX_POWER;
945 ptr[2] = (u8) hdev->inq_tx_power;
946
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700947 ptr += 3;
948 }
949
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700950 if (hdev->devid_source > 0) {
951 ptr[0] = 9;
952 ptr[1] = EIR_DEVICE_ID;
953
954 put_unaligned_le16(hdev->devid_source, ptr + 2);
955 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
956 put_unaligned_le16(hdev->devid_product, ptr + 6);
957 put_unaligned_le16(hdev->devid_version, ptr + 8);
958
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700959 ptr += 10;
960 }
961
Johan Hedberg213202e2013-01-27 00:31:33 +0200962 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200963 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200964 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300965}
966
Johan Hedberg890ea892013-03-15 17:06:52 -0500967static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300968{
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970 struct hci_cp_write_eir cp;
971
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200972 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500973 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200974
Johan Hedberg976eb202012-10-24 21:12:01 +0300975 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500976 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300977
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200978 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200981 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500982 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300983
984 memset(&cp, 0, sizeof(cp));
985
986 create_eir(hdev, cp.data);
987
988 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500989 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300990
991 memcpy(hdev->eir, cp.data, sizeof(cp.data));
992
Johan Hedberg890ea892013-03-15 17:06:52 -0500993 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300994}
995
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200996static u8 get_service_classes(struct hci_dev *hdev)
997{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300998 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200999 u8 val = 0;
1000
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001001 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001002 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003
1004 return val;
1005}
1006
Johan Hedberg890ea892013-03-15 17:06:52 -05001007static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001008{
Johan Hedberg890ea892013-03-15 17:06:52 -05001009 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001010 u8 cod[3];
1011
1012 BT_DBG("%s", hdev->name);
1013
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001014 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001015 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001016
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001017 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1018 return;
1019
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001020 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
1023 cod[0] = hdev->minor_class;
1024 cod[1] = hdev->major_class;
1025 cod[2] = get_service_classes(hdev);
1026
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001027 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1028 cod[1] |= 0x20;
1029
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001031 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001032
Johan Hedberg890ea892013-03-15 17:06:52 -05001033 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001034}
1035
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037{
1038 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001039
1040 /* If there's a pending mgmt command the flag will not yet have
1041 * it's final value, so check for this first.
1042 */
1043 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1044 if (cmd) {
1045 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001046 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001047 }
1048
Johan Hedberga4858cb2014-02-25 19:56:31 +02001049 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001050}
1051
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001052static void disable_advertising(struct hci_request *req)
1053{
1054 u8 enable = 0x00;
1055
1056 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1057}
1058
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001059static void enable_advertising(struct hci_request *req)
1060{
1061 struct hci_dev *hdev = req->hdev;
1062 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001063 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001064 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001065
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001066 if (hci_conn_num(hdev, LE_LINK) > 0)
1067 return;
1068
1069 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1070 disable_advertising(req);
1071
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001072 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001073 * hci_update_random_address knows that it's safe to go ahead
1074 * and write a new random address. The flag will be set back on
1075 * as soon as the SET_ADV_ENABLE HCI command completes.
1076 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001077 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001078
Johan Hedberga4858cb2014-02-25 19:56:31 +02001079 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001080
Johan Hedberga4858cb2014-02-25 19:56:31 +02001081 /* Set require_privacy to true only when non-connectable
1082 * advertising is used. In that case it is fine to use a
1083 * non-resolvable private address.
1084 */
1085 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001086 return;
1087
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001088 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001089 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1090 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001091 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001092 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001093 cp.channel_map = hdev->le_adv_channel_map;
1094
1095 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1096
1097 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1098}
1099
Johan Hedberg7d785252011-12-15 00:47:39 +02001100static void service_cache_off(struct work_struct *work)
1101{
1102 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001103 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001104 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001105
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001106 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001107 return;
1108
Johan Hedberg890ea892013-03-15 17:06:52 -05001109 hci_req_init(&req, hdev);
1110
Johan Hedberg7d785252011-12-15 00:47:39 +02001111 hci_dev_lock(hdev);
1112
Johan Hedberg890ea892013-03-15 17:06:52 -05001113 update_eir(&req);
1114 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001115
1116 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001117
1118 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001119}
1120
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001121static void rpa_expired(struct work_struct *work)
1122{
1123 struct hci_dev *hdev = container_of(work, struct hci_dev,
1124 rpa_expired.work);
1125 struct hci_request req;
1126
1127 BT_DBG("");
1128
1129 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1130
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001131 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001132 return;
1133
1134 /* The generation of a new RPA and programming it into the
1135 * controller happens in the enable_advertising() function.
1136 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 hci_req_run(&req, NULL);
1140}
1141
Johan Hedberg6a919082012-02-28 06:17:26 +02001142static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001143{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001144 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001145 return;
1146
Johan Hedberg4f87da82012-03-02 19:55:56 +02001147 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001148 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001149
Johan Hedberg4f87da82012-03-02 19:55:56 +02001150 /* Non-mgmt controlled devices get this bit set
1151 * implicitly so that pairing works for them, however
1152 * for mgmt we require user-space to explicitly enable
1153 * it
1154 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001155 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001156}
1157
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001158static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001159 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001160{
1161 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001162
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001163 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001164
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001165 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001166
Johan Hedberg03811012010-12-08 00:21:06 +02001167 memset(&rp, 0, sizeof(rp));
1168
Johan Hedberg03811012010-12-08 00:21:06 +02001169 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001170
1171 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001172 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001173
1174 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1175 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1176
1177 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001178
1179 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001180 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001181
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001182 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001183
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001184 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001185 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001186}
1187
1188static void mgmt_pending_free(struct pending_cmd *cmd)
1189{
1190 sock_put(cmd->sk);
1191 kfree(cmd->param);
1192 kfree(cmd);
1193}
1194
1195static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001196 struct hci_dev *hdev, void *data,
1197 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001198{
1199 struct pending_cmd *cmd;
1200
Johan Hedbergfca20012014-06-28 17:54:05 +03001201 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001202 if (!cmd)
1203 return NULL;
1204
1205 cmd->opcode = opcode;
1206 cmd->index = hdev->id;
1207
Andre Guedes12b94562012-06-07 19:05:45 -03001208 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001209 if (!cmd->param) {
1210 kfree(cmd);
1211 return NULL;
1212 }
1213
1214 if (data)
1215 memcpy(cmd->param, data, len);
1216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberge6fe7982013-10-02 15:45:22 +03001475static u8 mgmt_bredr_support(struct hci_dev *hdev)
1476{
1477 if (!lmp_bredr_capable(hdev))
1478 return MGMT_STATUS_NOT_SUPPORTED;
1479 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1480 return MGMT_STATUS_REJECTED;
1481 else
1482 return MGMT_STATUS_SUCCESS;
1483}
1484
1485static u8 mgmt_le_support(struct hci_dev *hdev)
1486{
1487 if (!lmp_le_capable(hdev))
1488 return MGMT_STATUS_NOT_SUPPORTED;
1489 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1490 return MGMT_STATUS_REJECTED;
1491 else
1492 return MGMT_STATUS_SUCCESS;
1493}
1494
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001495static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1496{
1497 struct pending_cmd *cmd;
1498 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001499 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001500 bool changed;
1501
1502 BT_DBG("status 0x%02x", status);
1503
1504 hci_dev_lock(hdev);
1505
1506 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1507 if (!cmd)
1508 goto unlock;
1509
1510 if (status) {
1511 u8 mgmt_err = mgmt_status(status);
1512 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001513 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001514 goto remove_cmd;
1515 }
1516
1517 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001518 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001519 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1520 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001521
1522 if (hdev->discov_timeout > 0) {
1523 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1524 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1525 to);
1526 }
1527 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001528 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1529 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001530 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001531
1532 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1533
1534 if (changed)
1535 new_settings(hdev, cmd->sk);
1536
Marcel Holtmann970ba522013-10-15 06:33:57 -07001537 /* When the discoverable mode gets changed, make sure
1538 * that class of device has the limited discoverable
1539 * bit correctly set.
1540 */
1541 hci_req_init(&req, hdev);
1542 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 Hedbergbc6d2d02014-07-10 12:09:08 +03001788 if (discov_changed)
1789 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001790 hci_update_background_scan(hdev);
1791 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001792
Johan Hedberg37438c12013-10-14 16:20:05 +03001793remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001794 mgmt_pending_remove(cmd);
1795
1796unlock:
1797 hci_dev_unlock(hdev);
1798}
1799
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001800static int set_connectable_update_settings(struct hci_dev *hdev,
1801 struct sock *sk, u8 val)
1802{
1803 bool changed = false;
1804 int err;
1805
1806 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1807 changed = true;
1808
1809 if (val) {
1810 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1811 } else {
1812 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1813 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1814 }
1815
1816 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1817 if (err < 0)
1818 return err;
1819
Johan Hedberg562064e2014-07-08 16:35:34 +03001820 if (changed) {
1821 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001822 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001823 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001824
1825 return 0;
1826}
1827
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001828static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001829 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001830{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001831 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001832 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001833 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001834 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001835 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001836
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001837 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001838
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001839 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1840 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001841 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001842 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001843
Johan Hedberga7e80f22013-01-09 16:05:19 +02001844 if (cp->val != 0x00 && cp->val != 0x01)
1845 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1846 MGMT_STATUS_INVALID_PARAMS);
1847
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001848 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001849
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001850 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001851 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001852 goto failed;
1853 }
1854
1855 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001856 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001857 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001858 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001859 goto failed;
1860 }
1861
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001862 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1863 if (!cmd) {
1864 err = -ENOMEM;
1865 goto failed;
1866 }
1867
Johan Hedberg2b76f452013-03-15 17:07:04 -05001868 hci_req_init(&req, hdev);
1869
Johan Hedberg9a43e252013-10-20 19:00:07 +03001870 /* If BR/EDR is not enabled and we disable advertising as a
1871 * by-product of disabling connectable, we need to update the
1872 * advertising flags.
1873 */
1874 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1875 if (!cp->val) {
1876 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1877 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1878 }
1879 update_adv_data(&req);
1880 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001881 if (cp->val) {
1882 scan = SCAN_PAGE;
1883 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001884 /* If we don't have any whitelist entries just
1885 * disable all scanning. If there are entries
1886 * and we had both page and inquiry scanning
1887 * enabled then fall back to only page scanning.
1888 * Otherwise no changes are needed.
1889 */
1890 if (list_empty(&hdev->whitelist))
1891 scan = SCAN_DISABLED;
1892 else if (test_bit(HCI_ISCAN, &hdev->flags))
1893 scan = SCAN_PAGE;
1894 else
1895 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001896
1897 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001898 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001899 cancel_delayed_work(&hdev->discov_off);
1900 }
1901
1902 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1903 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001904
Johan Hedberg3bd27242014-07-28 20:53:58 +03001905no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001906 /* If we're going from non-connectable to connectable or
1907 * vice-versa when fast connectable is enabled ensure that fast
1908 * connectable gets disabled. write_fast_connectable won't do
1909 * anything if the page scan parameters are already what they
1910 * should be.
1911 */
1912 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001913 write_fast_connectable(&req, false);
1914
Johan Hedberge8b12022014-07-10 10:51:27 +03001915 /* Update the advertising parameters if necessary */
1916 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001917 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001918
Johan Hedberg2b76f452013-03-15 17:07:04 -05001919 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001920 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001921 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001922 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001923 err = set_connectable_update_settings(hdev, sk,
1924 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001925 goto failed;
1926 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001927
1928failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001929 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001930 return err;
1931}
1932
Johan Hedbergb2939472014-07-30 09:22:23 +03001933static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001934 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001935{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001936 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001937 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001938 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001939
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001940 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001941
Johan Hedberga7e80f22013-01-09 16:05:19 +02001942 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001943 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001944 MGMT_STATUS_INVALID_PARAMS);
1945
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001946 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001947
1948 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001949 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001950 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001951 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001952
Johan Hedbergb2939472014-07-30 09:22:23 +03001953 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001954 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001955 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001956
Marcel Holtmann55594352013-10-06 16:11:57 -07001957 if (changed)
1958 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001959
Marcel Holtmann55594352013-10-06 16:11:57 -07001960unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001961 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001962 return err;
1963}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001964
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001965static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1966 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001967{
1968 struct mgmt_mode *cp = data;
1969 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001970 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001971 int err;
1972
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001973 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001974
Johan Hedberge6fe7982013-10-02 15:45:22 +03001975 status = mgmt_bredr_support(hdev);
1976 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001977 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001978 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001979
Johan Hedberga7e80f22013-01-09 16:05:19 +02001980 if (cp->val != 0x00 && cp->val != 0x01)
1981 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1982 MGMT_STATUS_INVALID_PARAMS);
1983
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001984 hci_dev_lock(hdev);
1985
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001986 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001987 bool changed = false;
1988
1989 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001990 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001991 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1992 changed = true;
1993 }
1994
1995 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1996 if (err < 0)
1997 goto failed;
1998
1999 if (changed)
2000 err = new_settings(hdev, sk);
2001
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002002 goto failed;
2003 }
2004
2005 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002006 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002007 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002008 goto failed;
2009 }
2010
2011 val = !!cp->val;
2012
2013 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2014 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2015 goto failed;
2016 }
2017
2018 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2019 if (!cmd) {
2020 err = -ENOMEM;
2021 goto failed;
2022 }
2023
2024 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2025 if (err < 0) {
2026 mgmt_pending_remove(cmd);
2027 goto failed;
2028 }
2029
2030failed:
2031 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 return err;
2033}
2034
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002035static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002036{
2037 struct mgmt_mode *cp = data;
2038 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002039 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002040 int err;
2041
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002042 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002043
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002044 status = mgmt_bredr_support(hdev);
2045 if (status)
2046 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2047
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002048 if (!lmp_ssp_capable(hdev))
2049 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2050 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002051
Johan Hedberga7e80f22013-01-09 16:05:19 +02002052 if (cp->val != 0x00 && cp->val != 0x01)
2053 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2054 MGMT_STATUS_INVALID_PARAMS);
2055
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002056 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002057
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002058 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002059 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002060
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002061 if (cp->val) {
2062 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2063 &hdev->dev_flags);
2064 } else {
2065 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2066 &hdev->dev_flags);
2067 if (!changed)
2068 changed = test_and_clear_bit(HCI_HS_ENABLED,
2069 &hdev->dev_flags);
2070 else
2071 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002072 }
2073
2074 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2075 if (err < 0)
2076 goto failed;
2077
2078 if (changed)
2079 err = new_settings(hdev, sk);
2080
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002081 goto failed;
2082 }
2083
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002084 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2085 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002086 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2087 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002088 goto failed;
2089 }
2090
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002091 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002092 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2093 goto failed;
2094 }
2095
2096 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2097 if (!cmd) {
2098 err = -ENOMEM;
2099 goto failed;
2100 }
2101
Johan Hedberg37699722014-06-24 14:00:27 +03002102 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2103 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2104 sizeof(cp->val), &cp->val);
2105
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002106 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002107 if (err < 0) {
2108 mgmt_pending_remove(cmd);
2109 goto failed;
2110 }
2111
2112failed:
2113 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002114 return err;
2115}
2116
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002117static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002118{
2119 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002120 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002121 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002122 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002123
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002124 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002125
Johan Hedberge6fe7982013-10-02 15:45:22 +03002126 status = mgmt_bredr_support(hdev);
2127 if (status)
2128 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002129
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002130 if (!lmp_ssp_capable(hdev))
2131 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2132 MGMT_STATUS_NOT_SUPPORTED);
2133
2134 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2135 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2136 MGMT_STATUS_REJECTED);
2137
Johan Hedberga7e80f22013-01-09 16:05:19 +02002138 if (cp->val != 0x00 && cp->val != 0x01)
2139 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2140 MGMT_STATUS_INVALID_PARAMS);
2141
Marcel Holtmannee392692013-10-01 22:59:23 -07002142 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002143
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002144 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002145 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002146 } else {
2147 if (hdev_is_powered(hdev)) {
2148 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2149 MGMT_STATUS_REJECTED);
2150 goto unlock;
2151 }
2152
Marcel Holtmannee392692013-10-01 22:59:23 -07002153 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002154 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002155
2156 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2157 if (err < 0)
2158 goto unlock;
2159
2160 if (changed)
2161 err = new_settings(hdev, sk);
2162
2163unlock:
2164 hci_dev_unlock(hdev);
2165 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002166}
2167
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002168static void le_enable_complete(struct hci_dev *hdev, u8 status)
2169{
2170 struct cmd_lookup match = { NULL, hdev };
2171
2172 if (status) {
2173 u8 mgmt_err = mgmt_status(status);
2174
2175 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2176 &mgmt_err);
2177 return;
2178 }
2179
2180 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2181
2182 new_settings(hdev, match.sk);
2183
2184 if (match.sk)
2185 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002186
2187 /* Make sure the controller has a good default for
2188 * advertising data. Restrict the update to when LE
2189 * has actually been enabled. During power on, the
2190 * update in powered_update_hci will take care of it.
2191 */
2192 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2193 struct hci_request req;
2194
2195 hci_dev_lock(hdev);
2196
2197 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002198 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002199 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002200 hci_req_run(&req, NULL);
2201
Johan Hedberga70f4b52014-07-07 15:19:50 +03002202 hci_update_background_scan(hdev);
2203
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002204 hci_dev_unlock(hdev);
2205 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002206}
2207
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002208static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002209{
2210 struct mgmt_mode *cp = data;
2211 struct hci_cp_write_le_host_supported hci_cp;
2212 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002213 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002214 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002215 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002216
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002217 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002218
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002219 if (!lmp_le_capable(hdev))
2220 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2221 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002222
Johan Hedberga7e80f22013-01-09 16:05:19 +02002223 if (cp->val != 0x00 && cp->val != 0x01)
2224 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2225 MGMT_STATUS_INVALID_PARAMS);
2226
Johan Hedbergc73eee92013-04-19 18:35:21 +03002227 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002228 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002229 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2230 MGMT_STATUS_REJECTED);
2231
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002232 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002233
2234 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002235 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002236
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002237 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002238 bool changed = false;
2239
2240 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2241 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2242 changed = true;
2243 }
2244
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002245 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2246 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002247 changed = true;
2248 }
2249
Johan Hedberg06199cf2012-02-22 16:37:11 +02002250 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2251 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002252 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002253
2254 if (changed)
2255 err = new_settings(hdev, sk);
2256
Johan Hedberg1de028c2012-02-29 19:55:35 -08002257 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002258 }
2259
Johan Hedberg4375f102013-09-25 13:26:10 +03002260 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2261 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002262 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002263 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002264 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002265 }
2266
2267 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2268 if (!cmd) {
2269 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002270 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002271 }
2272
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002273 hci_req_init(&req, hdev);
2274
Johan Hedberg06199cf2012-02-22 16:37:11 +02002275 memset(&hci_cp, 0, sizeof(hci_cp));
2276
2277 if (val) {
2278 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002279 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002280 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002281 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002282 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002283 }
2284
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002285 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2286 &hci_cp);
2287
2288 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302289 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002290 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002291
Johan Hedberg1de028c2012-02-29 19:55:35 -08002292unlock:
2293 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002294 return err;
2295}
2296
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002297/* This is a helper function to test for pending mgmt commands that can
2298 * cause CoD or EIR HCI commands. We can only allow one such pending
2299 * mgmt command at a time since otherwise we cannot easily track what
2300 * the current values are, will be, and based on that calculate if a new
2301 * HCI command needs to be sent and if yes with what value.
2302 */
2303static bool pending_eir_or_class(struct hci_dev *hdev)
2304{
2305 struct pending_cmd *cmd;
2306
2307 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2308 switch (cmd->opcode) {
2309 case MGMT_OP_ADD_UUID:
2310 case MGMT_OP_REMOVE_UUID:
2311 case MGMT_OP_SET_DEV_CLASS:
2312 case MGMT_OP_SET_POWERED:
2313 return true;
2314 }
2315 }
2316
2317 return false;
2318}
2319
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002320static const u8 bluetooth_base_uuid[] = {
2321 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2322 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2323};
2324
2325static u8 get_uuid_size(const u8 *uuid)
2326{
2327 u32 val;
2328
2329 if (memcmp(uuid, bluetooth_base_uuid, 12))
2330 return 128;
2331
2332 val = get_unaligned_le32(&uuid[12]);
2333 if (val > 0xffff)
2334 return 32;
2335
2336 return 16;
2337}
2338
Johan Hedberg92da6092013-03-15 17:06:55 -05002339static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2340{
2341 struct pending_cmd *cmd;
2342
2343 hci_dev_lock(hdev);
2344
2345 cmd = mgmt_pending_find(mgmt_op, hdev);
2346 if (!cmd)
2347 goto unlock;
2348
2349 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2350 hdev->dev_class, 3);
2351
2352 mgmt_pending_remove(cmd);
2353
2354unlock:
2355 hci_dev_unlock(hdev);
2356}
2357
2358static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2359{
2360 BT_DBG("status 0x%02x", status);
2361
2362 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2363}
2364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002365static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002366{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002367 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002368 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002369 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002370 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002371 int err;
2372
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002373 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002374
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002375 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002376
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002377 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002378 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002379 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002380 goto failed;
2381 }
2382
Andre Guedes92c4c202012-06-07 19:05:44 -03002383 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002384 if (!uuid) {
2385 err = -ENOMEM;
2386 goto failed;
2387 }
2388
2389 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002390 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002391 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002392
Johan Hedbergde66aa62013-01-27 00:31:27 +02002393 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002394
Johan Hedberg890ea892013-03-15 17:06:52 -05002395 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002396
Johan Hedberg890ea892013-03-15 17:06:52 -05002397 update_class(&req);
2398 update_eir(&req);
2399
Johan Hedberg92da6092013-03-15 17:06:55 -05002400 err = hci_req_run(&req, add_uuid_complete);
2401 if (err < 0) {
2402 if (err != -ENODATA)
2403 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002405 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002406 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002407 goto failed;
2408 }
2409
2410 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002411 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002412 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002413 goto failed;
2414 }
2415
2416 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002417
2418failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002419 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002420 return err;
2421}
2422
Johan Hedberg24b78d02012-02-23 23:24:30 +02002423static bool enable_service_cache(struct hci_dev *hdev)
2424{
2425 if (!hdev_is_powered(hdev))
2426 return false;
2427
2428 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002429 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2430 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002431 return true;
2432 }
2433
2434 return false;
2435}
2436
Johan Hedberg92da6092013-03-15 17:06:55 -05002437static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2438{
2439 BT_DBG("status 0x%02x", status);
2440
2441 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2442}
2443
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002444static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002445 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002446{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002447 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002448 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002449 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002450 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 -05002451 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002452 int err, found;
2453
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002454 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002455
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002456 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002457
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002458 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002459 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002460 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002461 goto unlock;
2462 }
2463
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002464 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002465 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002466
Johan Hedberg24b78d02012-02-23 23:24:30 +02002467 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002468 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002469 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002470 goto unlock;
2471 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002472
Johan Hedberg9246a862012-02-23 21:33:16 +02002473 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002474 }
2475
2476 found = 0;
2477
Johan Hedberg056341c2013-01-27 00:31:30 +02002478 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002479 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2480 continue;
2481
2482 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002483 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002484 found++;
2485 }
2486
2487 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002488 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002489 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002490 goto unlock;
2491 }
2492
Johan Hedberg9246a862012-02-23 21:33:16 +02002493update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002494 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002495
Johan Hedberg890ea892013-03-15 17:06:52 -05002496 update_class(&req);
2497 update_eir(&req);
2498
Johan Hedberg92da6092013-03-15 17:06:55 -05002499 err = hci_req_run(&req, remove_uuid_complete);
2500 if (err < 0) {
2501 if (err != -ENODATA)
2502 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002503
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002504 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002505 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002506 goto unlock;
2507 }
2508
2509 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002510 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002511 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002512 goto unlock;
2513 }
2514
2515 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002516
2517unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002518 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002519 return err;
2520}
2521
Johan Hedberg92da6092013-03-15 17:06:55 -05002522static void set_class_complete(struct hci_dev *hdev, u8 status)
2523{
2524 BT_DBG("status 0x%02x", status);
2525
2526 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2527}
2528
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002529static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002530 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002531{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002532 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002533 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002534 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002535 int err;
2536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002537 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002538
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002539 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002540 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2541 MGMT_STATUS_NOT_SUPPORTED);
2542
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002543 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002544
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002545 if (pending_eir_or_class(hdev)) {
2546 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2547 MGMT_STATUS_BUSY);
2548 goto unlock;
2549 }
2550
2551 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2552 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2553 MGMT_STATUS_INVALID_PARAMS);
2554 goto unlock;
2555 }
2556
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002557 hdev->major_class = cp->major;
2558 hdev->minor_class = cp->minor;
2559
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002560 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002561 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002562 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002563 goto unlock;
2564 }
2565
Johan Hedberg890ea892013-03-15 17:06:52 -05002566 hci_req_init(&req, hdev);
2567
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002568 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002569 hci_dev_unlock(hdev);
2570 cancel_delayed_work_sync(&hdev->service_cache);
2571 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002572 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002573 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002574
Johan Hedberg890ea892013-03-15 17:06:52 -05002575 update_class(&req);
2576
Johan Hedberg92da6092013-03-15 17:06:55 -05002577 err = hci_req_run(&req, set_class_complete);
2578 if (err < 0) {
2579 if (err != -ENODATA)
2580 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002581
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002582 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002583 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002584 goto unlock;
2585 }
2586
2587 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002588 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002589 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002590 goto unlock;
2591 }
2592
2593 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002594
Johan Hedbergb5235a62012-02-21 14:32:24 +02002595unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002596 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002597 return err;
2598}
2599
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002600static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002601 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002602{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002603 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002604 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2605 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002606 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002607 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002608 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002609
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002610 BT_DBG("request for %s", hdev->name);
2611
2612 if (!lmp_bredr_capable(hdev))
2613 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2614 MGMT_STATUS_NOT_SUPPORTED);
2615
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002616 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002617 if (key_count > max_key_count) {
2618 BT_ERR("load_link_keys: too big key_count value %u",
2619 key_count);
2620 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2621 MGMT_STATUS_INVALID_PARAMS);
2622 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002623
Johan Hedberg86742e12011-11-07 23:13:38 +02002624 expected_len = sizeof(*cp) + key_count *
2625 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002626 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002627 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002628 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002629 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002630 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002631 }
2632
Johan Hedberg4ae14302013-01-20 14:27:13 +02002633 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2634 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2635 MGMT_STATUS_INVALID_PARAMS);
2636
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002637 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002638 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002640 for (i = 0; i < key_count; i++) {
2641 struct mgmt_link_key_info *key = &cp->keys[i];
2642
Marcel Holtmann8e991132014-01-10 02:07:25 -08002643 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002644 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2645 MGMT_STATUS_INVALID_PARAMS);
2646 }
2647
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002648 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002649
2650 hci_link_keys_clear(hdev);
2651
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002652 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002653 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2654 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002655 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002656 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2657 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002658
2659 if (changed)
2660 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002662 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002663 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002664
Johan Hedberg58e92932014-06-24 14:00:26 +03002665 /* Always ignore debug keys and require a new pairing if
2666 * the user wants to use them.
2667 */
2668 if (key->type == HCI_LK_DEBUG_COMBINATION)
2669 continue;
2670
Johan Hedberg7652ff62014-06-24 13:15:49 +03002671 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2672 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002673 }
2674
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002675 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002676
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002677 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002678
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002679 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002680}
2681
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002682static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002683 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002684{
2685 struct mgmt_ev_device_unpaired ev;
2686
2687 bacpy(&ev.addr.bdaddr, bdaddr);
2688 ev.addr.type = addr_type;
2689
2690 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002691 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002692}
2693
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002694static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002695 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002696{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002697 struct mgmt_cp_unpair_device *cp = data;
2698 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002699 struct hci_cp_disconnect dc;
2700 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002701 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702 int err;
2703
Johan Hedberga8a1d192011-11-10 15:54:38 +02002704 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002705 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2706 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002707
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002708 if (!bdaddr_type_is_valid(cp->addr.type))
2709 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2710 MGMT_STATUS_INVALID_PARAMS,
2711 &rp, sizeof(rp));
2712
Johan Hedberg118da702013-01-20 14:27:20 +02002713 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2714 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2715 MGMT_STATUS_INVALID_PARAMS,
2716 &rp, sizeof(rp));
2717
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002718 hci_dev_lock(hdev);
2719
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002720 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002721 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002722 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002723 goto unlock;
2724 }
2725
Johan Hedberge0b2b272014-02-18 17:14:31 +02002726 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002727 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002728 } else {
2729 u8 addr_type;
2730
2731 if (cp->addr.type == BDADDR_LE_PUBLIC)
2732 addr_type = ADDR_LE_DEV_PUBLIC;
2733 else
2734 addr_type = ADDR_LE_DEV_RANDOM;
2735
Johan Hedberga7ec7332014-02-18 17:14:35 +02002736 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2737
Andre Guedesa9b0a042014-02-26 20:21:52 -03002738 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2739
Johan Hedberge0b2b272014-02-18 17:14:31 +02002740 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2741 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002742
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002743 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002744 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002745 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002746 goto unlock;
2747 }
2748
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002749 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002750 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002751 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002752 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002753 else
2754 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002755 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002756 } else {
2757 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002758 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002759
Johan Hedberga8a1d192011-11-10 15:54:38 +02002760 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002761 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002762 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002763 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002764 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002765 }
2766
Johan Hedberg124f6e32012-02-09 13:50:12 +02002767 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002768 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002769 if (!cmd) {
2770 err = -ENOMEM;
2771 goto unlock;
2772 }
2773
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002774 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002775 dc.reason = 0x13; /* Remote User Terminated Connection */
2776 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2777 if (err < 0)
2778 mgmt_pending_remove(cmd);
2779
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002780unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002781 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002782 return err;
2783}
2784
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002785static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002786 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002787{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002788 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002789 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002790 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002791 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002792 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002793 int err;
2794
2795 BT_DBG("");
2796
Johan Hedberg06a63b12013-01-20 14:27:21 +02002797 memset(&rp, 0, sizeof(rp));
2798 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2799 rp.addr.type = cp->addr.type;
2800
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002801 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002802 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2803 MGMT_STATUS_INVALID_PARAMS,
2804 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002805
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002806 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002807
2808 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002809 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2810 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002811 goto failed;
2812 }
2813
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002814 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002815 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2816 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002817 goto failed;
2818 }
2819
Andre Guedes591f47f2012-04-24 21:02:49 -03002820 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002821 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2822 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002823 else
2824 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002825
Vishal Agarwalf9607272012-06-13 05:32:43 +05302826 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002827 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2828 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002829 goto failed;
2830 }
2831
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002832 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002833 if (!cmd) {
2834 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002835 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002836 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002837
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002838 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002839 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002840
2841 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2842 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002843 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002844
2845failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002846 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002847 return err;
2848}
2849
Andre Guedes57c14772012-04-24 21:02:50 -03002850static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002851{
2852 switch (link_type) {
2853 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002854 switch (addr_type) {
2855 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002856 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002857
Johan Hedberg48264f02011-11-09 13:58:58 +02002858 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002859 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002860 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002861 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002862
Johan Hedberg4c659c32011-11-07 23:13:39 +02002863 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002864 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002865 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002866 }
2867}
2868
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002869static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2870 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002871{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002872 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002873 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002874 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002875 int err;
2876 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002877
2878 BT_DBG("");
2879
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002880 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002881
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002882 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002883 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002884 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002885 goto unlock;
2886 }
2887
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002888 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002889 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2890 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002891 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002892 }
2893
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002894 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002895 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002896 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002897 err = -ENOMEM;
2898 goto unlock;
2899 }
2900
Johan Hedberg2784eb42011-01-21 13:56:35 +02002901 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002902 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002903 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2904 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002905 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002906 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002907 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002908 continue;
2909 i++;
2910 }
2911
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002912 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002913
Johan Hedberg4c659c32011-11-07 23:13:39 +02002914 /* Recalculate length in case of filtered SCO connections, etc */
2915 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002916
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002917 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002918 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002919
Johan Hedberga38528f2011-01-22 06:46:43 +02002920 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002921
2922unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002923 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002924 return err;
2925}
2926
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002927static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002928 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002929{
2930 struct pending_cmd *cmd;
2931 int err;
2932
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002933 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002934 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002935 if (!cmd)
2936 return -ENOMEM;
2937
Johan Hedbergd8457692012-02-17 14:24:57 +02002938 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002939 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002940 if (err < 0)
2941 mgmt_pending_remove(cmd);
2942
2943 return err;
2944}
2945
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002946static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002947 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002948{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002949 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002950 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002951 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002952 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002953 int err;
2954
2955 BT_DBG("");
2956
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002957 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002958
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002959 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002960 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002961 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002962 goto failed;
2963 }
2964
Johan Hedbergd8457692012-02-17 14:24:57 +02002965 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002966 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002967 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002968 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002969 goto failed;
2970 }
2971
2972 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002973 struct mgmt_cp_pin_code_neg_reply ncp;
2974
2975 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002976
2977 BT_ERR("PIN code is not 16 bytes long");
2978
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002979 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002980 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002981 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002983
2984 goto failed;
2985 }
2986
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002987 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002988 if (!cmd) {
2989 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002990 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002991 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002992
Johan Hedbergd8457692012-02-17 14:24:57 +02002993 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002994 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002995 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002996
2997 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2998 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002999 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003000
3001failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003002 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003003 return err;
3004}
3005
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003006static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3007 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003008{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003009 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003010
3011 BT_DBG("");
3012
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003013 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3014 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3015 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3016
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003017 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003018
3019 hdev->io_capability = cp->io_capability;
3020
3021 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003022 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003023
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003024 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003025
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003026 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3027 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003028}
3029
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003030static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003031{
3032 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003033 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003034
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003035 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003036 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3037 continue;
3038
Johan Hedberge9a416b2011-02-19 12:05:56 -03003039 if (cmd->user_data != conn)
3040 continue;
3041
3042 return cmd;
3043 }
3044
3045 return NULL;
3046}
3047
3048static void pairing_complete(struct pending_cmd *cmd, u8 status)
3049{
3050 struct mgmt_rp_pair_device rp;
3051 struct hci_conn *conn = cmd->user_data;
3052
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003053 bacpy(&rp.addr.bdaddr, &conn->dst);
3054 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003055
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003056 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003057 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003058
3059 /* So we don't get further callbacks for this connection */
3060 conn->connect_cfm_cb = NULL;
3061 conn->security_cfm_cb = NULL;
3062 conn->disconn_cfm_cb = NULL;
3063
David Herrmann76a68ba2013-04-06 20:28:37 +02003064 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003065
Johan Hedberga664b5b2011-02-19 12:06:02 -03003066 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003067}
3068
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003069void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3070{
3071 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3072 struct pending_cmd *cmd;
3073
3074 cmd = find_pairing(conn);
3075 if (cmd)
3076 pairing_complete(cmd, status);
3077}
3078
Johan Hedberge9a416b2011-02-19 12:05:56 -03003079static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3080{
3081 struct pending_cmd *cmd;
3082
3083 BT_DBG("status %u", status);
3084
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003085 cmd = find_pairing(conn);
3086 if (!cmd)
3087 BT_DBG("Unable to find a pending command");
3088 else
Johan Hedberge2113262012-02-18 15:20:03 +02003089 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003090}
3091
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003092static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303093{
3094 struct pending_cmd *cmd;
3095
3096 BT_DBG("status %u", status);
3097
3098 if (!status)
3099 return;
3100
3101 cmd = find_pairing(conn);
3102 if (!cmd)
3103 BT_DBG("Unable to find a pending command");
3104 else
3105 pairing_complete(cmd, mgmt_status(status));
3106}
3107
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003108static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003109 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003110{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003111 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003112 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003113 struct pending_cmd *cmd;
3114 u8 sec_level, auth_type;
3115 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003116 int err;
3117
3118 BT_DBG("");
3119
Szymon Jancf950a30e2013-01-18 12:48:07 +01003120 memset(&rp, 0, sizeof(rp));
3121 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3122 rp.addr.type = cp->addr.type;
3123
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003124 if (!bdaddr_type_is_valid(cp->addr.type))
3125 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3126 MGMT_STATUS_INVALID_PARAMS,
3127 &rp, sizeof(rp));
3128
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003129 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3130 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3131 MGMT_STATUS_INVALID_PARAMS,
3132 &rp, sizeof(rp));
3133
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003134 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003135
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003136 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003137 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3138 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003139 goto unlock;
3140 }
3141
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003142 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003143 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003144
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003145 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003146 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3147 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003148 } else {
3149 u8 addr_type;
3150
3151 /* Convert from L2CAP channel address type to HCI address type
3152 */
3153 if (cp->addr.type == BDADDR_LE_PUBLIC)
3154 addr_type = ADDR_LE_DEV_PUBLIC;
3155 else
3156 addr_type = ADDR_LE_DEV_RANDOM;
3157
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003158 /* When pairing a new device, it is expected to remember
3159 * this device for future connections. Adding the connection
3160 * parameter information ahead of time allows tracking
3161 * of the slave preferred values and will speed up any
3162 * further connection establishment.
3163 *
3164 * If connection parameters already exist, then they
3165 * will be kept and this function does nothing.
3166 */
3167 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3168
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003169 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003170 sec_level, HCI_LE_CONN_TIMEOUT,
3171 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003172 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003173
Ville Tervo30e76272011-02-22 16:10:53 -03003174 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003175 int status;
3176
3177 if (PTR_ERR(conn) == -EBUSY)
3178 status = MGMT_STATUS_BUSY;
3179 else
3180 status = MGMT_STATUS_CONNECT_FAILED;
3181
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003182 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003183 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003184 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003185 goto unlock;
3186 }
3187
3188 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003189 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003190 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003191 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003192 goto unlock;
3193 }
3194
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003195 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003196 if (!cmd) {
3197 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003198 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003199 goto unlock;
3200 }
3201
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003202 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003203 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003204 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003205 conn->security_cfm_cb = pairing_complete_cb;
3206 conn->disconn_cfm_cb = pairing_complete_cb;
3207 } else {
3208 conn->connect_cfm_cb = le_pairing_complete_cb;
3209 conn->security_cfm_cb = le_pairing_complete_cb;
3210 conn->disconn_cfm_cb = le_pairing_complete_cb;
3211 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003212
Johan Hedberge9a416b2011-02-19 12:05:56 -03003213 conn->io_capability = cp->io_cap;
3214 cmd->user_data = conn;
3215
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003216 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003217 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003218 pairing_complete(cmd, 0);
3219
3220 err = 0;
3221
3222unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003223 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003224 return err;
3225}
3226
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003227static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3228 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003229{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003230 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003231 struct pending_cmd *cmd;
3232 struct hci_conn *conn;
3233 int err;
3234
3235 BT_DBG("");
3236
Johan Hedberg28424702012-02-02 04:02:29 +02003237 hci_dev_lock(hdev);
3238
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003239 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003240 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003241 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003242 goto unlock;
3243 }
3244
Johan Hedberg28424702012-02-02 04:02:29 +02003245 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3246 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003247 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003248 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003249 goto unlock;
3250 }
3251
3252 conn = cmd->user_data;
3253
3254 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003255 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003256 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003257 goto unlock;
3258 }
3259
3260 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3261
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003262 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003263 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003264unlock:
3265 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003266 return err;
3267}
3268
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003269static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003270 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003271 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003272{
Johan Hedberga5c29682011-02-19 12:05:57 -03003273 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003274 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003275 int err;
3276
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003277 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003278
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003279 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003280 err = cmd_complete(sk, hdev->id, mgmt_op,
3281 MGMT_STATUS_NOT_POWERED, addr,
3282 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003283 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003284 }
3285
Johan Hedberg1707c602013-03-15 17:07:15 -05003286 if (addr->type == BDADDR_BREDR)
3287 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003288 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003289 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003290
Johan Hedberg272d90d2012-02-09 15:26:12 +02003291 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003292 err = cmd_complete(sk, hdev->id, mgmt_op,
3293 MGMT_STATUS_NOT_CONNECTED, addr,
3294 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003295 goto done;
3296 }
3297
Johan Hedberg1707c602013-03-15 17:07:15 -05003298 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003299 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003300 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003301 err = cmd_complete(sk, hdev->id, mgmt_op,
3302 MGMT_STATUS_SUCCESS, addr,
3303 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003304 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003305 err = cmd_complete(sk, hdev->id, mgmt_op,
3306 MGMT_STATUS_FAILED, addr,
3307 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003308
Brian Gix47c15e22011-11-16 13:53:14 -08003309 goto done;
3310 }
3311
Johan Hedberg1707c602013-03-15 17:07:15 -05003312 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003313 if (!cmd) {
3314 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003315 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003316 }
3317
Brian Gix0df4c182011-11-16 13:53:13 -08003318 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003319 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3320 struct hci_cp_user_passkey_reply cp;
3321
Johan Hedberg1707c602013-03-15 17:07:15 -05003322 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003323 cp.passkey = passkey;
3324 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3325 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003326 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3327 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003328
Johan Hedberga664b5b2011-02-19 12:06:02 -03003329 if (err < 0)
3330 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003331
Brian Gix0df4c182011-11-16 13:53:13 -08003332done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003333 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003334 return err;
3335}
3336
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303337static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3338 void *data, u16 len)
3339{
3340 struct mgmt_cp_pin_code_neg_reply *cp = data;
3341
3342 BT_DBG("");
3343
Johan Hedberg1707c602013-03-15 17:07:15 -05003344 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303345 MGMT_OP_PIN_CODE_NEG_REPLY,
3346 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3347}
3348
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003349static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3350 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003351{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003352 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003353
3354 BT_DBG("");
3355
3356 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003357 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003358 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003359
Johan Hedberg1707c602013-03-15 17:07:15 -05003360 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003361 MGMT_OP_USER_CONFIRM_REPLY,
3362 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003363}
3364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003365static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003366 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003367{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003368 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003369
3370 BT_DBG("");
3371
Johan Hedberg1707c602013-03-15 17:07:15 -05003372 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003373 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3374 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003375}
3376
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003377static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3378 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003379{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003380 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003381
3382 BT_DBG("");
3383
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_PASSKEY_REPLY,
3386 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003387}
3388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003389static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003390 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003391{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003392 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -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_PASSKEY_NEG_REPLY,
3398 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003399}
3400
Johan Hedberg13928972013-03-15 17:07:00 -05003401static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003402{
Johan Hedberg13928972013-03-15 17:07:00 -05003403 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003404 struct hci_cp_write_local_name cp;
3405
Johan Hedberg13928972013-03-15 17:07:00 -05003406 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003407
Johan Hedberg890ea892013-03-15 17:06:52 -05003408 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003409}
3410
Johan Hedberg13928972013-03-15 17:07:00 -05003411static void set_name_complete(struct hci_dev *hdev, u8 status)
3412{
3413 struct mgmt_cp_set_local_name *cp;
3414 struct pending_cmd *cmd;
3415
3416 BT_DBG("status 0x%02x", status);
3417
3418 hci_dev_lock(hdev);
3419
3420 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3421 if (!cmd)
3422 goto unlock;
3423
3424 cp = cmd->param;
3425
3426 if (status)
3427 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3428 mgmt_status(status));
3429 else
3430 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3431 cp, sizeof(*cp));
3432
3433 mgmt_pending_remove(cmd);
3434
3435unlock:
3436 hci_dev_unlock(hdev);
3437}
3438
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003439static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003440 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003441{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003442 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003443 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003444 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003445 int err;
3446
3447 BT_DBG("");
3448
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003449 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003450
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003451 /* If the old values are the same as the new ones just return a
3452 * direct command complete event.
3453 */
3454 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3455 !memcmp(hdev->short_name, cp->short_name,
3456 sizeof(hdev->short_name))) {
3457 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3458 data, len);
3459 goto failed;
3460 }
3461
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003462 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003463
Johan Hedbergb5235a62012-02-21 14:32:24 +02003464 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003465 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003466
3467 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003468 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003469 if (err < 0)
3470 goto failed;
3471
3472 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003473 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003474
Johan Hedbergb5235a62012-02-21 14:32:24 +02003475 goto failed;
3476 }
3477
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003478 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003479 if (!cmd) {
3480 err = -ENOMEM;
3481 goto failed;
3482 }
3483
Johan Hedberg13928972013-03-15 17:07:00 -05003484 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3485
Johan Hedberg890ea892013-03-15 17:06:52 -05003486 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003487
3488 if (lmp_bredr_capable(hdev)) {
3489 update_name(&req);
3490 update_eir(&req);
3491 }
3492
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003493 /* The name is stored in the scan response data and so
3494 * no need to udpate the advertising data here.
3495 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003496 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003497 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003498
Johan Hedberg13928972013-03-15 17:07:00 -05003499 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003500 if (err < 0)
3501 mgmt_pending_remove(cmd);
3502
3503failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003504 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003505 return err;
3506}
3507
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003508static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003509 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003510{
Szymon Jancc35938b2011-03-22 13:12:21 +01003511 struct pending_cmd *cmd;
3512 int err;
3513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003515
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003516 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003517
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003518 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003519 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003520 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003521 goto unlock;
3522 }
3523
Andre Guedes9a1a1992012-07-24 15:03:48 -03003524 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003525 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003526 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003527 goto unlock;
3528 }
3529
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003530 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003531 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003532 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003533 goto unlock;
3534 }
3535
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003536 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003537 if (!cmd) {
3538 err = -ENOMEM;
3539 goto unlock;
3540 }
3541
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003542 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3543 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3544 0, NULL);
3545 else
3546 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3547
Szymon Jancc35938b2011-03-22 13:12:21 +01003548 if (err < 0)
3549 mgmt_pending_remove(cmd);
3550
3551unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003552 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003553 return err;
3554}
3555
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003556static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003557 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003558{
Szymon Janc2763eda2011-03-22 13:12:22 +01003559 int err;
3560
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003561 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003562
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003563 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003564
Marcel Holtmannec109112014-01-10 02:07:30 -08003565 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3566 struct mgmt_cp_add_remote_oob_data *cp = data;
3567 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003568
Marcel Holtmannec109112014-01-10 02:07:30 -08003569 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3570 cp->hash, cp->randomizer);
3571 if (err < 0)
3572 status = MGMT_STATUS_FAILED;
3573 else
3574 status = MGMT_STATUS_SUCCESS;
3575
3576 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3577 status, &cp->addr, sizeof(cp->addr));
3578 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3579 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3580 u8 status;
3581
3582 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3583 cp->hash192,
3584 cp->randomizer192,
3585 cp->hash256,
3586 cp->randomizer256);
3587 if (err < 0)
3588 status = MGMT_STATUS_FAILED;
3589 else
3590 status = MGMT_STATUS_SUCCESS;
3591
3592 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3593 status, &cp->addr, sizeof(cp->addr));
3594 } else {
3595 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3596 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3597 MGMT_STATUS_INVALID_PARAMS);
3598 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003599
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003600 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003601 return err;
3602}
3603
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003604static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003605 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003606{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003607 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003608 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003609 int err;
3610
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003611 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003612
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003613 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003614
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003615 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003616 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003617 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003618 else
Szymon Janca6785be2012-12-13 15:11:21 +01003619 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003620
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003621 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003622 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003623
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003624 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003625 return err;
3626}
3627
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003628static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3629{
3630 struct pending_cmd *cmd;
3631 u8 type;
3632 int err;
3633
3634 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3635
3636 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3637 if (!cmd)
3638 return -ENOENT;
3639
3640 type = hdev->discovery.type;
3641
3642 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3643 &type, sizeof(type));
3644 mgmt_pending_remove(cmd);
3645
3646 return err;
3647}
3648
Andre Guedes7c307722013-04-30 15:29:28 -03003649static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3650{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003651 unsigned long timeout = 0;
3652
Andre Guedes7c307722013-04-30 15:29:28 -03003653 BT_DBG("status %d", status);
3654
3655 if (status) {
3656 hci_dev_lock(hdev);
3657 mgmt_start_discovery_failed(hdev, status);
3658 hci_dev_unlock(hdev);
3659 return;
3660 }
3661
3662 hci_dev_lock(hdev);
3663 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3664 hci_dev_unlock(hdev);
3665
3666 switch (hdev->discovery.type) {
3667 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003668 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003669 break;
3670
3671 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003672 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003673 break;
3674
3675 case DISCOV_TYPE_BREDR:
3676 break;
3677
3678 default:
3679 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3680 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003681
3682 if (!timeout)
3683 return;
3684
3685 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003686}
3687
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003688static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003689 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003690{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003691 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003692 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003693 struct hci_cp_le_set_scan_param param_cp;
3694 struct hci_cp_le_set_scan_enable enable_cp;
3695 struct hci_cp_inquiry inq_cp;
3696 struct hci_request req;
3697 /* General inquiry access code (GIAC) */
3698 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003699 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003700 int err;
3701
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003702 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003703
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003704 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003705
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003706 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003707 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003708 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003709 goto failed;
3710 }
3711
Andre Guedes642be6c2012-03-21 00:03:37 -03003712 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3713 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3714 MGMT_STATUS_BUSY);
3715 goto failed;
3716 }
3717
Johan Hedbergff9ef572012-01-04 14:23:45 +02003718 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003719 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003720 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003721 goto failed;
3722 }
3723
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003724 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003725 if (!cmd) {
3726 err = -ENOMEM;
3727 goto failed;
3728 }
3729
Andre Guedes4aab14e2012-02-17 20:39:36 -03003730 hdev->discovery.type = cp->type;
3731
Andre Guedes7c307722013-04-30 15:29:28 -03003732 hci_req_init(&req, hdev);
3733
Andre Guedes4aab14e2012-02-17 20:39:36 -03003734 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003735 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003736 status = mgmt_bredr_support(hdev);
3737 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003738 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003739 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003740 mgmt_pending_remove(cmd);
3741 goto failed;
3742 }
3743
Andre Guedes7c307722013-04-30 15:29:28 -03003744 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3745 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3746 MGMT_STATUS_BUSY);
3747 mgmt_pending_remove(cmd);
3748 goto failed;
3749 }
3750
3751 hci_inquiry_cache_flush(hdev);
3752
3753 memset(&inq_cp, 0, sizeof(inq_cp));
3754 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003755 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003756 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003757 break;
3758
3759 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003760 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003761 status = mgmt_le_support(hdev);
3762 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003763 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003764 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003765 mgmt_pending_remove(cmd);
3766 goto failed;
3767 }
3768
Andre Guedes7c307722013-04-30 15:29:28 -03003769 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003770 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003771 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3772 MGMT_STATUS_NOT_SUPPORTED);
3773 mgmt_pending_remove(cmd);
3774 goto failed;
3775 }
3776
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003777 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3778 /* Don't let discovery abort an outgoing
3779 * connection attempt that's using directed
3780 * advertising.
3781 */
3782 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3783 BT_CONNECT)) {
3784 err = cmd_status(sk, hdev->id,
3785 MGMT_OP_START_DISCOVERY,
3786 MGMT_STATUS_REJECTED);
3787 mgmt_pending_remove(cmd);
3788 goto failed;
3789 }
3790
3791 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003792 }
3793
Andre Guedesc54c3862014-02-26 20:21:50 -03003794 /* If controller is scanning, it means the background scanning
3795 * is running. Thus, we should temporarily stop it in order to
3796 * set the discovery scanning parameters.
3797 */
3798 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3799 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003800
3801 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003802
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003803 /* All active scans will be done with either a resolvable
3804 * private address (when privacy feature has been enabled)
3805 * or unresolvable private address.
3806 */
3807 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003808 if (err < 0) {
3809 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3810 MGMT_STATUS_FAILED);
3811 mgmt_pending_remove(cmd);
3812 goto failed;
3813 }
3814
Andre Guedes7c307722013-04-30 15:29:28 -03003815 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003816 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3817 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003818 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003819 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3820 &param_cp);
3821
3822 memset(&enable_cp, 0, sizeof(enable_cp));
3823 enable_cp.enable = LE_SCAN_ENABLE;
3824 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3825 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3826 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003827 break;
3828
Andre Guedesf39799f2012-02-17 20:39:35 -03003829 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003830 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3831 MGMT_STATUS_INVALID_PARAMS);
3832 mgmt_pending_remove(cmd);
3833 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003834 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003835
Andre Guedes7c307722013-04-30 15:29:28 -03003836 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003837 if (err < 0)
3838 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003839 else
3840 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003841
3842failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003843 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003844 return err;
3845}
3846
Andre Guedes1183fdc2013-04-30 15:29:35 -03003847static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3848{
3849 struct pending_cmd *cmd;
3850 int err;
3851
3852 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3853 if (!cmd)
3854 return -ENOENT;
3855
3856 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3857 &hdev->discovery.type, sizeof(hdev->discovery.type));
3858 mgmt_pending_remove(cmd);
3859
3860 return err;
3861}
3862
Andre Guedes0e05bba2013-04-30 15:29:33 -03003863static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3864{
3865 BT_DBG("status %d", status);
3866
3867 hci_dev_lock(hdev);
3868
3869 if (status) {
3870 mgmt_stop_discovery_failed(hdev, status);
3871 goto unlock;
3872 }
3873
3874 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3875
3876unlock:
3877 hci_dev_unlock(hdev);
3878}
3879
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003880static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003881 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003882{
Johan Hedbergd9306502012-02-20 23:25:18 +02003883 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003884 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003885 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003886 int err;
3887
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003888 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003889
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003890 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003891
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003892 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003893 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003894 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3895 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003896 goto unlock;
3897 }
3898
3899 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003900 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003901 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3902 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003903 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003904 }
3905
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003906 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003907 if (!cmd) {
3908 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003909 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003910 }
3911
Andre Guedes0e05bba2013-04-30 15:29:33 -03003912 hci_req_init(&req, hdev);
3913
Johan Hedberg21a60d32014-06-10 14:05:58 +03003914 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003915
Johan Hedberg21a60d32014-06-10 14:05:58 +03003916 err = hci_req_run(&req, stop_discovery_complete);
3917 if (!err) {
3918 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003919 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003920 }
3921
Johan Hedberg21a60d32014-06-10 14:05:58 +03003922 mgmt_pending_remove(cmd);
3923
3924 /* If no HCI commands were sent we're done */
3925 if (err == -ENODATA) {
3926 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3927 &mgmt_cp->type, sizeof(mgmt_cp->type));
3928 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3929 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003930
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003931unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003932 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003933 return err;
3934}
3935
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003936static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003937 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003938{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003939 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003940 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003941 int err;
3942
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003943 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003944
Johan Hedberg561aafb2012-01-04 13:31:59 +02003945 hci_dev_lock(hdev);
3946
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003947 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003948 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3949 MGMT_STATUS_FAILED, &cp->addr,
3950 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003951 goto failed;
3952 }
3953
Johan Hedberga198e7b2012-02-17 14:27:06 +02003954 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003955 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003956 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3957 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3958 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003959 goto failed;
3960 }
3961
3962 if (cp->name_known) {
3963 e->name_state = NAME_KNOWN;
3964 list_del(&e->list);
3965 } else {
3966 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003967 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003968 }
3969
Johan Hedberge3846622013-01-09 15:29:33 +02003970 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3971 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003972
3973failed:
3974 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003975 return err;
3976}
3977
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003978static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003979 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003980{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003981 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003982 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003983 int err;
3984
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003985 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003986
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003987 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003988 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3989 MGMT_STATUS_INVALID_PARAMS,
3990 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003991
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003992 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003993
Johan Hedbergdcc36c12014-07-09 12:59:13 +03003994 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
3995 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003996 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003997 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003998 goto done;
3999 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004000
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004001 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4002 sk);
4003 status = MGMT_STATUS_SUCCESS;
4004
4005done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004006 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004007 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004008
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004009 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004010
4011 return err;
4012}
4013
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004014static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004015 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004016{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004017 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004018 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004019 int err;
4020
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004021 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004022
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004023 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004024 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4025 MGMT_STATUS_INVALID_PARAMS,
4026 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004027
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004028 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004029
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004030 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4031 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004032 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004033 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004034 goto done;
4035 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004036
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004037 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4038 sk);
4039 status = MGMT_STATUS_SUCCESS;
4040
4041done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004042 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004043 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004044
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004045 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004046
4047 return err;
4048}
4049
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004050static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4051 u16 len)
4052{
4053 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004054 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004055 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004056 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004057
4058 BT_DBG("%s", hdev->name);
4059
Szymon Jancc72d4b82012-03-16 16:02:57 +01004060 source = __le16_to_cpu(cp->source);
4061
4062 if (source > 0x0002)
4063 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4064 MGMT_STATUS_INVALID_PARAMS);
4065
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004066 hci_dev_lock(hdev);
4067
Szymon Jancc72d4b82012-03-16 16:02:57 +01004068 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004069 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4070 hdev->devid_product = __le16_to_cpu(cp->product);
4071 hdev->devid_version = __le16_to_cpu(cp->version);
4072
4073 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4074
Johan Hedberg890ea892013-03-15 17:06:52 -05004075 hci_req_init(&req, hdev);
4076 update_eir(&req);
4077 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004078
4079 hci_dev_unlock(hdev);
4080
4081 return err;
4082}
4083
Johan Hedberg4375f102013-09-25 13:26:10 +03004084static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4085{
4086 struct cmd_lookup match = { NULL, hdev };
4087
4088 if (status) {
4089 u8 mgmt_err = mgmt_status(status);
4090
4091 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4092 cmd_status_rsp, &mgmt_err);
4093 return;
4094 }
4095
Johan Hedbergc93bd152014-07-08 15:07:48 +03004096 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4097 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4098 else
4099 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4100
Johan Hedberg4375f102013-09-25 13:26:10 +03004101 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4102 &match);
4103
4104 new_settings(hdev, match.sk);
4105
4106 if (match.sk)
4107 sock_put(match.sk);
4108}
4109
Marcel Holtmann21b51872013-10-10 09:47:53 -07004110static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4111 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004112{
4113 struct mgmt_mode *cp = data;
4114 struct pending_cmd *cmd;
4115 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004116 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004117 int err;
4118
4119 BT_DBG("request for %s", hdev->name);
4120
Johan Hedberge6fe7982013-10-02 15:45:22 +03004121 status = mgmt_le_support(hdev);
4122 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004123 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004124 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004125
4126 if (cp->val != 0x00 && cp->val != 0x01)
4127 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4128 MGMT_STATUS_INVALID_PARAMS);
4129
4130 hci_dev_lock(hdev);
4131
4132 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004133 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004134
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004135 /* The following conditions are ones which mean that we should
4136 * not do any HCI communication but directly send a mgmt
4137 * response to user space (after toggling the flag if
4138 * necessary).
4139 */
4140 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004141 hci_conn_num(hdev, LE_LINK) > 0 ||
4142 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4143 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004144 bool changed = false;
4145
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004146 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4147 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004148 changed = true;
4149 }
4150
4151 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4152 if (err < 0)
4153 goto unlock;
4154
4155 if (changed)
4156 err = new_settings(hdev, sk);
4157
4158 goto unlock;
4159 }
4160
4161 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4162 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4163 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4164 MGMT_STATUS_BUSY);
4165 goto unlock;
4166 }
4167
4168 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4169 if (!cmd) {
4170 err = -ENOMEM;
4171 goto unlock;
4172 }
4173
4174 hci_req_init(&req, hdev);
4175
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004176 if (val)
4177 enable_advertising(&req);
4178 else
4179 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004180
4181 err = hci_req_run(&req, set_advertising_complete);
4182 if (err < 0)
4183 mgmt_pending_remove(cmd);
4184
4185unlock:
4186 hci_dev_unlock(hdev);
4187 return err;
4188}
4189
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004190static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4191 void *data, u16 len)
4192{
4193 struct mgmt_cp_set_static_address *cp = data;
4194 int err;
4195
4196 BT_DBG("%s", hdev->name);
4197
Marcel Holtmann62af4442013-10-02 22:10:32 -07004198 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004199 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004200 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004201
4202 if (hdev_is_powered(hdev))
4203 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4204 MGMT_STATUS_REJECTED);
4205
4206 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4207 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4208 return cmd_status(sk, hdev->id,
4209 MGMT_OP_SET_STATIC_ADDRESS,
4210 MGMT_STATUS_INVALID_PARAMS);
4211
4212 /* Two most significant bits shall be set */
4213 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4214 return cmd_status(sk, hdev->id,
4215 MGMT_OP_SET_STATIC_ADDRESS,
4216 MGMT_STATUS_INVALID_PARAMS);
4217 }
4218
4219 hci_dev_lock(hdev);
4220
4221 bacpy(&hdev->static_addr, &cp->bdaddr);
4222
4223 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4224
4225 hci_dev_unlock(hdev);
4226
4227 return err;
4228}
4229
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004230static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4231 void *data, u16 len)
4232{
4233 struct mgmt_cp_set_scan_params *cp = data;
4234 __u16 interval, window;
4235 int err;
4236
4237 BT_DBG("%s", hdev->name);
4238
4239 if (!lmp_le_capable(hdev))
4240 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4241 MGMT_STATUS_NOT_SUPPORTED);
4242
4243 interval = __le16_to_cpu(cp->interval);
4244
4245 if (interval < 0x0004 || interval > 0x4000)
4246 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4247 MGMT_STATUS_INVALID_PARAMS);
4248
4249 window = __le16_to_cpu(cp->window);
4250
4251 if (window < 0x0004 || window > 0x4000)
4252 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4253 MGMT_STATUS_INVALID_PARAMS);
4254
Marcel Holtmann899e1072013-10-14 09:55:32 -07004255 if (window > interval)
4256 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4257 MGMT_STATUS_INVALID_PARAMS);
4258
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004259 hci_dev_lock(hdev);
4260
4261 hdev->le_scan_interval = interval;
4262 hdev->le_scan_window = window;
4263
4264 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4265
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004266 /* If background scan is running, restart it so new parameters are
4267 * loaded.
4268 */
4269 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4270 hdev->discovery.state == DISCOVERY_STOPPED) {
4271 struct hci_request req;
4272
4273 hci_req_init(&req, hdev);
4274
4275 hci_req_add_le_scan_disable(&req);
4276 hci_req_add_le_passive_scan(&req);
4277
4278 hci_req_run(&req, NULL);
4279 }
4280
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004281 hci_dev_unlock(hdev);
4282
4283 return err;
4284}
4285
Johan Hedberg33e38b32013-03-15 17:07:05 -05004286static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4287{
4288 struct pending_cmd *cmd;
4289
4290 BT_DBG("status 0x%02x", status);
4291
4292 hci_dev_lock(hdev);
4293
4294 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4295 if (!cmd)
4296 goto unlock;
4297
4298 if (status) {
4299 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4300 mgmt_status(status));
4301 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004302 struct mgmt_mode *cp = cmd->param;
4303
4304 if (cp->val)
4305 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4306 else
4307 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4308
Johan Hedberg33e38b32013-03-15 17:07:05 -05004309 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4310 new_settings(hdev, cmd->sk);
4311 }
4312
4313 mgmt_pending_remove(cmd);
4314
4315unlock:
4316 hci_dev_unlock(hdev);
4317}
4318
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004319static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004320 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004321{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004322 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004323 struct pending_cmd *cmd;
4324 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004325 int err;
4326
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004327 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004328
Johan Hedberg56f87902013-10-02 13:43:13 +03004329 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4330 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004331 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4332 MGMT_STATUS_NOT_SUPPORTED);
4333
Johan Hedberga7e80f22013-01-09 16:05:19 +02004334 if (cp->val != 0x00 && cp->val != 0x01)
4335 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4336 MGMT_STATUS_INVALID_PARAMS);
4337
Johan Hedberg5400c042012-02-21 16:40:33 +02004338 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004339 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004340 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004341
4342 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004343 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004344 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004345
4346 hci_dev_lock(hdev);
4347
Johan Hedberg05cbf292013-03-15 17:07:07 -05004348 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4349 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4350 MGMT_STATUS_BUSY);
4351 goto unlock;
4352 }
4353
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004354 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4355 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4356 hdev);
4357 goto unlock;
4358 }
4359
Johan Hedberg33e38b32013-03-15 17:07:05 -05004360 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4361 data, len);
4362 if (!cmd) {
4363 err = -ENOMEM;
4364 goto unlock;
4365 }
4366
4367 hci_req_init(&req, hdev);
4368
Johan Hedberg406d7802013-03-15 17:07:09 -05004369 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004370
4371 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004372 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004373 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004374 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004375 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004376 }
4377
Johan Hedberg33e38b32013-03-15 17:07:05 -05004378unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004379 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004380
Antti Julkuf6422ec2011-06-22 13:11:56 +03004381 return err;
4382}
4383
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004384static void set_bredr_scan(struct hci_request *req)
4385{
4386 struct hci_dev *hdev = req->hdev;
4387 u8 scan = 0;
4388
4389 /* Ensure that fast connectable is disabled. This function will
4390 * not do anything if the page scan parameters are already what
4391 * they should be.
4392 */
4393 write_fast_connectable(req, false);
4394
Johan Hedberg6cebb9e72014-07-09 12:59:18 +03004395 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
4396 !list_empty(&hdev->whitelist))
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004397 scan |= SCAN_PAGE;
4398 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4399 scan |= SCAN_INQUIRY;
4400
4401 if (scan)
4402 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4403}
4404
Johan Hedberg0663ca22013-10-02 13:43:14 +03004405static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4406{
4407 struct pending_cmd *cmd;
4408
4409 BT_DBG("status 0x%02x", status);
4410
4411 hci_dev_lock(hdev);
4412
4413 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4414 if (!cmd)
4415 goto unlock;
4416
4417 if (status) {
4418 u8 mgmt_err = mgmt_status(status);
4419
4420 /* We need to restore the flag if related HCI commands
4421 * failed.
4422 */
4423 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4424
4425 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4426 } else {
4427 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4428 new_settings(hdev, cmd->sk);
4429 }
4430
4431 mgmt_pending_remove(cmd);
4432
4433unlock:
4434 hci_dev_unlock(hdev);
4435}
4436
4437static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4438{
4439 struct mgmt_mode *cp = data;
4440 struct pending_cmd *cmd;
4441 struct hci_request req;
4442 int err;
4443
4444 BT_DBG("request for %s", hdev->name);
4445
4446 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4447 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4448 MGMT_STATUS_NOT_SUPPORTED);
4449
4450 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4451 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4452 MGMT_STATUS_REJECTED);
4453
4454 if (cp->val != 0x00 && cp->val != 0x01)
4455 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4456 MGMT_STATUS_INVALID_PARAMS);
4457
4458 hci_dev_lock(hdev);
4459
4460 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4461 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4462 goto unlock;
4463 }
4464
4465 if (!hdev_is_powered(hdev)) {
4466 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004467 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4468 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4469 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4470 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4471 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4472 }
4473
4474 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4475
4476 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4477 if (err < 0)
4478 goto unlock;
4479
4480 err = new_settings(hdev, sk);
4481 goto unlock;
4482 }
4483
4484 /* Reject disabling when powered on */
4485 if (!cp->val) {
4486 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4487 MGMT_STATUS_REJECTED);
4488 goto unlock;
4489 }
4490
4491 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4492 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4493 MGMT_STATUS_BUSY);
4494 goto unlock;
4495 }
4496
4497 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4498 if (!cmd) {
4499 err = -ENOMEM;
4500 goto unlock;
4501 }
4502
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004503 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004504 * generates the correct flags.
4505 */
4506 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4507
4508 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004509
Johan Hedberg6cebb9e72014-07-09 12:59:18 +03004510 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
4511 !list_empty(&hdev->whitelist))
Johan Hedbergaa8af462013-10-14 21:15:26 +03004512 set_bredr_scan(&req);
4513
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004514 /* Since only the advertising data flags will change, there
4515 * is no need to update the scan response data.
4516 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004517 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004518
Johan Hedberg0663ca22013-10-02 13:43:14 +03004519 err = hci_req_run(&req, set_bredr_complete);
4520 if (err < 0)
4521 mgmt_pending_remove(cmd);
4522
4523unlock:
4524 hci_dev_unlock(hdev);
4525 return err;
4526}
4527
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004528static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4529 void *data, u16 len)
4530{
4531 struct mgmt_mode *cp = data;
4532 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004533 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004534 int err;
4535
4536 BT_DBG("request for %s", hdev->name);
4537
4538 status = mgmt_bredr_support(hdev);
4539 if (status)
4540 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4541 status);
4542
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004543 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004544 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004545 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4546 MGMT_STATUS_NOT_SUPPORTED);
4547
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004548 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004549 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4550 MGMT_STATUS_INVALID_PARAMS);
4551
4552 hci_dev_lock(hdev);
4553
4554 if (!hdev_is_powered(hdev)) {
4555 bool changed;
4556
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004557 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004558 changed = !test_and_set_bit(HCI_SC_ENABLED,
4559 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004560 if (cp->val == 0x02)
4561 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4562 else
4563 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4564 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004565 changed = test_and_clear_bit(HCI_SC_ENABLED,
4566 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004567 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4568 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004569
4570 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4571 if (err < 0)
4572 goto failed;
4573
4574 if (changed)
4575 err = new_settings(hdev, sk);
4576
4577 goto failed;
4578 }
4579
4580 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4581 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4582 MGMT_STATUS_BUSY);
4583 goto failed;
4584 }
4585
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004586 val = !!cp->val;
4587
4588 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4589 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004590 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4591 goto failed;
4592 }
4593
4594 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4595 if (!cmd) {
4596 err = -ENOMEM;
4597 goto failed;
4598 }
4599
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004600 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004601 if (err < 0) {
4602 mgmt_pending_remove(cmd);
4603 goto failed;
4604 }
4605
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004606 if (cp->val == 0x02)
4607 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4608 else
4609 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4610
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004611failed:
4612 hci_dev_unlock(hdev);
4613 return err;
4614}
4615
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004616static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4617 void *data, u16 len)
4618{
4619 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004620 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004621 int err;
4622
4623 BT_DBG("request for %s", hdev->name);
4624
Johan Hedbergb97109792014-06-24 14:00:28 +03004625 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004626 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4627 MGMT_STATUS_INVALID_PARAMS);
4628
4629 hci_dev_lock(hdev);
4630
4631 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004632 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4633 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004634 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004635 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4636 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004637
Johan Hedbergb97109792014-06-24 14:00:28 +03004638 if (cp->val == 0x02)
4639 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4640 &hdev->dev_flags);
4641 else
4642 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4643 &hdev->dev_flags);
4644
4645 if (hdev_is_powered(hdev) && use_changed &&
4646 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4647 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4648 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4649 sizeof(mode), &mode);
4650 }
4651
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004652 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4653 if (err < 0)
4654 goto unlock;
4655
4656 if (changed)
4657 err = new_settings(hdev, sk);
4658
4659unlock:
4660 hci_dev_unlock(hdev);
4661 return err;
4662}
4663
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004664static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4665 u16 len)
4666{
4667 struct mgmt_cp_set_privacy *cp = cp_data;
4668 bool changed;
4669 int err;
4670
4671 BT_DBG("request for %s", hdev->name);
4672
4673 if (!lmp_le_capable(hdev))
4674 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4675 MGMT_STATUS_NOT_SUPPORTED);
4676
4677 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4678 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4679 MGMT_STATUS_INVALID_PARAMS);
4680
4681 if (hdev_is_powered(hdev))
4682 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4683 MGMT_STATUS_REJECTED);
4684
4685 hci_dev_lock(hdev);
4686
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004687 /* If user space supports this command it is also expected to
4688 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4689 */
4690 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4691
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004692 if (cp->privacy) {
4693 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4694 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4695 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4696 } else {
4697 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4698 memset(hdev->irk, 0, sizeof(hdev->irk));
4699 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4700 }
4701
4702 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4703 if (err < 0)
4704 goto unlock;
4705
4706 if (changed)
4707 err = new_settings(hdev, sk);
4708
4709unlock:
4710 hci_dev_unlock(hdev);
4711 return err;
4712}
4713
Johan Hedberg41edf162014-02-18 10:19:35 +02004714static bool irk_is_valid(struct mgmt_irk_info *irk)
4715{
4716 switch (irk->addr.type) {
4717 case BDADDR_LE_PUBLIC:
4718 return true;
4719
4720 case BDADDR_LE_RANDOM:
4721 /* Two most significant bits shall be set */
4722 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4723 return false;
4724 return true;
4725 }
4726
4727 return false;
4728}
4729
4730static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4731 u16 len)
4732{
4733 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004734 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4735 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004736 u16 irk_count, expected_len;
4737 int i, err;
4738
4739 BT_DBG("request for %s", hdev->name);
4740
4741 if (!lmp_le_capable(hdev))
4742 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4743 MGMT_STATUS_NOT_SUPPORTED);
4744
4745 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004746 if (irk_count > max_irk_count) {
4747 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4748 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4749 MGMT_STATUS_INVALID_PARAMS);
4750 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004751
4752 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4753 if (expected_len != len) {
4754 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004755 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004756 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4757 MGMT_STATUS_INVALID_PARAMS);
4758 }
4759
4760 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4761
4762 for (i = 0; i < irk_count; i++) {
4763 struct mgmt_irk_info *key = &cp->irks[i];
4764
4765 if (!irk_is_valid(key))
4766 return cmd_status(sk, hdev->id,
4767 MGMT_OP_LOAD_IRKS,
4768 MGMT_STATUS_INVALID_PARAMS);
4769 }
4770
4771 hci_dev_lock(hdev);
4772
4773 hci_smp_irks_clear(hdev);
4774
4775 for (i = 0; i < irk_count; i++) {
4776 struct mgmt_irk_info *irk = &cp->irks[i];
4777 u8 addr_type;
4778
4779 if (irk->addr.type == BDADDR_LE_PUBLIC)
4780 addr_type = ADDR_LE_DEV_PUBLIC;
4781 else
4782 addr_type = ADDR_LE_DEV_RANDOM;
4783
4784 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4785 BDADDR_ANY);
4786 }
4787
4788 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4789
4790 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4791
4792 hci_dev_unlock(hdev);
4793
4794 return err;
4795}
4796
Johan Hedberg3f706b72013-01-20 14:27:16 +02004797static bool ltk_is_valid(struct mgmt_ltk_info *key)
4798{
4799 if (key->master != 0x00 && key->master != 0x01)
4800 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004801
4802 switch (key->addr.type) {
4803 case BDADDR_LE_PUBLIC:
4804 return true;
4805
4806 case BDADDR_LE_RANDOM:
4807 /* Two most significant bits shall be set */
4808 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4809 return false;
4810 return true;
4811 }
4812
4813 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004814}
4815
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004816static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004817 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004818{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004819 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004820 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4821 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004822 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004823 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004824
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004825 BT_DBG("request for %s", hdev->name);
4826
4827 if (!lmp_le_capable(hdev))
4828 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4829 MGMT_STATUS_NOT_SUPPORTED);
4830
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004831 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004832 if (key_count > max_key_count) {
4833 BT_ERR("load_ltks: too big key_count value %u", key_count);
4834 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4835 MGMT_STATUS_INVALID_PARAMS);
4836 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004837
4838 expected_len = sizeof(*cp) + key_count *
4839 sizeof(struct mgmt_ltk_info);
4840 if (expected_len != len) {
4841 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004842 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004843 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004844 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004845 }
4846
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004847 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004848
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004849 for (i = 0; i < key_count; i++) {
4850 struct mgmt_ltk_info *key = &cp->keys[i];
4851
Johan Hedberg3f706b72013-01-20 14:27:16 +02004852 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004853 return cmd_status(sk, hdev->id,
4854 MGMT_OP_LOAD_LONG_TERM_KEYS,
4855 MGMT_STATUS_INVALID_PARAMS);
4856 }
4857
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004858 hci_dev_lock(hdev);
4859
4860 hci_smp_ltks_clear(hdev);
4861
4862 for (i = 0; i < key_count; i++) {
4863 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004864 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004865
4866 if (key->addr.type == BDADDR_LE_PUBLIC)
4867 addr_type = ADDR_LE_DEV_PUBLIC;
4868 else
4869 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004870
4871 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004872 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004873 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004874 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004875
Johan Hedberg61b43352014-05-29 19:36:53 +03004876 switch (key->type) {
4877 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004878 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004879 break;
4880 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004881 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004882 break;
4883 default:
4884 continue;
4885 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004886
Johan Hedberg35d70272014-02-19 14:57:47 +02004887 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004888 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004889 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004890 }
4891
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004892 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4893 NULL, 0);
4894
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004895 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004896
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004897 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004898}
4899
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004900struct cmd_conn_lookup {
4901 struct hci_conn *conn;
4902 bool valid_tx_power;
4903 u8 mgmt_status;
4904};
4905
4906static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4907{
4908 struct cmd_conn_lookup *match = data;
4909 struct mgmt_cp_get_conn_info *cp;
4910 struct mgmt_rp_get_conn_info rp;
4911 struct hci_conn *conn = cmd->user_data;
4912
4913 if (conn != match->conn)
4914 return;
4915
4916 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4917
4918 memset(&rp, 0, sizeof(rp));
4919 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4920 rp.addr.type = cp->addr.type;
4921
4922 if (!match->mgmt_status) {
4923 rp.rssi = conn->rssi;
4924
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004925 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004926 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004927 rp.max_tx_power = conn->max_tx_power;
4928 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004929 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004930 rp.max_tx_power = HCI_TX_POWER_INVALID;
4931 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004932 }
4933
4934 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4935 match->mgmt_status, &rp, sizeof(rp));
4936
4937 hci_conn_drop(conn);
4938
4939 mgmt_pending_remove(cmd);
4940}
4941
4942static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4943{
4944 struct hci_cp_read_rssi *cp;
4945 struct hci_conn *conn;
4946 struct cmd_conn_lookup match;
4947 u16 handle;
4948
4949 BT_DBG("status 0x%02x", status);
4950
4951 hci_dev_lock(hdev);
4952
4953 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004954 * otherwise we assume it's not valid. At the moment we assume that
4955 * either both or none of current and max values are valid to keep code
4956 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004957 */
4958 match.valid_tx_power = !status;
4959
4960 /* Commands sent in request are either Read RSSI or Read Transmit Power
4961 * Level so we check which one was last sent to retrieve connection
4962 * handle. Both commands have handle as first parameter so it's safe to
4963 * cast data on the same command struct.
4964 *
4965 * First command sent is always Read RSSI and we fail only if it fails.
4966 * In other case we simply override error to indicate success as we
4967 * already remembered if TX power value is actually valid.
4968 */
4969 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4970 if (!cp) {
4971 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4972 status = 0;
4973 }
4974
4975 if (!cp) {
4976 BT_ERR("invalid sent_cmd in response");
4977 goto unlock;
4978 }
4979
4980 handle = __le16_to_cpu(cp->handle);
4981 conn = hci_conn_hash_lookup_handle(hdev, handle);
4982 if (!conn) {
4983 BT_ERR("unknown handle (%d) in response", handle);
4984 goto unlock;
4985 }
4986
4987 match.conn = conn;
4988 match.mgmt_status = mgmt_status(status);
4989
4990 /* Cache refresh is complete, now reply for mgmt request for given
4991 * connection only.
4992 */
4993 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4994 get_conn_info_complete, &match);
4995
4996unlock:
4997 hci_dev_unlock(hdev);
4998}
4999
5000static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5001 u16 len)
5002{
5003 struct mgmt_cp_get_conn_info *cp = data;
5004 struct mgmt_rp_get_conn_info rp;
5005 struct hci_conn *conn;
5006 unsigned long conn_info_age;
5007 int err = 0;
5008
5009 BT_DBG("%s", hdev->name);
5010
5011 memset(&rp, 0, sizeof(rp));
5012 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5013 rp.addr.type = cp->addr.type;
5014
5015 if (!bdaddr_type_is_valid(cp->addr.type))
5016 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5017 MGMT_STATUS_INVALID_PARAMS,
5018 &rp, sizeof(rp));
5019
5020 hci_dev_lock(hdev);
5021
5022 if (!hdev_is_powered(hdev)) {
5023 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5024 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5025 goto unlock;
5026 }
5027
5028 if (cp->addr.type == BDADDR_BREDR)
5029 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5030 &cp->addr.bdaddr);
5031 else
5032 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5033
5034 if (!conn || conn->state != BT_CONNECTED) {
5035 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5036 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5037 goto unlock;
5038 }
5039
5040 /* To avoid client trying to guess when to poll again for information we
5041 * calculate conn info age as random value between min/max set in hdev.
5042 */
5043 conn_info_age = hdev->conn_info_min_age +
5044 prandom_u32_max(hdev->conn_info_max_age -
5045 hdev->conn_info_min_age);
5046
5047 /* Query controller to refresh cached values if they are too old or were
5048 * never read.
5049 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005050 if (time_after(jiffies, conn->conn_info_timestamp +
5051 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005052 !conn->conn_info_timestamp) {
5053 struct hci_request req;
5054 struct hci_cp_read_tx_power req_txp_cp;
5055 struct hci_cp_read_rssi req_rssi_cp;
5056 struct pending_cmd *cmd;
5057
5058 hci_req_init(&req, hdev);
5059 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5060 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5061 &req_rssi_cp);
5062
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005063 /* For LE links TX power does not change thus we don't need to
5064 * query for it once value is known.
5065 */
5066 if (!bdaddr_type_is_le(cp->addr.type) ||
5067 conn->tx_power == HCI_TX_POWER_INVALID) {
5068 req_txp_cp.handle = cpu_to_le16(conn->handle);
5069 req_txp_cp.type = 0x00;
5070 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5071 sizeof(req_txp_cp), &req_txp_cp);
5072 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005073
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005074 /* Max TX power needs to be read only once per connection */
5075 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5076 req_txp_cp.handle = cpu_to_le16(conn->handle);
5077 req_txp_cp.type = 0x01;
5078 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5079 sizeof(req_txp_cp), &req_txp_cp);
5080 }
5081
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005082 err = hci_req_run(&req, conn_info_refresh_complete);
5083 if (err < 0)
5084 goto unlock;
5085
5086 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5087 data, len);
5088 if (!cmd) {
5089 err = -ENOMEM;
5090 goto unlock;
5091 }
5092
5093 hci_conn_hold(conn);
5094 cmd->user_data = conn;
5095
5096 conn->conn_info_timestamp = jiffies;
5097 } else {
5098 /* Cache is valid, just reply with values cached in hci_conn */
5099 rp.rssi = conn->rssi;
5100 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005101 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005102
5103 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5104 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5105 }
5106
5107unlock:
5108 hci_dev_unlock(hdev);
5109 return err;
5110}
5111
Johan Hedberg95868422014-06-28 17:54:07 +03005112static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5113{
5114 struct mgmt_cp_get_clock_info *cp;
5115 struct mgmt_rp_get_clock_info rp;
5116 struct hci_cp_read_clock *hci_cp;
5117 struct pending_cmd *cmd;
5118 struct hci_conn *conn;
5119
5120 BT_DBG("%s status %u", hdev->name, status);
5121
5122 hci_dev_lock(hdev);
5123
5124 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5125 if (!hci_cp)
5126 goto unlock;
5127
5128 if (hci_cp->which) {
5129 u16 handle = __le16_to_cpu(hci_cp->handle);
5130 conn = hci_conn_hash_lookup_handle(hdev, handle);
5131 } else {
5132 conn = NULL;
5133 }
5134
5135 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5136 if (!cmd)
5137 goto unlock;
5138
5139 cp = cmd->param;
5140
5141 memset(&rp, 0, sizeof(rp));
5142 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5143
5144 if (status)
5145 goto send_rsp;
5146
5147 rp.local_clock = cpu_to_le32(hdev->clock);
5148
5149 if (conn) {
5150 rp.piconet_clock = cpu_to_le32(conn->clock);
5151 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5152 }
5153
5154send_rsp:
5155 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5156 &rp, sizeof(rp));
5157 mgmt_pending_remove(cmd);
5158 if (conn)
5159 hci_conn_drop(conn);
5160
5161unlock:
5162 hci_dev_unlock(hdev);
5163}
5164
5165static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5166 u16 len)
5167{
5168 struct mgmt_cp_get_clock_info *cp = data;
5169 struct mgmt_rp_get_clock_info rp;
5170 struct hci_cp_read_clock hci_cp;
5171 struct pending_cmd *cmd;
5172 struct hci_request req;
5173 struct hci_conn *conn;
5174 int err;
5175
5176 BT_DBG("%s", hdev->name);
5177
5178 memset(&rp, 0, sizeof(rp));
5179 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5180 rp.addr.type = cp->addr.type;
5181
5182 if (cp->addr.type != BDADDR_BREDR)
5183 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5184 MGMT_STATUS_INVALID_PARAMS,
5185 &rp, sizeof(rp));
5186
5187 hci_dev_lock(hdev);
5188
5189 if (!hdev_is_powered(hdev)) {
5190 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5191 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5192 goto unlock;
5193 }
5194
5195 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5196 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5197 &cp->addr.bdaddr);
5198 if (!conn || conn->state != BT_CONNECTED) {
5199 err = cmd_complete(sk, hdev->id,
5200 MGMT_OP_GET_CLOCK_INFO,
5201 MGMT_STATUS_NOT_CONNECTED,
5202 &rp, sizeof(rp));
5203 goto unlock;
5204 }
5205 } else {
5206 conn = NULL;
5207 }
5208
5209 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5210 if (!cmd) {
5211 err = -ENOMEM;
5212 goto unlock;
5213 }
5214
5215 hci_req_init(&req, hdev);
5216
5217 memset(&hci_cp, 0, sizeof(hci_cp));
5218 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5219
5220 if (conn) {
5221 hci_conn_hold(conn);
5222 cmd->user_data = conn;
5223
5224 hci_cp.handle = cpu_to_le16(conn->handle);
5225 hci_cp.which = 0x01; /* Piconet clock */
5226 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5227 }
5228
5229 err = hci_req_run(&req, get_clock_info_complete);
5230 if (err < 0)
5231 mgmt_pending_remove(cmd);
5232
5233unlock:
5234 hci_dev_unlock(hdev);
5235 return err;
5236}
5237
Johan Hedberga3974072014-07-09 12:59:15 +03005238/* Helper for Add/Remove Device commands */
5239static void update_page_scan(struct hci_dev *hdev, u8 scan)
5240{
5241 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5242 return;
5243
5244 if (!hdev_is_powered(hdev))
5245 return;
5246
5247 /* If HCI_CONNECTABLE is set then Add/Remove Device should not
5248 * make any changes to page scanning.
5249 */
5250 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
5251 return;
5252
5253 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
5254 scan |= SCAN_INQUIRY;
5255
5256 hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
5257}
5258
Marcel Holtmann8afef092014-06-29 22:28:34 +02005259static void device_added(struct sock *sk, struct hci_dev *hdev,
5260 bdaddr_t *bdaddr, u8 type, u8 action)
5261{
5262 struct mgmt_ev_device_added ev;
5263
5264 bacpy(&ev.addr.bdaddr, bdaddr);
5265 ev.addr.type = type;
5266 ev.action = action;
5267
5268 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5269}
5270
Marcel Holtmann2faade52014-06-29 19:44:03 +02005271static int add_device(struct sock *sk, struct hci_dev *hdev,
5272 void *data, u16 len)
5273{
5274 struct mgmt_cp_add_device *cp = data;
5275 u8 auto_conn, addr_type;
5276 int err;
5277
5278 BT_DBG("%s", hdev->name);
5279
Johan Hedberg66593582014-07-09 12:59:14 +03005280 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005281 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5282 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5283 MGMT_STATUS_INVALID_PARAMS,
5284 &cp->addr, sizeof(cp->addr));
5285
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005286 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005287 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5288 MGMT_STATUS_INVALID_PARAMS,
5289 &cp->addr, sizeof(cp->addr));
5290
5291 hci_dev_lock(hdev);
5292
Johan Hedberg66593582014-07-09 12:59:14 +03005293 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberga3974072014-07-09 12:59:15 +03005294 bool update_scan;
5295
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005296 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005297 if (cp->action != 0x01) {
5298 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5299 MGMT_STATUS_INVALID_PARAMS,
5300 &cp->addr, sizeof(cp->addr));
5301 goto unlock;
5302 }
5303
Johan Hedberga3974072014-07-09 12:59:15 +03005304 update_scan = list_empty(&hdev->whitelist);
5305
Johan Hedberg66593582014-07-09 12:59:14 +03005306 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5307 cp->addr.type);
5308 if (err)
5309 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005310
5311 if (update_scan)
5312 update_page_scan(hdev, SCAN_PAGE);
5313
Johan Hedberg66593582014-07-09 12:59:14 +03005314 goto added;
5315 }
5316
Marcel Holtmann2faade52014-06-29 19:44:03 +02005317 if (cp->addr.type == BDADDR_LE_PUBLIC)
5318 addr_type = ADDR_LE_DEV_PUBLIC;
5319 else
5320 addr_type = ADDR_LE_DEV_RANDOM;
5321
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005322 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005323 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005324 else if (cp->action == 0x01)
5325 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005326 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005327 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005328
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005329 /* If the connection parameters don't exist for this device,
5330 * they will be created and configured with defaults.
5331 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005332 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5333 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005334 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5335 MGMT_STATUS_FAILED,
5336 &cp->addr, sizeof(cp->addr));
5337 goto unlock;
5338 }
5339
Johan Hedberg66593582014-07-09 12:59:14 +03005340added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005341 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5342
Marcel Holtmann2faade52014-06-29 19:44:03 +02005343 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5344 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5345
5346unlock:
5347 hci_dev_unlock(hdev);
5348 return err;
5349}
5350
Marcel Holtmann8afef092014-06-29 22:28:34 +02005351static void device_removed(struct sock *sk, struct hci_dev *hdev,
5352 bdaddr_t *bdaddr, u8 type)
5353{
5354 struct mgmt_ev_device_removed ev;
5355
5356 bacpy(&ev.addr.bdaddr, bdaddr);
5357 ev.addr.type = type;
5358
5359 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5360}
5361
Marcel Holtmann2faade52014-06-29 19:44:03 +02005362static int remove_device(struct sock *sk, struct hci_dev *hdev,
5363 void *data, u16 len)
5364{
5365 struct mgmt_cp_remove_device *cp = data;
5366 int err;
5367
5368 BT_DBG("%s", hdev->name);
5369
5370 hci_dev_lock(hdev);
5371
5372 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005373 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005374 u8 addr_type;
5375
Johan Hedberg66593582014-07-09 12:59:14 +03005376 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005377 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5378 MGMT_STATUS_INVALID_PARAMS,
5379 &cp->addr, sizeof(cp->addr));
5380 goto unlock;
5381 }
5382
Johan Hedberg66593582014-07-09 12:59:14 +03005383 if (cp->addr.type == BDADDR_BREDR) {
5384 err = hci_bdaddr_list_del(&hdev->whitelist,
5385 &cp->addr.bdaddr,
5386 cp->addr.type);
5387 if (err) {
5388 err = cmd_complete(sk, hdev->id,
5389 MGMT_OP_REMOVE_DEVICE,
5390 MGMT_STATUS_INVALID_PARAMS,
5391 &cp->addr, sizeof(cp->addr));
5392 goto unlock;
5393 }
5394
Johan Hedberga3974072014-07-09 12:59:15 +03005395 if (list_empty(&hdev->whitelist))
5396 update_page_scan(hdev, SCAN_DISABLED);
5397
Johan Hedberg66593582014-07-09 12:59:14 +03005398 device_removed(sk, hdev, &cp->addr.bdaddr,
5399 cp->addr.type);
5400 goto complete;
5401 }
5402
Marcel Holtmann2faade52014-06-29 19:44:03 +02005403 if (cp->addr.type == BDADDR_LE_PUBLIC)
5404 addr_type = ADDR_LE_DEV_PUBLIC;
5405 else
5406 addr_type = ADDR_LE_DEV_RANDOM;
5407
Johan Hedbergc71593d2014-07-02 17:37:28 +03005408 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5409 addr_type);
5410 if (!params) {
5411 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5412 MGMT_STATUS_INVALID_PARAMS,
5413 &cp->addr, sizeof(cp->addr));
5414 goto unlock;
5415 }
5416
5417 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5418 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5419 MGMT_STATUS_INVALID_PARAMS,
5420 &cp->addr, sizeof(cp->addr));
5421 goto unlock;
5422 }
5423
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005424 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005425 list_del(&params->list);
5426 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005427 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005428
5429 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005430 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005431 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005432 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005433
Marcel Holtmann2faade52014-06-29 19:44:03 +02005434 if (cp->addr.type) {
5435 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5436 MGMT_STATUS_INVALID_PARAMS,
5437 &cp->addr, sizeof(cp->addr));
5438 goto unlock;
5439 }
5440
Johan Hedberg66593582014-07-09 12:59:14 +03005441 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5442 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5443 list_del(&b->list);
5444 kfree(b);
5445 }
5446
Johan Hedberga3974072014-07-09 12:59:15 +03005447 update_page_scan(hdev, SCAN_DISABLED);
5448
Johan Hedberg19de0822014-07-06 13:06:51 +03005449 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5450 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5451 continue;
5452 device_removed(sk, hdev, &p->addr, p->addr_type);
5453 list_del(&p->action);
5454 list_del(&p->list);
5455 kfree(p);
5456 }
5457
5458 BT_DBG("All LE connection parameters were removed");
5459
5460 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005461 }
5462
Johan Hedberg66593582014-07-09 12:59:14 +03005463complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005464 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5465 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5466
5467unlock:
5468 hci_dev_unlock(hdev);
5469 return err;
5470}
5471
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005472static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5473 u16 len)
5474{
5475 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005476 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5477 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005478 u16 param_count, expected_len;
5479 int i;
5480
5481 if (!lmp_le_capable(hdev))
5482 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5483 MGMT_STATUS_NOT_SUPPORTED);
5484
5485 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005486 if (param_count > max_param_count) {
5487 BT_ERR("load_conn_param: too big param_count value %u",
5488 param_count);
5489 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5490 MGMT_STATUS_INVALID_PARAMS);
5491 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005492
5493 expected_len = sizeof(*cp) + param_count *
5494 sizeof(struct mgmt_conn_param);
5495 if (expected_len != len) {
5496 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5497 expected_len, len);
5498 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5499 MGMT_STATUS_INVALID_PARAMS);
5500 }
5501
5502 BT_DBG("%s param_count %u", hdev->name, param_count);
5503
5504 hci_dev_lock(hdev);
5505
5506 hci_conn_params_clear_disabled(hdev);
5507
5508 for (i = 0; i < param_count; i++) {
5509 struct mgmt_conn_param *param = &cp->params[i];
5510 struct hci_conn_params *hci_param;
5511 u16 min, max, latency, timeout;
5512 u8 addr_type;
5513
5514 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5515 param->addr.type);
5516
5517 if (param->addr.type == BDADDR_LE_PUBLIC) {
5518 addr_type = ADDR_LE_DEV_PUBLIC;
5519 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5520 addr_type = ADDR_LE_DEV_RANDOM;
5521 } else {
5522 BT_ERR("Ignoring invalid connection parameters");
5523 continue;
5524 }
5525
5526 min = le16_to_cpu(param->min_interval);
5527 max = le16_to_cpu(param->max_interval);
5528 latency = le16_to_cpu(param->latency);
5529 timeout = le16_to_cpu(param->timeout);
5530
5531 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5532 min, max, latency, timeout);
5533
5534 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5535 BT_ERR("Ignoring invalid connection parameters");
5536 continue;
5537 }
5538
5539 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5540 addr_type);
5541 if (!hci_param) {
5542 BT_ERR("Failed to add connection parameters");
5543 continue;
5544 }
5545
5546 hci_param->conn_min_interval = min;
5547 hci_param->conn_max_interval = max;
5548 hci_param->conn_latency = latency;
5549 hci_param->supervision_timeout = timeout;
5550 }
5551
5552 hci_dev_unlock(hdev);
5553
5554 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5555}
5556
Marcel Holtmanndbece372014-07-04 18:11:55 +02005557static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5558 void *data, u16 len)
5559{
5560 struct mgmt_cp_set_external_config *cp = data;
5561 bool changed;
5562 int err;
5563
5564 BT_DBG("%s", hdev->name);
5565
5566 if (hdev_is_powered(hdev))
5567 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5568 MGMT_STATUS_REJECTED);
5569
5570 if (cp->config != 0x00 && cp->config != 0x01)
5571 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5572 MGMT_STATUS_INVALID_PARAMS);
5573
5574 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5575 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5576 MGMT_STATUS_NOT_SUPPORTED);
5577
5578 hci_dev_lock(hdev);
5579
5580 if (cp->config)
5581 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5582 &hdev->dev_flags);
5583 else
5584 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5585 &hdev->dev_flags);
5586
5587 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5588 if (err < 0)
5589 goto unlock;
5590
5591 if (!changed)
5592 goto unlock;
5593
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005594 err = new_options(hdev, sk);
5595
Marcel Holtmanndbece372014-07-04 18:11:55 +02005596 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5597 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005598
5599 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5600 set_bit(HCI_CONFIG, &hdev->dev_flags);
5601 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5602
5603 queue_work(hdev->req_workqueue, &hdev->power_on);
5604 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005605 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005606 mgmt_index_added(hdev);
5607 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005608 }
5609
5610unlock:
5611 hci_dev_unlock(hdev);
5612 return err;
5613}
5614
Marcel Holtmann9713c172014-07-06 12:11:15 +02005615static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5616 void *data, u16 len)
5617{
5618 struct mgmt_cp_set_public_address *cp = data;
5619 bool changed;
5620 int err;
5621
5622 BT_DBG("%s", hdev->name);
5623
5624 if (hdev_is_powered(hdev))
5625 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5626 MGMT_STATUS_REJECTED);
5627
5628 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5629 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5630 MGMT_STATUS_INVALID_PARAMS);
5631
5632 if (!hdev->set_bdaddr)
5633 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5634 MGMT_STATUS_NOT_SUPPORTED);
5635
5636 hci_dev_lock(hdev);
5637
5638 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5639 bacpy(&hdev->public_addr, &cp->bdaddr);
5640
5641 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5642 if (err < 0)
5643 goto unlock;
5644
5645 if (!changed)
5646 goto unlock;
5647
5648 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5649 err = new_options(hdev, sk);
5650
5651 if (is_configured(hdev)) {
5652 mgmt_index_removed(hdev);
5653
5654 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5655
5656 set_bit(HCI_CONFIG, &hdev->dev_flags);
5657 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5658
5659 queue_work(hdev->req_workqueue, &hdev->power_on);
5660 }
5661
5662unlock:
5663 hci_dev_unlock(hdev);
5664 return err;
5665}
5666
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005667static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005668 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5669 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005670 bool var_len;
5671 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005672} mgmt_handlers[] = {
5673 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005674 { read_version, false, MGMT_READ_VERSION_SIZE },
5675 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5676 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5677 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5678 { set_powered, false, MGMT_SETTING_SIZE },
5679 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5680 { set_connectable, false, MGMT_SETTING_SIZE },
5681 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005682 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005683 { set_link_security, false, MGMT_SETTING_SIZE },
5684 { set_ssp, false, MGMT_SETTING_SIZE },
5685 { set_hs, false, MGMT_SETTING_SIZE },
5686 { set_le, false, MGMT_SETTING_SIZE },
5687 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5688 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5689 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5690 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5691 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5692 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5693 { disconnect, false, MGMT_DISCONNECT_SIZE },
5694 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5695 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5696 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5697 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5698 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5699 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5700 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5701 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5702 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5703 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5704 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5705 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005706 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005707 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5708 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5709 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5710 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5711 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5712 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005713 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005714 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005715 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005716 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005717 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005718 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005719 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005720 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005721 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005722 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005723 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005724 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5725 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005726 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5727 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005728 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005729 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005730 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005731};
5732
Johan Hedberg03811012010-12-08 00:21:06 +02005733int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5734{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005735 void *buf;
5736 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005737 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005738 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005739 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005740 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005741 int err;
5742
5743 BT_DBG("got %zu bytes", msglen);
5744
5745 if (msglen < sizeof(*hdr))
5746 return -EINVAL;
5747
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005748 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005749 if (!buf)
5750 return -ENOMEM;
5751
5752 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5753 err = -EFAULT;
5754 goto done;
5755 }
5756
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005757 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005758 opcode = __le16_to_cpu(hdr->opcode);
5759 index = __le16_to_cpu(hdr->index);
5760 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005761
5762 if (len != msglen - sizeof(*hdr)) {
5763 err = -EINVAL;
5764 goto done;
5765 }
5766
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005767 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005768 hdev = hci_dev_get(index);
5769 if (!hdev) {
5770 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005771 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005772 goto done;
5773 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005774
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005775 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005776 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005777 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005778 err = cmd_status(sk, index, opcode,
5779 MGMT_STATUS_INVALID_INDEX);
5780 goto done;
5781 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005782
5783 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005784 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005785 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5786 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005787 err = cmd_status(sk, index, opcode,
5788 MGMT_STATUS_INVALID_INDEX);
5789 goto done;
5790 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005791 }
5792
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005793 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005794 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005795 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005796 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005797 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005798 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005799 }
5800
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005801 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5802 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5803 err = cmd_status(sk, index, opcode,
5804 MGMT_STATUS_INVALID_INDEX);
5805 goto done;
5806 }
5807
5808 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5809 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005810 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005811 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005812 goto done;
5813 }
5814
Johan Hedbergbe22b542012-03-01 22:24:41 +02005815 handler = &mgmt_handlers[opcode];
5816
5817 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005818 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005819 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005820 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005821 goto done;
5822 }
5823
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005824 if (hdev)
5825 mgmt_init_hdev(sk, hdev);
5826
5827 cp = buf + sizeof(*hdr);
5828
Johan Hedbergbe22b542012-03-01 22:24:41 +02005829 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005830 if (err < 0)
5831 goto done;
5832
Johan Hedberg03811012010-12-08 00:21:06 +02005833 err = msglen;
5834
5835done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005836 if (hdev)
5837 hci_dev_put(hdev);
5838
Johan Hedberg03811012010-12-08 00:21:06 +02005839 kfree(buf);
5840 return err;
5841}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005842
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005843void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005844{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005845 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005846 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005847
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005848 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5849 return;
5850
5851 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5852 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5853 else
5854 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005855}
5856
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005857void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005858{
Johan Hedberg5f159032012-03-02 03:13:19 +02005859 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005860
Marcel Holtmann1514b892013-10-06 08:25:01 -07005861 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005862 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005863
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005864 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5865 return;
5866
Johan Hedberg744cf192011-11-08 20:40:14 +02005867 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005868
Marcel Holtmannedd38962014-07-02 21:30:55 +02005869 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5870 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5871 else
5872 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005873}
5874
Andre Guedes6046dc32014-02-26 20:21:51 -03005875/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005876static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005877{
5878 struct hci_conn_params *p;
5879
5880 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005881 /* Needed for AUTO_OFF case where might not "really"
5882 * have been powered off.
5883 */
5884 list_del_init(&p->action);
5885
5886 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005887 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03005888 case HCI_AUTO_CONN_ALWAYS:
5889 list_add(&p->action, &hdev->pend_le_conns);
5890 break;
5891 case HCI_AUTO_CONN_REPORT:
5892 list_add(&p->action, &hdev->pend_le_reports);
5893 break;
5894 default:
5895 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005896 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005897 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005898
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005899 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005900}
5901
Johan Hedberg229ab392013-03-15 17:06:53 -05005902static void powered_complete(struct hci_dev *hdev, u8 status)
5903{
5904 struct cmd_lookup match = { NULL, hdev };
5905
5906 BT_DBG("status 0x%02x", status);
5907
5908 hci_dev_lock(hdev);
5909
Johan Hedbergd7347f32014-07-04 12:37:23 +03005910 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005911
Johan Hedberg229ab392013-03-15 17:06:53 -05005912 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5913
5914 new_settings(hdev, match.sk);
5915
5916 hci_dev_unlock(hdev);
5917
5918 if (match.sk)
5919 sock_put(match.sk);
5920}
5921
Johan Hedberg70da6242013-03-15 17:06:51 -05005922static int powered_update_hci(struct hci_dev *hdev)
5923{
Johan Hedberg890ea892013-03-15 17:06:52 -05005924 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005925 u8 link_sec;
5926
Johan Hedberg890ea892013-03-15 17:06:52 -05005927 hci_req_init(&req, hdev);
5928
Johan Hedberg70da6242013-03-15 17:06:51 -05005929 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5930 !lmp_host_ssp_capable(hdev)) {
5931 u8 ssp = 1;
5932
Johan Hedberg890ea892013-03-15 17:06:52 -05005933 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005934 }
5935
Johan Hedbergc73eee92013-04-19 18:35:21 +03005936 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5937 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005938 struct hci_cp_write_le_host_supported cp;
5939
Marcel Holtmann32226e42014-07-24 20:04:16 +02005940 cp.le = 0x01;
5941 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05005942
5943 /* Check first if we already have the right
5944 * host state (host features set)
5945 */
5946 if (cp.le != lmp_host_le_capable(hdev) ||
5947 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005948 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5949 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005950 }
5951
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005952 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005953 /* Make sure the controller has a good default for
5954 * advertising data. This also applies to the case
5955 * where BR/EDR was toggled during the AUTO_OFF phase.
5956 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005957 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005958 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005959 update_scan_rsp_data(&req);
5960 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005961
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005962 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5963 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005964 }
5965
Johan Hedberg70da6242013-03-15 17:06:51 -05005966 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5967 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005968 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5969 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005970
5971 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005972 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5973 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005974 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005975 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005976 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005977 }
5978
Johan Hedberg229ab392013-03-15 17:06:53 -05005979 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005980}
5981
Johan Hedberg744cf192011-11-08 20:40:14 +02005982int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005983{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005984 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005985 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5986 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005987 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005988
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005989 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5990 return 0;
5991
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005992 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005993 if (powered_update_hci(hdev) == 0)
5994 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005995
Johan Hedberg229ab392013-03-15 17:06:53 -05005996 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5997 &match);
5998 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005999 }
6000
Johan Hedberg229ab392013-03-15 17:06:53 -05006001 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6002 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
6003
6004 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6005 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6006 zero_cod, sizeof(zero_cod), NULL);
6007
6008new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006009 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006010
6011 if (match.sk)
6012 sock_put(match.sk);
6013
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006014 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006015}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006016
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006017void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006018{
6019 struct pending_cmd *cmd;
6020 u8 status;
6021
6022 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6023 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006024 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006025
6026 if (err == -ERFKILL)
6027 status = MGMT_STATUS_RFKILLED;
6028 else
6029 status = MGMT_STATUS_FAILED;
6030
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006031 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006032
6033 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006034}
6035
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006036void mgmt_discoverable_timeout(struct hci_dev *hdev)
6037{
6038 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006039
6040 hci_dev_lock(hdev);
6041
6042 /* When discoverable timeout triggers, then just make sure
6043 * the limited discoverable flag is cleared. Even in the case
6044 * of a timeout triggered from general discoverable, it is
6045 * safe to unconditionally clear the flag.
6046 */
6047 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006048 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006049
6050 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006051 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6052 u8 scan = SCAN_PAGE;
6053 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6054 sizeof(scan), &scan);
6055 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006056 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006057 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006058 hci_req_run(&req, NULL);
6059
6060 hdev->discov_timeout = 0;
6061
Johan Hedberg9a43e252013-10-20 19:00:07 +03006062 new_settings(hdev, NULL);
6063
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006064 hci_dev_unlock(hdev);
6065}
6066
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006067void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6068 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006069{
Johan Hedberg86742e12011-11-07 23:13:38 +02006070 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006071
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006072 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006073
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006074 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006075 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006076 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006077 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006078 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006079 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006080
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006081 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006082}
Johan Hedbergf7520542011-01-20 12:34:39 +02006083
Johan Hedbergd7b25452014-05-23 13:19:53 +03006084static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6085{
6086 if (ltk->authenticated)
6087 return MGMT_LTK_AUTHENTICATED;
6088
6089 return MGMT_LTK_UNAUTHENTICATED;
6090}
6091
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006092void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006093{
6094 struct mgmt_ev_new_long_term_key ev;
6095
6096 memset(&ev, 0, sizeof(ev));
6097
Marcel Holtmann5192d302014-02-19 17:11:58 -08006098 /* Devices using resolvable or non-resolvable random addresses
6099 * without providing an indentity resolving key don't require
6100 * to store long term keys. Their addresses will change the
6101 * next time around.
6102 *
6103 * Only when a remote device provides an identity address
6104 * make sure the long term key is stored. If the remote
6105 * identity is known, the long term keys are internally
6106 * mapped to the identity address. So allow static random
6107 * and public addresses here.
6108 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006109 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6110 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6111 ev.store_hint = 0x00;
6112 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006113 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006114
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006115 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006116 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006117 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006118 ev.key.enc_size = key->enc_size;
6119 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006120 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006121
Johan Hedberg2ceba532014-06-16 19:25:16 +03006122 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006123 ev.key.master = 1;
6124
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006125 memcpy(ev.key.val, key->val, sizeof(key->val));
6126
Marcel Holtmann083368f2013-10-15 14:26:29 -07006127 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006128}
6129
Johan Hedberg95fbac82014-02-19 15:18:31 +02006130void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6131{
6132 struct mgmt_ev_new_irk ev;
6133
6134 memset(&ev, 0, sizeof(ev));
6135
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006136 /* For identity resolving keys from devices that are already
6137 * using a public address or static random address, do not
6138 * ask for storing this key. The identity resolving key really
6139 * is only mandatory for devices using resovlable random
6140 * addresses.
6141 *
6142 * Storing all identity resolving keys has the downside that
6143 * they will be also loaded on next boot of they system. More
6144 * identity resolving keys, means more time during scanning is
6145 * needed to actually resolve these addresses.
6146 */
6147 if (bacmp(&irk->rpa, BDADDR_ANY))
6148 ev.store_hint = 0x01;
6149 else
6150 ev.store_hint = 0x00;
6151
Johan Hedberg95fbac82014-02-19 15:18:31 +02006152 bacpy(&ev.rpa, &irk->rpa);
6153 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6154 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6155 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6156
6157 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6158}
6159
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006160void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6161 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006162{
6163 struct mgmt_ev_new_csrk ev;
6164
6165 memset(&ev, 0, sizeof(ev));
6166
6167 /* Devices using resolvable or non-resolvable random addresses
6168 * without providing an indentity resolving key don't require
6169 * to store signature resolving keys. Their addresses will change
6170 * the next time around.
6171 *
6172 * Only when a remote device provides an identity address
6173 * make sure the signature resolving key is stored. So allow
6174 * static random and public addresses here.
6175 */
6176 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6177 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6178 ev.store_hint = 0x00;
6179 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006180 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006181
6182 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6183 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6184 ev.key.master = csrk->master;
6185 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6186
6187 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6188}
6189
Andre Guedesffb5a8272014-07-01 18:10:11 -03006190void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006191 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6192 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006193{
6194 struct mgmt_ev_new_conn_param ev;
6195
Johan Hedbergc103aea2014-07-02 17:37:34 +03006196 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6197 return;
6198
Andre Guedesffb5a8272014-07-01 18:10:11 -03006199 memset(&ev, 0, sizeof(ev));
6200 bacpy(&ev.addr.bdaddr, bdaddr);
6201 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006202 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006203 ev.min_interval = cpu_to_le16(min_interval);
6204 ev.max_interval = cpu_to_le16(max_interval);
6205 ev.latency = cpu_to_le16(latency);
6206 ev.timeout = cpu_to_le16(timeout);
6207
6208 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6209}
6210
Marcel Holtmann94933992013-10-15 10:26:39 -07006211static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6212 u8 data_len)
6213{
6214 eir[eir_len++] = sizeof(type) + data_len;
6215 eir[eir_len++] = type;
6216 memcpy(&eir[eir_len], data, data_len);
6217 eir_len += data_len;
6218
6219 return eir_len;
6220}
6221
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006222void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6223 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6224 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006225{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006226 char buf[512];
6227 struct mgmt_ev_device_connected *ev = (void *) buf;
6228 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006229
Johan Hedbergb644ba32012-01-17 21:48:47 +02006230 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006231 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006232
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006233 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006234
Johan Hedbergb644ba32012-01-17 21:48:47 +02006235 if (name_len > 0)
6236 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006237 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006238
6239 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006240 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006241 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006242
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006243 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006244
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006245 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6246 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006247}
6248
Johan Hedberg8962ee72011-01-20 12:40:27 +02006249static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6250{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006251 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006252 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006253 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006254
Johan Hedberg88c3df12012-02-09 14:27:38 +02006255 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6256 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006257
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006258 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006259 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006260
6261 *sk = cmd->sk;
6262 sock_hold(*sk);
6263
Johan Hedberga664b5b2011-02-19 12:06:02 -03006264 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006265}
6266
Johan Hedberg124f6e32012-02-09 13:50:12 +02006267static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006268{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006269 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006270 struct mgmt_cp_unpair_device *cp = cmd->param;
6271 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006272
6273 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006274 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6275 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006276
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006277 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6278
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006279 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006280
6281 mgmt_pending_remove(cmd);
6282}
6283
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006284void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006285 u8 link_type, u8 addr_type, u8 reason,
6286 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006287{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006288 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006289 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006290 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006291
Johan Hedberg8b064a32014-02-24 14:52:22 +02006292 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6293 if (power_off) {
6294 struct mgmt_mode *cp = power_off->param;
6295
6296 /* The connection is still in hci_conn_hash so test for 1
6297 * instead of 0 to know if this is the last one.
6298 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006299 if (!cp->val && hci_conn_count(hdev) == 1) {
6300 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006301 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006302 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006303 }
6304
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006305 if (!mgmt_connected)
6306 return;
6307
Andre Guedes57eb7762013-10-30 19:01:41 -03006308 if (link_type != ACL_LINK && link_type != LE_LINK)
6309 return;
6310
Johan Hedberg744cf192011-11-08 20:40:14 +02006311 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006312
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006313 bacpy(&ev.addr.bdaddr, bdaddr);
6314 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6315 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006316
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006317 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006318
6319 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006320 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006321
Johan Hedberg124f6e32012-02-09 13:50:12 +02006322 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006323 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006324}
6325
Marcel Holtmann78929242013-10-06 23:55:47 -07006326void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6327 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006328{
Andre Guedes3655bba2013-10-30 19:01:40 -03006329 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6330 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006331 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006332 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006333
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006334 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6335 hdev);
6336
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006337 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006338 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006339 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006340
Andre Guedes3655bba2013-10-30 19:01:40 -03006341 cp = cmd->param;
6342
6343 if (bacmp(bdaddr, &cp->addr.bdaddr))
6344 return;
6345
6346 if (cp->addr.type != bdaddr_type)
6347 return;
6348
Johan Hedberg88c3df12012-02-09 14:27:38 +02006349 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006350 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006351
Marcel Holtmann78929242013-10-06 23:55:47 -07006352 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6353 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006354
Johan Hedberga664b5b2011-02-19 12:06:02 -03006355 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006356}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006357
Marcel Holtmann445608d2013-10-06 23:55:48 -07006358void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6359 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006360{
6361 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006362 struct pending_cmd *power_off;
6363
6364 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6365 if (power_off) {
6366 struct mgmt_mode *cp = power_off->param;
6367
6368 /* The connection is still in hci_conn_hash so test for 1
6369 * instead of 0 to know if this is the last one.
6370 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006371 if (!cp->val && hci_conn_count(hdev) == 1) {
6372 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006373 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006374 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006375 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006376
Johan Hedberg4c659c32011-11-07 23:13:39 +02006377 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006378 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006379 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006380
Marcel Holtmann445608d2013-10-06 23:55:48 -07006381 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006382}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006383
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006384void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006385{
6386 struct mgmt_ev_pin_code_request ev;
6387
Johan Hedbergd8457692012-02-17 14:24:57 +02006388 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006389 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006390 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006391
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006392 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006393}
6394
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006395void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6396 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006397{
6398 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006399 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006400
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006401 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006402 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006403 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006404
Johan Hedbergd8457692012-02-17 14:24:57 +02006405 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006406 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006407
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006408 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6409 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006410
Johan Hedberga664b5b2011-02-19 12:06:02 -03006411 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006412}
6413
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006414void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6415 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006416{
6417 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006418 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006419
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006420 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006421 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006422 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006423
Johan Hedbergd8457692012-02-17 14:24:57 +02006424 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006425 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006426
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006427 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6428 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006429
Johan Hedberga664b5b2011-02-19 12:06:02 -03006430 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006431}
Johan Hedberga5c29682011-02-19 12:05:57 -03006432
Johan Hedberg744cf192011-11-08 20:40:14 +02006433int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006434 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006435 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006436{
6437 struct mgmt_ev_user_confirm_request ev;
6438
Johan Hedberg744cf192011-11-08 20:40:14 +02006439 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006440
Johan Hedberg272d90d2012-02-09 15:26:12 +02006441 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006442 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006443 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006444 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006445
Johan Hedberg744cf192011-11-08 20:40:14 +02006446 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006447 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006448}
6449
Johan Hedberg272d90d2012-02-09 15:26:12 +02006450int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006451 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006452{
6453 struct mgmt_ev_user_passkey_request ev;
6454
6455 BT_DBG("%s", hdev->name);
6456
Johan Hedberg272d90d2012-02-09 15:26:12 +02006457 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006458 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006459
6460 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006461 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006462}
6463
Brian Gix0df4c182011-11-16 13:53:13 -08006464static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006465 u8 link_type, u8 addr_type, u8 status,
6466 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006467{
6468 struct pending_cmd *cmd;
6469 struct mgmt_rp_user_confirm_reply rp;
6470 int err;
6471
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006472 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006473 if (!cmd)
6474 return -ENOENT;
6475
Johan Hedberg272d90d2012-02-09 15:26:12 +02006476 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006477 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006478 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006479 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006480
Johan Hedberga664b5b2011-02-19 12:06:02 -03006481 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006482
6483 return err;
6484}
6485
Johan Hedberg744cf192011-11-08 20:40:14 +02006486int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006487 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006488{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006489 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006490 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006491}
6492
Johan Hedberg272d90d2012-02-09 15:26:12 +02006493int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006494 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006495{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006496 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006497 status,
6498 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006499}
Johan Hedberg2a611692011-02-19 12:06:00 -03006500
Brian Gix604086b2011-11-23 08:28:33 -08006501int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006502 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006503{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006504 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006505 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006506}
6507
Johan Hedberg272d90d2012-02-09 15:26:12 +02006508int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006509 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006510{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006511 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006512 status,
6513 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006514}
6515
Johan Hedberg92a25252012-09-06 18:39:26 +03006516int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6517 u8 link_type, u8 addr_type, u32 passkey,
6518 u8 entered)
6519{
6520 struct mgmt_ev_passkey_notify ev;
6521
6522 BT_DBG("%s", hdev->name);
6523
6524 bacpy(&ev.addr.bdaddr, bdaddr);
6525 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6526 ev.passkey = __cpu_to_le32(passkey);
6527 ev.entered = entered;
6528
6529 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6530}
6531
Marcel Holtmanne5460992013-10-15 14:26:23 -07006532void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6533 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006534{
6535 struct mgmt_ev_auth_failed ev;
6536
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006537 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006538 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006539 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006540
Marcel Holtmanne5460992013-10-15 14:26:23 -07006541 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006542}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006543
Marcel Holtmann464996a2013-10-15 14:26:24 -07006544void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006545{
6546 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006547 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006548
6549 if (status) {
6550 u8 mgmt_err = mgmt_status(status);
6551 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006552 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006553 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006554 }
6555
Marcel Holtmann464996a2013-10-15 14:26:24 -07006556 if (test_bit(HCI_AUTH, &hdev->flags))
6557 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6558 &hdev->dev_flags);
6559 else
6560 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6561 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006562
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006563 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006564 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006565
Johan Hedberg47990ea2012-02-22 11:58:37 +02006566 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006567 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006568
6569 if (match.sk)
6570 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006571}
6572
Johan Hedberg890ea892013-03-15 17:06:52 -05006573static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006574{
Johan Hedberg890ea892013-03-15 17:06:52 -05006575 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006576 struct hci_cp_write_eir cp;
6577
Johan Hedberg976eb202012-10-24 21:12:01 +03006578 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006579 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006580
Johan Hedbergc80da272012-02-22 15:38:48 +02006581 memset(hdev->eir, 0, sizeof(hdev->eir));
6582
Johan Hedbergcacaf522012-02-21 00:52:42 +02006583 memset(&cp, 0, sizeof(cp));
6584
Johan Hedberg890ea892013-03-15 17:06:52 -05006585 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006586}
6587
Marcel Holtmann3e248562013-10-15 14:26:25 -07006588void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006589{
6590 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006591 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006592 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006593
6594 if (status) {
6595 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006596
6597 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006598 &hdev->dev_flags)) {
6599 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006600 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006601 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006602
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006603 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6604 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006605 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006606 }
6607
6608 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006609 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006610 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006611 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6612 if (!changed)
6613 changed = test_and_clear_bit(HCI_HS_ENABLED,
6614 &hdev->dev_flags);
6615 else
6616 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006617 }
6618
6619 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6620
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006621 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006622 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006623
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006624 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006625 sock_put(match.sk);
6626
Johan Hedberg890ea892013-03-15 17:06:52 -05006627 hci_req_init(&req, hdev);
6628
Johan Hedberg37699722014-06-24 14:00:27 +03006629 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6630 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6631 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6632 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006633 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006634 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006635 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006636 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006637
6638 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006639}
6640
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006641void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6642{
6643 struct cmd_lookup match = { NULL, hdev };
6644 bool changed = false;
6645
6646 if (status) {
6647 u8 mgmt_err = mgmt_status(status);
6648
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006649 if (enable) {
6650 if (test_and_clear_bit(HCI_SC_ENABLED,
6651 &hdev->dev_flags))
6652 new_settings(hdev, NULL);
6653 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6654 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006655
6656 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6657 cmd_status_rsp, &mgmt_err);
6658 return;
6659 }
6660
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006661 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006662 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006663 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006664 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006665 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6666 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006667
6668 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6669 settings_rsp, &match);
6670
6671 if (changed)
6672 new_settings(hdev, match.sk);
6673
6674 if (match.sk)
6675 sock_put(match.sk);
6676}
6677
Johan Hedberg92da6092013-03-15 17:06:55 -05006678static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006679{
6680 struct cmd_lookup *match = data;
6681
Johan Hedberg90e70452012-02-23 23:09:40 +02006682 if (match->sk == NULL) {
6683 match->sk = cmd->sk;
6684 sock_hold(match->sk);
6685 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006686}
6687
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006688void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6689 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006690{
Johan Hedberg90e70452012-02-23 23:09:40 +02006691 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006692
Johan Hedberg92da6092013-03-15 17:06:55 -05006693 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6694 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6695 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006696
6697 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006698 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6699 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006700
6701 if (match.sk)
6702 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006703}
6704
Marcel Holtmann7667da32013-10-15 14:26:27 -07006705void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006706{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006707 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006708 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006709
Johan Hedberg13928972013-03-15 17:07:00 -05006710 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006711 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006712
6713 memset(&ev, 0, sizeof(ev));
6714 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006715 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006716
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006717 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006718 if (!cmd) {
6719 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006720
Johan Hedberg13928972013-03-15 17:07:00 -05006721 /* If this is a HCI command related to powering on the
6722 * HCI dev don't send any mgmt signals.
6723 */
6724 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006725 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006726 }
6727
Marcel Holtmann7667da32013-10-15 14:26:27 -07006728 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6729 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006730}
Szymon Jancc35938b2011-03-22 13:12:21 +01006731
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006732void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6733 u8 *randomizer192, u8 *hash256,
6734 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006735{
6736 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006737
Johan Hedberg744cf192011-11-08 20:40:14 +02006738 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006739
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006740 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006741 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006742 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006743
6744 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006745 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6746 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006747 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006748 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6749 hash256 && randomizer256) {
6750 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006751
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006752 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6753 memcpy(rp.randomizer192, randomizer192,
6754 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006755
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006756 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6757 memcpy(rp.randomizer256, randomizer256,
6758 sizeof(rp.randomizer256));
6759
6760 cmd_complete(cmd->sk, hdev->id,
6761 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6762 &rp, sizeof(rp));
6763 } else {
6764 struct mgmt_rp_read_local_oob_data rp;
6765
6766 memcpy(rp.hash, hash192, sizeof(rp.hash));
6767 memcpy(rp.randomizer, randomizer192,
6768 sizeof(rp.randomizer));
6769
6770 cmd_complete(cmd->sk, hdev->id,
6771 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6772 &rp, sizeof(rp));
6773 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006774 }
6775
6776 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006777}
Johan Hedberge17acd42011-03-30 23:57:16 +03006778
Marcel Holtmann901801b2013-10-06 23:55:51 -07006779void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006780 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6781 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006782{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006783 char buf[512];
6784 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006785 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006786
Johan Hedberg75ce2082014-07-02 22:42:01 +03006787 /* Don't send events for a non-kernel initiated discovery. With
6788 * LE one exception is if we have pend_le_reports > 0 in which
6789 * case we're doing passive scanning and want these events.
6790 */
6791 if (!hci_discovery_active(hdev)) {
6792 if (link_type == ACL_LINK)
6793 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006794 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006795 return;
6796 }
Andre Guedes12602d02013-04-30 15:29:40 -03006797
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006798 /* Make sure that the buffer is big enough. The 5 extra bytes
6799 * are for the potential CoD field.
6800 */
6801 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006802 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006803
Johan Hedberg1dc06092012-01-15 21:01:23 +02006804 memset(buf, 0, sizeof(buf));
6805
Johan Hedberg841c5642014-07-07 12:45:54 +03006806 bacpy(&ev->addr.bdaddr, bdaddr);
6807 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006808 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006809 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006810
Johan Hedberg1dc06092012-01-15 21:01:23 +02006811 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006812 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006813
Johan Hedberg1dc06092012-01-15 21:01:23 +02006814 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6815 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006816 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006817
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006818 if (scan_rsp_len > 0)
6819 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6820
6821 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6822 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006823
Marcel Holtmann901801b2013-10-06 23:55:51 -07006824 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006825}
Johan Hedberga88a9652011-03-30 13:18:12 +03006826
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006827void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6828 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006829{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006830 struct mgmt_ev_device_found *ev;
6831 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6832 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006833
Johan Hedbergb644ba32012-01-17 21:48:47 +02006834 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006835
Johan Hedbergb644ba32012-01-17 21:48:47 +02006836 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006837
Johan Hedbergb644ba32012-01-17 21:48:47 +02006838 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006839 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006840 ev->rssi = rssi;
6841
6842 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006843 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006844
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006845 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006846
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006847 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006848}
Johan Hedberg314b2382011-04-27 10:29:57 -04006849
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006850void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006851{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006852 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006853 struct pending_cmd *cmd;
6854
Andre Guedes343fb142011-11-22 17:14:19 -03006855 BT_DBG("%s discovering %u", hdev->name, discovering);
6856
Johan Hedberg164a6e72011-11-01 17:06:44 +02006857 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006858 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006859 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006860 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006861
6862 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006863 u8 type = hdev->discovery.type;
6864
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006865 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6866 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006867 mgmt_pending_remove(cmd);
6868 }
6869
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006870 memset(&ev, 0, sizeof(ev));
6871 ev.type = hdev->discovery.type;
6872 ev.discovering = discovering;
6873
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006874 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006875}
Antti Julku5e762442011-08-25 16:48:02 +03006876
Marcel Holtmann5976e602013-10-06 04:08:14 -07006877static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6878{
6879 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006880}
6881
6882void mgmt_reenable_advertising(struct hci_dev *hdev)
6883{
6884 struct hci_request req;
6885
Marcel Holtmann5976e602013-10-06 04:08:14 -07006886 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6887 return;
6888
6889 hci_req_init(&req, hdev);
6890 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006891 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006892}