blob: b391e2fef4b64789293caa2c1c45775d9ac70131 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan 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 Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200558
Andre Guedesed3fa312012-07-24 15:03:46 -0300559 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300560 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500561 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
562 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300563 settings |= MGMT_SETTING_DISCOVERABLE;
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 Hedberga8b2d5c2012-01-08 23:11:15 +0200606 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_PAIRABLE;
608
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 Hedberg80a1e1d2011-03-28 14:07:23 +0300909static void create_eir(struct hci_dev *hdev, u8 *data)
910{
911 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300912 size_t name_len;
913
914 name_len = strlen(hdev->dev_name);
915
916 if (name_len > 0) {
917 /* EIR Data type */
918 if (name_len > 48) {
919 name_len = 48;
920 ptr[1] = EIR_NAME_SHORT;
921 } else
922 ptr[1] = EIR_NAME_COMPLETE;
923
924 /* EIR Data length */
925 ptr[0] = name_len + 1;
926
927 memcpy(ptr + 2, hdev->dev_name, name_len);
928
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300929 ptr += (name_len + 2);
930 }
931
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100932 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700933 ptr[0] = 2;
934 ptr[1] = EIR_TX_POWER;
935 ptr[2] = (u8) hdev->inq_tx_power;
936
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700937 ptr += 3;
938 }
939
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700940 if (hdev->devid_source > 0) {
941 ptr[0] = 9;
942 ptr[1] = EIR_DEVICE_ID;
943
944 put_unaligned_le16(hdev->devid_source, ptr + 2);
945 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
946 put_unaligned_le16(hdev->devid_product, ptr + 6);
947 put_unaligned_le16(hdev->devid_version, ptr + 8);
948
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700949 ptr += 10;
950 }
951
Johan Hedberg213202e2013-01-27 00:31:33 +0200952 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200953 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200954 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300955}
956
Johan Hedberg890ea892013-03-15 17:06:52 -0500957static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300958{
Johan Hedberg890ea892013-03-15 17:06:52 -0500959 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300960 struct hci_cp_write_eir cp;
961
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200962 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500963 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200964
Johan Hedberg976eb202012-10-24 21:12:01 +0300965 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500966 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200968 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200971 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500972 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973
974 memset(&cp, 0, sizeof(cp));
975
976 create_eir(hdev, cp.data);
977
978 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
981 memcpy(hdev->eir, cp.data, sizeof(cp.data));
982
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984}
985
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200986static u8 get_service_classes(struct hci_dev *hdev)
987{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300988 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200989 u8 val = 0;
990
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300991 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200992 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200993
994 return val;
995}
996
Johan Hedberg890ea892013-03-15 17:06:52 -0500997static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200998{
Johan Hedberg890ea892013-03-15 17:06:52 -0500999 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 cod[3];
1001
1002 BT_DBG("%s", hdev->name);
1003
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001004 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001005 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001006
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001007 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1008 return;
1009
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001010 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001011 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001012
1013 cod[0] = hdev->minor_class;
1014 cod[1] = hdev->major_class;
1015 cod[2] = get_service_classes(hdev);
1016
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001017 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1018 cod[1] |= 0x20;
1019
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001020 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001024}
1025
Johan Hedberga4858cb2014-02-25 19:56:31 +02001026static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001027{
1028 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001029
1030 /* If there's a pending mgmt command the flag will not yet have
1031 * it's final value, so check for this first.
1032 */
1033 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1034 if (cmd) {
1035 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037 }
1038
Johan Hedberga4858cb2014-02-25 19:56:31 +02001039 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040}
1041
1042static void enable_advertising(struct hci_request *req)
1043{
1044 struct hci_dev *hdev = req->hdev;
1045 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001046 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048
Johan Hedberg8d972502014-02-28 12:54:14 +02001049 /* Clear the HCI_ADVERTISING bit temporarily so that the
1050 * hci_update_random_address knows that it's safe to go ahead
1051 * and write a new random address. The flag will be set back on
1052 * as soon as the SET_ADV_ENABLE HCI command completes.
1053 */
1054 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1055
Johan Hedberga4858cb2014-02-25 19:56:31 +02001056 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001057
Johan Hedberga4858cb2014-02-25 19:56:31 +02001058 /* Set require_privacy to true only when non-connectable
1059 * advertising is used. In that case it is fine to use a
1060 * non-resolvable private address.
1061 */
1062 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001063 return;
1064
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001065 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001066 cp.min_interval = cpu_to_le16(0x0800);
1067 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001068 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001069 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001070 cp.channel_map = hdev->le_adv_channel_map;
1071
1072 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1073
1074 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1075}
1076
1077static void disable_advertising(struct hci_request *req)
1078{
1079 u8 enable = 0x00;
1080
1081 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1082}
1083
Johan Hedberg7d785252011-12-15 00:47:39 +02001084static void service_cache_off(struct work_struct *work)
1085{
1086 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001087 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001088 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001089
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001090 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001091 return;
1092
Johan Hedberg890ea892013-03-15 17:06:52 -05001093 hci_req_init(&req, hdev);
1094
Johan Hedberg7d785252011-12-15 00:47:39 +02001095 hci_dev_lock(hdev);
1096
Johan Hedberg890ea892013-03-15 17:06:52 -05001097 update_eir(&req);
1098 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001099
1100 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001101
1102 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001103}
1104
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001105static void rpa_expired(struct work_struct *work)
1106{
1107 struct hci_dev *hdev = container_of(work, struct hci_dev,
1108 rpa_expired.work);
1109 struct hci_request req;
1110
1111 BT_DBG("");
1112
1113 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1114
1115 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
1116 hci_conn_num(hdev, LE_LINK) > 0)
1117 return;
1118
1119 /* The generation of a new RPA and programming it into the
1120 * controller happens in the enable_advertising() function.
1121 */
1122
1123 hci_req_init(&req, hdev);
1124
1125 disable_advertising(&req);
1126 enable_advertising(&req);
1127
1128 hci_req_run(&req, NULL);
1129}
1130
Johan Hedberg6a919082012-02-28 06:17:26 +02001131static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001132{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001133 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001134 return;
1135
Johan Hedberg4f87da82012-03-02 19:55:56 +02001136 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001138
Johan Hedberg4f87da82012-03-02 19:55:56 +02001139 /* Non-mgmt controlled devices get this bit set
1140 * implicitly so that pairing works for them, however
1141 * for mgmt we require user-space to explicitly enable
1142 * it
1143 */
1144 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001145}
1146
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001147static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001148 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001149{
1150 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001151
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001152 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001153
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001154 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001155
Johan Hedberg03811012010-12-08 00:21:06 +02001156 memset(&rp, 0, sizeof(rp));
1157
Johan Hedberg03811012010-12-08 00:21:06 +02001158 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001159
1160 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001161 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001162
1163 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1164 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1165
1166 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001167
1168 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001169 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001170
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001171 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001173 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001174 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001175}
1176
1177static void mgmt_pending_free(struct pending_cmd *cmd)
1178{
1179 sock_put(cmd->sk);
1180 kfree(cmd->param);
1181 kfree(cmd);
1182}
1183
1184static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001185 struct hci_dev *hdev, void *data,
1186 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001187{
1188 struct pending_cmd *cmd;
1189
Johan Hedbergfca20012014-06-28 17:54:05 +03001190 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001191 if (!cmd)
1192 return NULL;
1193
1194 cmd->opcode = opcode;
1195 cmd->index = hdev->id;
1196
Andre Guedes12b94562012-06-07 19:05:45 -03001197 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001198 if (!cmd->param) {
1199 kfree(cmd);
1200 return NULL;
1201 }
1202
1203 if (data)
1204 memcpy(cmd->param, data, len);
1205
1206 cmd->sk = sk;
1207 sock_hold(sk);
1208
1209 list_add(&cmd->list, &hdev->mgmt_pending);
1210
1211 return cmd;
1212}
1213
1214static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001215 void (*cb)(struct pending_cmd *cmd,
1216 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001217 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001218{
Andre Guedesa3d09352013-02-01 11:21:30 -03001219 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001220
Andre Guedesa3d09352013-02-01 11:21:30 -03001221 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001222 if (opcode > 0 && cmd->opcode != opcode)
1223 continue;
1224
1225 cb(cmd, data);
1226 }
1227}
1228
Johan Hedberg03811012010-12-08 00:21:06 +02001229static void mgmt_pending_remove(struct pending_cmd *cmd)
1230{
1231 list_del(&cmd->list);
1232 mgmt_pending_free(cmd);
1233}
1234
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001235static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001236{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001237 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001238
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001239 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001240 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001241}
1242
Johan Hedberg8b064a32014-02-24 14:52:22 +02001243static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1244{
1245 BT_DBG("%s status 0x%02x", hdev->name, status);
1246
Johan Hedberga3172b72014-02-28 09:33:44 +02001247 if (hci_conn_count(hdev) == 0) {
1248 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001249 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001250 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001251}
1252
Johan Hedberg21a60d32014-06-10 14:05:58 +03001253static void hci_stop_discovery(struct hci_request *req)
1254{
1255 struct hci_dev *hdev = req->hdev;
1256 struct hci_cp_remote_name_req_cancel cp;
1257 struct inquiry_entry *e;
1258
1259 switch (hdev->discovery.state) {
1260 case DISCOVERY_FINDING:
1261 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1262 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1263 } else {
1264 cancel_delayed_work(&hdev->le_scan_disable);
1265 hci_req_add_le_scan_disable(req);
1266 }
1267
1268 break;
1269
1270 case DISCOVERY_RESOLVING:
1271 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1272 NAME_PENDING);
1273 if (!e)
1274 return;
1275
1276 bacpy(&cp.bdaddr, &e->data.bdaddr);
1277 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1278 &cp);
1279
1280 break;
1281
1282 default:
1283 /* Passive scanning */
1284 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1285 hci_req_add_le_scan_disable(req);
1286 break;
1287 }
1288}
1289
Johan Hedberg8b064a32014-02-24 14:52:22 +02001290static int clean_up_hci_state(struct hci_dev *hdev)
1291{
1292 struct hci_request req;
1293 struct hci_conn *conn;
1294
1295 hci_req_init(&req, hdev);
1296
1297 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1298 test_bit(HCI_PSCAN, &hdev->flags)) {
1299 u8 scan = 0x00;
1300 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1301 }
1302
1303 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1304 disable_advertising(&req);
1305
Johan Hedbergf8680f12014-06-10 14:05:59 +03001306 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001307
1308 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1309 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001310 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001311
Johan Hedbergc9910d02014-02-27 14:35:12 +02001312 switch (conn->state) {
1313 case BT_CONNECTED:
1314 case BT_CONFIG:
1315 dc.handle = cpu_to_le16(conn->handle);
1316 dc.reason = 0x15; /* Terminated due to Power Off */
1317 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1318 break;
1319 case BT_CONNECT:
1320 if (conn->type == LE_LINK)
1321 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1322 0, NULL);
1323 else if (conn->type == ACL_LINK)
1324 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1325 6, &conn->dst);
1326 break;
1327 case BT_CONNECT2:
1328 bacpy(&rej.bdaddr, &conn->dst);
1329 rej.reason = 0x15; /* Terminated due to Power Off */
1330 if (conn->type == ACL_LINK)
1331 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1332 sizeof(rej), &rej);
1333 else if (conn->type == SCO_LINK)
1334 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1335 sizeof(rej), &rej);
1336 break;
1337 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001338 }
1339
1340 return hci_req_run(&req, clean_up_hci_complete);
1341}
1342
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001343static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001344 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001345{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001346 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001347 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001348 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001350 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001351
Johan Hedberga7e80f22013-01-09 16:05:19 +02001352 if (cp->val != 0x00 && cp->val != 0x01)
1353 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1354 MGMT_STATUS_INVALID_PARAMS);
1355
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001356 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001357
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001358 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1359 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1360 MGMT_STATUS_BUSY);
1361 goto failed;
1362 }
1363
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001364 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1365 cancel_delayed_work(&hdev->power_off);
1366
1367 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001368 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1369 data, len);
1370 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001371 goto failed;
1372 }
1373 }
1374
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001375 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001376 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001377 goto failed;
1378 }
1379
Johan Hedberg03811012010-12-08 00:21:06 +02001380 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1381 if (!cmd) {
1382 err = -ENOMEM;
1383 goto failed;
1384 }
1385
Johan Hedberg8b064a32014-02-24 14:52:22 +02001386 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001387 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001388 err = 0;
1389 } else {
1390 /* Disconnect connections, stop scans, etc */
1391 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001392 if (!err)
1393 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1394 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001395
Johan Hedberg8b064a32014-02-24 14:52:22 +02001396 /* ENODATA means there were no HCI commands queued */
1397 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001398 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001399 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1400 err = 0;
1401 }
1402 }
Johan Hedberg03811012010-12-08 00:21:06 +02001403
1404failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001405 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001406 return err;
1407}
1408
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001409static int new_settings(struct hci_dev *hdev, struct sock *skip)
1410{
1411 __le32 ev;
1412
1413 ev = cpu_to_le32(get_current_settings(hdev));
1414
1415 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1416}
1417
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001418struct cmd_lookup {
1419 struct sock *sk;
1420 struct hci_dev *hdev;
1421 u8 mgmt_status;
1422};
1423
1424static void settings_rsp(struct pending_cmd *cmd, void *data)
1425{
1426 struct cmd_lookup *match = data;
1427
1428 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1429
1430 list_del(&cmd->list);
1431
1432 if (match->sk == NULL) {
1433 match->sk = cmd->sk;
1434 sock_hold(match->sk);
1435 }
1436
1437 mgmt_pending_free(cmd);
1438}
1439
1440static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1441{
1442 u8 *status = data;
1443
1444 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1445 mgmt_pending_remove(cmd);
1446}
1447
Johan Hedberge6fe7982013-10-02 15:45:22 +03001448static u8 mgmt_bredr_support(struct hci_dev *hdev)
1449{
1450 if (!lmp_bredr_capable(hdev))
1451 return MGMT_STATUS_NOT_SUPPORTED;
1452 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1453 return MGMT_STATUS_REJECTED;
1454 else
1455 return MGMT_STATUS_SUCCESS;
1456}
1457
1458static u8 mgmt_le_support(struct hci_dev *hdev)
1459{
1460 if (!lmp_le_capable(hdev))
1461 return MGMT_STATUS_NOT_SUPPORTED;
1462 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1463 return MGMT_STATUS_REJECTED;
1464 else
1465 return MGMT_STATUS_SUCCESS;
1466}
1467
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001468static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1469{
1470 struct pending_cmd *cmd;
1471 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001472 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001473 bool changed;
1474
1475 BT_DBG("status 0x%02x", status);
1476
1477 hci_dev_lock(hdev);
1478
1479 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1480 if (!cmd)
1481 goto unlock;
1482
1483 if (status) {
1484 u8 mgmt_err = mgmt_status(status);
1485 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001486 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001487 goto remove_cmd;
1488 }
1489
1490 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001491 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001492 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1493 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001494
1495 if (hdev->discov_timeout > 0) {
1496 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1497 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1498 to);
1499 }
1500 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001501 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1502 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001503 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504
1505 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1506
1507 if (changed)
1508 new_settings(hdev, cmd->sk);
1509
Marcel Holtmann970ba522013-10-15 06:33:57 -07001510 /* When the discoverable mode gets changed, make sure
1511 * that class of device has the limited discoverable
1512 * bit correctly set.
1513 */
1514 hci_req_init(&req, hdev);
1515 update_class(&req);
1516 hci_req_run(&req, NULL);
1517
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001518remove_cmd:
1519 mgmt_pending_remove(cmd);
1520
1521unlock:
1522 hci_dev_unlock(hdev);
1523}
1524
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001525static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001526 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001527{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001528 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001529 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001530 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001531 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001532 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001533 int err;
1534
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001535 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001536
Johan Hedberg9a43e252013-10-20 19:00:07 +03001537 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1538 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001539 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001540 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001541
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001542 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001543 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1544 MGMT_STATUS_INVALID_PARAMS);
1545
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001546 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001547
1548 /* Disabling discoverable requires that no timeout is set,
1549 * and enabling limited discoverable requires a timeout.
1550 */
1551 if ((cp->val == 0x00 && timeout > 0) ||
1552 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001553 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001554 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001555
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001556 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001557
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001558 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001559 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001560 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001561 goto failed;
1562 }
1563
1564 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001565 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001566 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001567 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001568 goto failed;
1569 }
1570
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001571 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001572 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001573 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001574 goto failed;
1575 }
1576
1577 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001578 bool changed = false;
1579
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001580 /* Setting limited discoverable when powered off is
1581 * not a valid operation since it requires a timeout
1582 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1583 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001584 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1585 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1586 changed = true;
1587 }
1588
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001589 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001590 if (err < 0)
1591 goto failed;
1592
1593 if (changed)
1594 err = new_settings(hdev, sk);
1595
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001596 goto failed;
1597 }
1598
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001599 /* If the current mode is the same, then just update the timeout
1600 * value with the new value. And if only the timeout gets updated,
1601 * then no need for any HCI transactions.
1602 */
1603 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1604 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1605 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001606 cancel_delayed_work(&hdev->discov_off);
1607 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001608
Marcel Holtmann36261542013-10-15 08:28:51 -07001609 if (cp->val && hdev->discov_timeout > 0) {
1610 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001611 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001612 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001613 }
1614
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001615 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1620 if (!cmd) {
1621 err = -ENOMEM;
1622 goto failed;
1623 }
1624
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001625 /* Cancel any potential discoverable timeout that might be
1626 * still active and store new timeout value. The arming of
1627 * the timeout happens in the complete handler.
1628 */
1629 cancel_delayed_work(&hdev->discov_off);
1630 hdev->discov_timeout = timeout;
1631
Johan Hedbergb456f872013-10-19 23:38:22 +03001632 /* Limited discoverable mode */
1633 if (cp->val == 0x02)
1634 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1635 else
1636 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1637
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001638 hci_req_init(&req, hdev);
1639
Johan Hedberg9a43e252013-10-20 19:00:07 +03001640 /* The procedure for LE-only controllers is much simpler - just
1641 * update the advertising data.
1642 */
1643 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1644 goto update_ad;
1645
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001646 scan = SCAN_PAGE;
1647
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001648 if (cp->val) {
1649 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001650
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001651 if (cp->val == 0x02) {
1652 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001653 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1655 hci_cp.iac_lap[1] = 0x8b;
1656 hci_cp.iac_lap[2] = 0x9e;
1657 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1658 hci_cp.iac_lap[4] = 0x8b;
1659 hci_cp.iac_lap[5] = 0x9e;
1660 } else {
1661 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001662 hci_cp.num_iac = 1;
1663 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1664 hci_cp.iac_lap[1] = 0x8b;
1665 hci_cp.iac_lap[2] = 0x9e;
1666 }
1667
1668 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1669 (hci_cp.num_iac * 3) + 1, &hci_cp);
1670
1671 scan |= SCAN_INQUIRY;
1672 } else {
1673 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1674 }
1675
1676 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001677
Johan Hedberg9a43e252013-10-20 19:00:07 +03001678update_ad:
1679 update_adv_data(&req);
1680
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001681 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001682 if (err < 0)
1683 mgmt_pending_remove(cmd);
1684
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001685failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001686 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001687 return err;
1688}
1689
Johan Hedberg406d7802013-03-15 17:07:09 -05001690static void write_fast_connectable(struct hci_request *req, bool enable)
1691{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001692 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001693 struct hci_cp_write_page_scan_activity acp;
1694 u8 type;
1695
Johan Hedberg547003b2013-10-21 16:51:53 +03001696 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1697 return;
1698
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001699 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1700 return;
1701
Johan Hedberg406d7802013-03-15 17:07:09 -05001702 if (enable) {
1703 type = PAGE_SCAN_TYPE_INTERLACED;
1704
1705 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001706 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001707 } else {
1708 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1709
1710 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001711 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001712 }
1713
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001714 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001715
Johan Hedbergbd98b992013-03-15 17:07:13 -05001716 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1717 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1718 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1719 sizeof(acp), &acp);
1720
1721 if (hdev->page_scan_type != type)
1722 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001723}
1724
Johan Hedberg2b76f452013-03-15 17:07:04 -05001725static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1726{
1727 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001728 struct mgmt_mode *cp;
1729 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001730
1731 BT_DBG("status 0x%02x", status);
1732
1733 hci_dev_lock(hdev);
1734
1735 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1736 if (!cmd)
1737 goto unlock;
1738
Johan Hedberg37438c12013-10-14 16:20:05 +03001739 if (status) {
1740 u8 mgmt_err = mgmt_status(status);
1741 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1742 goto remove_cmd;
1743 }
1744
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001745 cp = cmd->param;
1746 if (cp->val)
1747 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1748 else
1749 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1750
Johan Hedberg2b76f452013-03-15 17:07:04 -05001751 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1752
Johan Hedberg2b7be332014-07-07 14:40:22 +03001753 if (changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001754 new_settings(hdev, cmd->sk);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001755 hci_update_background_scan(hdev);
1756 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001757
Johan Hedberg37438c12013-10-14 16:20:05 +03001758remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001759 mgmt_pending_remove(cmd);
1760
1761unlock:
1762 hci_dev_unlock(hdev);
1763}
1764
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001765static int set_connectable_update_settings(struct hci_dev *hdev,
1766 struct sock *sk, u8 val)
1767{
1768 bool changed = false;
1769 int err;
1770
1771 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1772 changed = true;
1773
1774 if (val) {
1775 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1776 } else {
1777 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1778 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1779 }
1780
1781 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1782 if (err < 0)
1783 return err;
1784
1785 if (changed)
1786 return new_settings(hdev, sk);
1787
1788 return 0;
1789}
1790
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001791static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001792 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001793{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001794 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001795 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001796 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001797 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001798 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001799
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001800 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001801
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001802 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1803 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001804 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001805 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001806
Johan Hedberga7e80f22013-01-09 16:05:19 +02001807 if (cp->val != 0x00 && cp->val != 0x01)
1808 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1809 MGMT_STATUS_INVALID_PARAMS);
1810
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001811 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001812
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001813 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001814 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001815 goto failed;
1816 }
1817
1818 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001819 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001820 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001821 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001822 goto failed;
1823 }
1824
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001825 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1826 if (!cmd) {
1827 err = -ENOMEM;
1828 goto failed;
1829 }
1830
Johan Hedberg2b76f452013-03-15 17:07:04 -05001831 hci_req_init(&req, hdev);
1832
Johan Hedberg9a43e252013-10-20 19:00:07 +03001833 /* If BR/EDR is not enabled and we disable advertising as a
1834 * by-product of disabling connectable, we need to update the
1835 * advertising flags.
1836 */
1837 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1838 if (!cp->val) {
1839 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1840 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1841 }
1842 update_adv_data(&req);
1843 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001844 if (cp->val) {
1845 scan = SCAN_PAGE;
1846 } else {
1847 scan = 0;
1848
1849 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001850 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001851 cancel_delayed_work(&hdev->discov_off);
1852 }
1853
1854 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1855 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001856
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001857 /* If we're going from non-connectable to connectable or
1858 * vice-versa when fast connectable is enabled ensure that fast
1859 * connectable gets disabled. write_fast_connectable won't do
1860 * anything if the page scan parameters are already what they
1861 * should be.
1862 */
1863 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001864 write_fast_connectable(&req, false);
1865
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001866 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1867 hci_conn_num(hdev, LE_LINK) == 0) {
1868 disable_advertising(&req);
1869 enable_advertising(&req);
1870 }
1871
Johan Hedberg2b76f452013-03-15 17:07:04 -05001872 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001873 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001874 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001875 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001876 err = set_connectable_update_settings(hdev, sk,
1877 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001878 goto failed;
1879 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001880
1881failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001882 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001883 return err;
1884}
1885
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001886static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001887 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001888{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001889 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001890 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001891 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001893 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001894
Johan Hedberga7e80f22013-01-09 16:05:19 +02001895 if (cp->val != 0x00 && cp->val != 0x01)
1896 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1897 MGMT_STATUS_INVALID_PARAMS);
1898
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001899 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001900
1901 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001902 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001903 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001904 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001905
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001906 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001907 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001908 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001909
Marcel Holtmann55594352013-10-06 16:11:57 -07001910 if (changed)
1911 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001912
Marcel Holtmann55594352013-10-06 16:11:57 -07001913unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001914 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001915 return err;
1916}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001917
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001918static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1919 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001920{
1921 struct mgmt_mode *cp = data;
1922 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001923 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001924 int err;
1925
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001926 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001927
Johan Hedberge6fe7982013-10-02 15:45:22 +03001928 status = mgmt_bredr_support(hdev);
1929 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001930 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001931 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001932
Johan Hedberga7e80f22013-01-09 16:05:19 +02001933 if (cp->val != 0x00 && cp->val != 0x01)
1934 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1935 MGMT_STATUS_INVALID_PARAMS);
1936
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001937 hci_dev_lock(hdev);
1938
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001939 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001940 bool changed = false;
1941
1942 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001943 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001944 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1945 changed = true;
1946 }
1947
1948 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1949 if (err < 0)
1950 goto failed;
1951
1952 if (changed)
1953 err = new_settings(hdev, sk);
1954
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001955 goto failed;
1956 }
1957
1958 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001959 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001960 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001961 goto failed;
1962 }
1963
1964 val = !!cp->val;
1965
1966 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1967 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1968 goto failed;
1969 }
1970
1971 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1972 if (!cmd) {
1973 err = -ENOMEM;
1974 goto failed;
1975 }
1976
1977 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1978 if (err < 0) {
1979 mgmt_pending_remove(cmd);
1980 goto failed;
1981 }
1982
1983failed:
1984 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001985 return err;
1986}
1987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001988static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001989{
1990 struct mgmt_mode *cp = data;
1991 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001992 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001993 int err;
1994
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001995 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001996
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001997 status = mgmt_bredr_support(hdev);
1998 if (status)
1999 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2000
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002001 if (!lmp_ssp_capable(hdev))
2002 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2003 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002004
Johan Hedberga7e80f22013-01-09 16:05:19 +02002005 if (cp->val != 0x00 && cp->val != 0x01)
2006 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2007 MGMT_STATUS_INVALID_PARAMS);
2008
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002009 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002010
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002011 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002012 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002013
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002014 if (cp->val) {
2015 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2016 &hdev->dev_flags);
2017 } else {
2018 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2019 &hdev->dev_flags);
2020 if (!changed)
2021 changed = test_and_clear_bit(HCI_HS_ENABLED,
2022 &hdev->dev_flags);
2023 else
2024 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002025 }
2026
2027 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2028 if (err < 0)
2029 goto failed;
2030
2031 if (changed)
2032 err = new_settings(hdev, sk);
2033
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002034 goto failed;
2035 }
2036
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002037 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2038 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002039 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2040 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002041 goto failed;
2042 }
2043
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002044 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002045 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2046 goto failed;
2047 }
2048
2049 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2050 if (!cmd) {
2051 err = -ENOMEM;
2052 goto failed;
2053 }
2054
Johan Hedberg37699722014-06-24 14:00:27 +03002055 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2056 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2057 sizeof(cp->val), &cp->val);
2058
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002059 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002060 if (err < 0) {
2061 mgmt_pending_remove(cmd);
2062 goto failed;
2063 }
2064
2065failed:
2066 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002067 return err;
2068}
2069
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002070static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002071{
2072 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002073 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002074 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002075 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002076
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002077 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002078
Johan Hedberge6fe7982013-10-02 15:45:22 +03002079 status = mgmt_bredr_support(hdev);
2080 if (status)
2081 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002082
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002083 if (!lmp_ssp_capable(hdev))
2084 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2085 MGMT_STATUS_NOT_SUPPORTED);
2086
2087 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2088 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2089 MGMT_STATUS_REJECTED);
2090
Johan Hedberga7e80f22013-01-09 16:05:19 +02002091 if (cp->val != 0x00 && cp->val != 0x01)
2092 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2093 MGMT_STATUS_INVALID_PARAMS);
2094
Marcel Holtmannee392692013-10-01 22:59:23 -07002095 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002096
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002097 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002098 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002099 } else {
2100 if (hdev_is_powered(hdev)) {
2101 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2102 MGMT_STATUS_REJECTED);
2103 goto unlock;
2104 }
2105
Marcel Holtmannee392692013-10-01 22:59:23 -07002106 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002107 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002108
2109 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2110 if (err < 0)
2111 goto unlock;
2112
2113 if (changed)
2114 err = new_settings(hdev, sk);
2115
2116unlock:
2117 hci_dev_unlock(hdev);
2118 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002119}
2120
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002121static void le_enable_complete(struct hci_dev *hdev, u8 status)
2122{
2123 struct cmd_lookup match = { NULL, hdev };
2124
2125 if (status) {
2126 u8 mgmt_err = mgmt_status(status);
2127
2128 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2129 &mgmt_err);
2130 return;
2131 }
2132
2133 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2134
2135 new_settings(hdev, match.sk);
2136
2137 if (match.sk)
2138 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002139
2140 /* Make sure the controller has a good default for
2141 * advertising data. Restrict the update to when LE
2142 * has actually been enabled. During power on, the
2143 * update in powered_update_hci will take care of it.
2144 */
2145 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2146 struct hci_request req;
2147
2148 hci_dev_lock(hdev);
2149
2150 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002151 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002152 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002153 hci_req_run(&req, NULL);
2154
2155 hci_dev_unlock(hdev);
2156 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002157}
2158
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002159static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002160{
2161 struct mgmt_mode *cp = data;
2162 struct hci_cp_write_le_host_supported hci_cp;
2163 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002164 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002165 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002166 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002167
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002168 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002169
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002170 if (!lmp_le_capable(hdev))
2171 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2172 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002173
Johan Hedberga7e80f22013-01-09 16:05:19 +02002174 if (cp->val != 0x00 && cp->val != 0x01)
2175 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2176 MGMT_STATUS_INVALID_PARAMS);
2177
Johan Hedbergc73eee92013-04-19 18:35:21 +03002178 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002179 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002180 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2181 MGMT_STATUS_REJECTED);
2182
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002183 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002184
2185 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002186 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002187
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002188 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002189 bool changed = false;
2190
2191 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2192 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2193 changed = true;
2194 }
2195
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002196 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2197 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002198 changed = true;
2199 }
2200
Johan Hedberg06199cf2012-02-22 16:37:11 +02002201 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2202 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002203 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002204
2205 if (changed)
2206 err = new_settings(hdev, sk);
2207
Johan Hedberg1de028c2012-02-29 19:55:35 -08002208 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002209 }
2210
Johan Hedberg4375f102013-09-25 13:26:10 +03002211 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2212 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002213 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002214 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002215 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002216 }
2217
2218 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2219 if (!cmd) {
2220 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002221 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002222 }
2223
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002224 hci_req_init(&req, hdev);
2225
Johan Hedberg06199cf2012-02-22 16:37:11 +02002226 memset(&hci_cp, 0, sizeof(hci_cp));
2227
2228 if (val) {
2229 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002230 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002231 } else {
2232 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2233 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002234 }
2235
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002236 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2237 &hci_cp);
2238
2239 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302240 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002241 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002242
Johan Hedberg1de028c2012-02-29 19:55:35 -08002243unlock:
2244 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002245 return err;
2246}
2247
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002248/* This is a helper function to test for pending mgmt commands that can
2249 * cause CoD or EIR HCI commands. We can only allow one such pending
2250 * mgmt command at a time since otherwise we cannot easily track what
2251 * the current values are, will be, and based on that calculate if a new
2252 * HCI command needs to be sent and if yes with what value.
2253 */
2254static bool pending_eir_or_class(struct hci_dev *hdev)
2255{
2256 struct pending_cmd *cmd;
2257
2258 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2259 switch (cmd->opcode) {
2260 case MGMT_OP_ADD_UUID:
2261 case MGMT_OP_REMOVE_UUID:
2262 case MGMT_OP_SET_DEV_CLASS:
2263 case MGMT_OP_SET_POWERED:
2264 return true;
2265 }
2266 }
2267
2268 return false;
2269}
2270
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002271static const u8 bluetooth_base_uuid[] = {
2272 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2273 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2274};
2275
2276static u8 get_uuid_size(const u8 *uuid)
2277{
2278 u32 val;
2279
2280 if (memcmp(uuid, bluetooth_base_uuid, 12))
2281 return 128;
2282
2283 val = get_unaligned_le32(&uuid[12]);
2284 if (val > 0xffff)
2285 return 32;
2286
2287 return 16;
2288}
2289
Johan Hedberg92da6092013-03-15 17:06:55 -05002290static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2291{
2292 struct pending_cmd *cmd;
2293
2294 hci_dev_lock(hdev);
2295
2296 cmd = mgmt_pending_find(mgmt_op, hdev);
2297 if (!cmd)
2298 goto unlock;
2299
2300 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2301 hdev->dev_class, 3);
2302
2303 mgmt_pending_remove(cmd);
2304
2305unlock:
2306 hci_dev_unlock(hdev);
2307}
2308
2309static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2310{
2311 BT_DBG("status 0x%02x", status);
2312
2313 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2314}
2315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002316static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002317{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002318 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002319 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002320 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002321 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002322 int err;
2323
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002324 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002325
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002326 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002327
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002328 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002329 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002330 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002331 goto failed;
2332 }
2333
Andre Guedes92c4c202012-06-07 19:05:44 -03002334 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002335 if (!uuid) {
2336 err = -ENOMEM;
2337 goto failed;
2338 }
2339
2340 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002341 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002342 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002343
Johan Hedbergde66aa62013-01-27 00:31:27 +02002344 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002345
Johan Hedberg890ea892013-03-15 17:06:52 -05002346 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002347
Johan Hedberg890ea892013-03-15 17:06:52 -05002348 update_class(&req);
2349 update_eir(&req);
2350
Johan Hedberg92da6092013-03-15 17:06:55 -05002351 err = hci_req_run(&req, add_uuid_complete);
2352 if (err < 0) {
2353 if (err != -ENODATA)
2354 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002355
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002356 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002357 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002358 goto failed;
2359 }
2360
2361 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002362 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002363 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002364 goto failed;
2365 }
2366
2367 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002368
2369failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002370 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002371 return err;
2372}
2373
Johan Hedberg24b78d02012-02-23 23:24:30 +02002374static bool enable_service_cache(struct hci_dev *hdev)
2375{
2376 if (!hdev_is_powered(hdev))
2377 return false;
2378
2379 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002380 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2381 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002382 return true;
2383 }
2384
2385 return false;
2386}
2387
Johan Hedberg92da6092013-03-15 17:06:55 -05002388static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2389{
2390 BT_DBG("status 0x%02x", status);
2391
2392 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2393}
2394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002396 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002397{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002398 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002399 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002400 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 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 -05002402 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002403 int err, found;
2404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002405 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002407 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002408
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002409 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002410 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002411 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002412 goto unlock;
2413 }
2414
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002415 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002416 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002417
Johan Hedberg24b78d02012-02-23 23:24:30 +02002418 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002419 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002420 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002421 goto unlock;
2422 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002423
Johan Hedberg9246a862012-02-23 21:33:16 +02002424 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002425 }
2426
2427 found = 0;
2428
Johan Hedberg056341c2013-01-27 00:31:30 +02002429 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002430 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2431 continue;
2432
2433 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002434 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002435 found++;
2436 }
2437
2438 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002439 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002440 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002441 goto unlock;
2442 }
2443
Johan Hedberg9246a862012-02-23 21:33:16 +02002444update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002445 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002446
Johan Hedberg890ea892013-03-15 17:06:52 -05002447 update_class(&req);
2448 update_eir(&req);
2449
Johan Hedberg92da6092013-03-15 17:06:55 -05002450 err = hci_req_run(&req, remove_uuid_complete);
2451 if (err < 0) {
2452 if (err != -ENODATA)
2453 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002454
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002455 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002456 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002457 goto unlock;
2458 }
2459
2460 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002461 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002462 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002463 goto unlock;
2464 }
2465
2466 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002467
2468unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002469 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002470 return err;
2471}
2472
Johan Hedberg92da6092013-03-15 17:06:55 -05002473static void set_class_complete(struct hci_dev *hdev, u8 status)
2474{
2475 BT_DBG("status 0x%02x", status);
2476
2477 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2478}
2479
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002480static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002481 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002482{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002483 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002484 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002485 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002486 int err;
2487
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002488 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002489
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002490 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002491 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2492 MGMT_STATUS_NOT_SUPPORTED);
2493
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002494 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002495
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002496 if (pending_eir_or_class(hdev)) {
2497 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2498 MGMT_STATUS_BUSY);
2499 goto unlock;
2500 }
2501
2502 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2503 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2504 MGMT_STATUS_INVALID_PARAMS);
2505 goto unlock;
2506 }
2507
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002508 hdev->major_class = cp->major;
2509 hdev->minor_class = cp->minor;
2510
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002511 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002512 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002513 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002514 goto unlock;
2515 }
2516
Johan Hedberg890ea892013-03-15 17:06:52 -05002517 hci_req_init(&req, hdev);
2518
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002519 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002520 hci_dev_unlock(hdev);
2521 cancel_delayed_work_sync(&hdev->service_cache);
2522 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002523 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002524 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002525
Johan Hedberg890ea892013-03-15 17:06:52 -05002526 update_class(&req);
2527
Johan Hedberg92da6092013-03-15 17:06:55 -05002528 err = hci_req_run(&req, set_class_complete);
2529 if (err < 0) {
2530 if (err != -ENODATA)
2531 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002532
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002533 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002534 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002535 goto unlock;
2536 }
2537
2538 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002539 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002540 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002541 goto unlock;
2542 }
2543
2544 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002545
Johan Hedbergb5235a62012-02-21 14:32:24 +02002546unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002547 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002548 return err;
2549}
2550
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002551static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002552 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002553{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002554 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002555 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2556 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002557 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002558 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002559 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002560
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002561 BT_DBG("request for %s", hdev->name);
2562
2563 if (!lmp_bredr_capable(hdev))
2564 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2565 MGMT_STATUS_NOT_SUPPORTED);
2566
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002567 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002568 if (key_count > max_key_count) {
2569 BT_ERR("load_link_keys: too big key_count value %u",
2570 key_count);
2571 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2572 MGMT_STATUS_INVALID_PARAMS);
2573 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002574
Johan Hedberg86742e12011-11-07 23:13:38 +02002575 expected_len = sizeof(*cp) + key_count *
2576 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002577 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002578 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002579 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002580 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002581 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002582 }
2583
Johan Hedberg4ae14302013-01-20 14:27:13 +02002584 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2585 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2586 MGMT_STATUS_INVALID_PARAMS);
2587
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002588 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002589 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002590
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002591 for (i = 0; i < key_count; i++) {
2592 struct mgmt_link_key_info *key = &cp->keys[i];
2593
Marcel Holtmann8e991132014-01-10 02:07:25 -08002594 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002595 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2596 MGMT_STATUS_INVALID_PARAMS);
2597 }
2598
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002599 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002600
2601 hci_link_keys_clear(hdev);
2602
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002603 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002604 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2605 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002606 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002607 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2608 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002609
2610 if (changed)
2611 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002612
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002613 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002614 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002615
Johan Hedberg58e92932014-06-24 14:00:26 +03002616 /* Always ignore debug keys and require a new pairing if
2617 * the user wants to use them.
2618 */
2619 if (key->type == HCI_LK_DEBUG_COMBINATION)
2620 continue;
2621
Johan Hedberg7652ff62014-06-24 13:15:49 +03002622 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2623 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002624 }
2625
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002626 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002627
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002628 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002629
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002630 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002631}
2632
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002633static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002634 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002635{
2636 struct mgmt_ev_device_unpaired ev;
2637
2638 bacpy(&ev.addr.bdaddr, bdaddr);
2639 ev.addr.type = addr_type;
2640
2641 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002642 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002643}
2644
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002645static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002646 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002647{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002648 struct mgmt_cp_unpair_device *cp = data;
2649 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002650 struct hci_cp_disconnect dc;
2651 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002652 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653 int err;
2654
Johan Hedberga8a1d192011-11-10 15:54:38 +02002655 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002656 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2657 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002658
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002659 if (!bdaddr_type_is_valid(cp->addr.type))
2660 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2661 MGMT_STATUS_INVALID_PARAMS,
2662 &rp, sizeof(rp));
2663
Johan Hedberg118da702013-01-20 14:27:20 +02002664 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2665 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2666 MGMT_STATUS_INVALID_PARAMS,
2667 &rp, sizeof(rp));
2668
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002669 hci_dev_lock(hdev);
2670
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002671 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002672 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002673 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002674 goto unlock;
2675 }
2676
Johan Hedberge0b2b272014-02-18 17:14:31 +02002677 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002678 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002679 } else {
2680 u8 addr_type;
2681
2682 if (cp->addr.type == BDADDR_LE_PUBLIC)
2683 addr_type = ADDR_LE_DEV_PUBLIC;
2684 else
2685 addr_type = ADDR_LE_DEV_RANDOM;
2686
Johan Hedberga7ec7332014-02-18 17:14:35 +02002687 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2688
Andre Guedesa9b0a042014-02-26 20:21:52 -03002689 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2690
Johan Hedberge0b2b272014-02-18 17:14:31 +02002691 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2692 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002693
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002695 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002696 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002697 goto unlock;
2698 }
2699
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002700 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002701 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002702 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002703 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002704 else
2705 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002706 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002707 } else {
2708 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002709 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710
Johan Hedberga8a1d192011-11-10 15:54:38 +02002711 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002712 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002714 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002715 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002716 }
2717
Johan Hedberg124f6e32012-02-09 13:50:12 +02002718 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002719 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002720 if (!cmd) {
2721 err = -ENOMEM;
2722 goto unlock;
2723 }
2724
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002725 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002726 dc.reason = 0x13; /* Remote User Terminated Connection */
2727 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2728 if (err < 0)
2729 mgmt_pending_remove(cmd);
2730
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002731unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002732 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002733 return err;
2734}
2735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002736static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002737 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002738{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002739 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002740 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002741 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002742 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002743 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002744 int err;
2745
2746 BT_DBG("");
2747
Johan Hedberg06a63b12013-01-20 14:27:21 +02002748 memset(&rp, 0, sizeof(rp));
2749 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2750 rp.addr.type = cp->addr.type;
2751
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002752 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002753 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2754 MGMT_STATUS_INVALID_PARAMS,
2755 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002756
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002757 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002758
2759 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002760 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2761 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002762 goto failed;
2763 }
2764
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002765 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002766 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2767 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002768 goto failed;
2769 }
2770
Andre Guedes591f47f2012-04-24 21:02:49 -03002771 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002772 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2773 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002774 else
2775 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002776
Vishal Agarwalf9607272012-06-13 05:32:43 +05302777 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002778 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2779 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002780 goto failed;
2781 }
2782
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002783 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002784 if (!cmd) {
2785 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002786 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002787 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002788
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002789 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002790 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002791
2792 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2793 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002794 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002795
2796failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002797 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002798 return err;
2799}
2800
Andre Guedes57c14772012-04-24 21:02:50 -03002801static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002802{
2803 switch (link_type) {
2804 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002805 switch (addr_type) {
2806 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002807 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002808
Johan Hedberg48264f02011-11-09 13:58:58 +02002809 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002810 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002811 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002812 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002813
Johan Hedberg4c659c32011-11-07 23:13:39 +02002814 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002815 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002816 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002817 }
2818}
2819
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002820static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2821 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002822{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002823 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002824 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002825 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002826 int err;
2827 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002828
2829 BT_DBG("");
2830
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002831 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002832
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002833 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002834 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002835 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002836 goto unlock;
2837 }
2838
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002839 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002840 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2841 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002842 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002843 }
2844
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002845 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002846 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002847 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002848 err = -ENOMEM;
2849 goto unlock;
2850 }
2851
Johan Hedberg2784eb42011-01-21 13:56:35 +02002852 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002853 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002854 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2855 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002856 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002857 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002858 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002859 continue;
2860 i++;
2861 }
2862
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002863 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002864
Johan Hedberg4c659c32011-11-07 23:13:39 +02002865 /* Recalculate length in case of filtered SCO connections, etc */
2866 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002867
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002868 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002869 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002870
Johan Hedberga38528f2011-01-22 06:46:43 +02002871 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002872
2873unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002874 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002875 return err;
2876}
2877
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002878static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002879 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002880{
2881 struct pending_cmd *cmd;
2882 int err;
2883
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002884 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002885 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002886 if (!cmd)
2887 return -ENOMEM;
2888
Johan Hedbergd8457692012-02-17 14:24:57 +02002889 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002890 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002891 if (err < 0)
2892 mgmt_pending_remove(cmd);
2893
2894 return err;
2895}
2896
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002897static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002898 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002899{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002900 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002901 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002902 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002903 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002904 int err;
2905
2906 BT_DBG("");
2907
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002908 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002909
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002910 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002911 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002912 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002913 goto failed;
2914 }
2915
Johan Hedbergd8457692012-02-17 14:24:57 +02002916 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002917 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002918 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002919 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002920 goto failed;
2921 }
2922
2923 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002924 struct mgmt_cp_pin_code_neg_reply ncp;
2925
2926 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002927
2928 BT_ERR("PIN code is not 16 bytes long");
2929
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002930 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002931 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002932 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002933 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002934
2935 goto failed;
2936 }
2937
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002938 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002939 if (!cmd) {
2940 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002941 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002942 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002943
Johan Hedbergd8457692012-02-17 14:24:57 +02002944 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002945 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002946 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002947
2948 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2949 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002950 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002951
2952failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002953 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002954 return err;
2955}
2956
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002957static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2958 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002959{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002960 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002961
2962 BT_DBG("");
2963
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002964 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2965 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2966 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002968 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002969
2970 hdev->io_capability = cp->io_capability;
2971
2972 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002973 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002974
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002975 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002976
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002977 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2978 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002979}
2980
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002981static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002982{
2983 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002984 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002985
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002986 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002987 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2988 continue;
2989
Johan Hedberge9a416b2011-02-19 12:05:56 -03002990 if (cmd->user_data != conn)
2991 continue;
2992
2993 return cmd;
2994 }
2995
2996 return NULL;
2997}
2998
2999static void pairing_complete(struct pending_cmd *cmd, u8 status)
3000{
3001 struct mgmt_rp_pair_device rp;
3002 struct hci_conn *conn = cmd->user_data;
3003
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003004 bacpy(&rp.addr.bdaddr, &conn->dst);
3005 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003006
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003007 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003008 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003009
3010 /* So we don't get further callbacks for this connection */
3011 conn->connect_cfm_cb = NULL;
3012 conn->security_cfm_cb = NULL;
3013 conn->disconn_cfm_cb = NULL;
3014
David Herrmann76a68ba2013-04-06 20:28:37 +02003015 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003016
Johan Hedberga664b5b2011-02-19 12:06:02 -03003017 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003018}
3019
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003020void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3021{
3022 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3023 struct pending_cmd *cmd;
3024
3025 cmd = find_pairing(conn);
3026 if (cmd)
3027 pairing_complete(cmd, status);
3028}
3029
Johan Hedberge9a416b2011-02-19 12:05:56 -03003030static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3031{
3032 struct pending_cmd *cmd;
3033
3034 BT_DBG("status %u", status);
3035
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003036 cmd = find_pairing(conn);
3037 if (!cmd)
3038 BT_DBG("Unable to find a pending command");
3039 else
Johan Hedberge2113262012-02-18 15:20:03 +02003040 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003041}
3042
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003043static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303044{
3045 struct pending_cmd *cmd;
3046
3047 BT_DBG("status %u", status);
3048
3049 if (!status)
3050 return;
3051
3052 cmd = find_pairing(conn);
3053 if (!cmd)
3054 BT_DBG("Unable to find a pending command");
3055 else
3056 pairing_complete(cmd, mgmt_status(status));
3057}
3058
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003059static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003060 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003061{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003062 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003063 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003064 struct pending_cmd *cmd;
3065 u8 sec_level, auth_type;
3066 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003067 int err;
3068
3069 BT_DBG("");
3070
Szymon Jancf950a30e2013-01-18 12:48:07 +01003071 memset(&rp, 0, sizeof(rp));
3072 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3073 rp.addr.type = cp->addr.type;
3074
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003075 if (!bdaddr_type_is_valid(cp->addr.type))
3076 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3077 MGMT_STATUS_INVALID_PARAMS,
3078 &rp, sizeof(rp));
3079
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003080 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3081 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3082 MGMT_STATUS_INVALID_PARAMS,
3083 &rp, sizeof(rp));
3084
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003085 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003086
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003087 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003088 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3089 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003090 goto unlock;
3091 }
3092
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003093 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003094 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003095
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003096 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003097 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3098 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003099 } else {
3100 u8 addr_type;
3101
3102 /* Convert from L2CAP channel address type to HCI address type
3103 */
3104 if (cp->addr.type == BDADDR_LE_PUBLIC)
3105 addr_type = ADDR_LE_DEV_PUBLIC;
3106 else
3107 addr_type = ADDR_LE_DEV_RANDOM;
3108
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003109 /* When pairing a new device, it is expected to remember
3110 * this device for future connections. Adding the connection
3111 * parameter information ahead of time allows tracking
3112 * of the slave preferred values and will speed up any
3113 * further connection establishment.
3114 *
3115 * If connection parameters already exist, then they
3116 * will be kept and this function does nothing.
3117 */
3118 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3119
Johan Hedbergcdd62752014-07-07 15:02:28 +03003120 /* Request a connection with master = true role */
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003121 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedbergcdd62752014-07-07 15:02:28 +03003122 sec_level, HCI_LE_CONN_TIMEOUT, true);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003123 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003124
Ville Tervo30e76272011-02-22 16:10:53 -03003125 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003126 int status;
3127
3128 if (PTR_ERR(conn) == -EBUSY)
3129 status = MGMT_STATUS_BUSY;
3130 else
3131 status = MGMT_STATUS_CONNECT_FAILED;
3132
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003133 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003134 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003135 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003136 goto unlock;
3137 }
3138
3139 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003140 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003141 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003142 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003143 goto unlock;
3144 }
3145
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003146 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003147 if (!cmd) {
3148 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003149 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003150 goto unlock;
3151 }
3152
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003153 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003154 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003155 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003156 conn->security_cfm_cb = pairing_complete_cb;
3157 conn->disconn_cfm_cb = pairing_complete_cb;
3158 } else {
3159 conn->connect_cfm_cb = le_pairing_complete_cb;
3160 conn->security_cfm_cb = le_pairing_complete_cb;
3161 conn->disconn_cfm_cb = le_pairing_complete_cb;
3162 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003163
Johan Hedberge9a416b2011-02-19 12:05:56 -03003164 conn->io_capability = cp->io_cap;
3165 cmd->user_data = conn;
3166
3167 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003168 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003169 pairing_complete(cmd, 0);
3170
3171 err = 0;
3172
3173unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003174 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003175 return err;
3176}
3177
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003178static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3179 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003180{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003181 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003182 struct pending_cmd *cmd;
3183 struct hci_conn *conn;
3184 int err;
3185
3186 BT_DBG("");
3187
Johan Hedberg28424702012-02-02 04:02:29 +02003188 hci_dev_lock(hdev);
3189
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003190 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003191 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003192 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003193 goto unlock;
3194 }
3195
Johan Hedberg28424702012-02-02 04:02:29 +02003196 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3197 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003198 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003199 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003200 goto unlock;
3201 }
3202
3203 conn = cmd->user_data;
3204
3205 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003206 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003207 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003208 goto unlock;
3209 }
3210
3211 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3212
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003213 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003214 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003215unlock:
3216 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003217 return err;
3218}
3219
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003220static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003221 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003222 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003223{
Johan Hedberga5c29682011-02-19 12:05:57 -03003224 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003225 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003226 int err;
3227
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003228 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003229
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003230 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003231 err = cmd_complete(sk, hdev->id, mgmt_op,
3232 MGMT_STATUS_NOT_POWERED, addr,
3233 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003234 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003235 }
3236
Johan Hedberg1707c602013-03-15 17:07:15 -05003237 if (addr->type == BDADDR_BREDR)
3238 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003239 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003240 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003241
Johan Hedberg272d90d2012-02-09 15:26:12 +02003242 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003243 err = cmd_complete(sk, hdev->id, mgmt_op,
3244 MGMT_STATUS_NOT_CONNECTED, addr,
3245 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003246 goto done;
3247 }
3248
Johan Hedberg1707c602013-03-15 17:07:15 -05003249 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003250 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003251 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003252 err = cmd_complete(sk, hdev->id, mgmt_op,
3253 MGMT_STATUS_SUCCESS, addr,
3254 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003255 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003256 err = cmd_complete(sk, hdev->id, mgmt_op,
3257 MGMT_STATUS_FAILED, addr,
3258 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003259
Brian Gix47c15e22011-11-16 13:53:14 -08003260 goto done;
3261 }
3262
Johan Hedberg1707c602013-03-15 17:07:15 -05003263 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003264 if (!cmd) {
3265 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003266 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003267 }
3268
Brian Gix0df4c182011-11-16 13:53:13 -08003269 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003270 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3271 struct hci_cp_user_passkey_reply cp;
3272
Johan Hedberg1707c602013-03-15 17:07:15 -05003273 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003274 cp.passkey = passkey;
3275 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3276 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003277 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3278 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003279
Johan Hedberga664b5b2011-02-19 12:06:02 -03003280 if (err < 0)
3281 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003282
Brian Gix0df4c182011-11-16 13:53:13 -08003283done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003284 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003285 return err;
3286}
3287
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303288static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3289 void *data, u16 len)
3290{
3291 struct mgmt_cp_pin_code_neg_reply *cp = data;
3292
3293 BT_DBG("");
3294
Johan Hedberg1707c602013-03-15 17:07:15 -05003295 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303296 MGMT_OP_PIN_CODE_NEG_REPLY,
3297 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3298}
3299
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003300static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3301 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003302{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003303 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003304
3305 BT_DBG("");
3306
3307 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003308 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003309 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003310
Johan Hedberg1707c602013-03-15 17:07:15 -05003311 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003312 MGMT_OP_USER_CONFIRM_REPLY,
3313 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003314}
3315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003316static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003317 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003318{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003319 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003320
3321 BT_DBG("");
3322
Johan Hedberg1707c602013-03-15 17:07:15 -05003323 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003324 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3325 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003326}
3327
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003328static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3329 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003330{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003331 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003332
3333 BT_DBG("");
3334
Johan Hedberg1707c602013-03-15 17:07:15 -05003335 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003336 MGMT_OP_USER_PASSKEY_REPLY,
3337 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003338}
3339
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003340static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003341 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003342{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003343 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003344
3345 BT_DBG("");
3346
Johan Hedberg1707c602013-03-15 17:07:15 -05003347 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003348 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3349 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003350}
3351
Johan Hedberg13928972013-03-15 17:07:00 -05003352static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003353{
Johan Hedberg13928972013-03-15 17:07:00 -05003354 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003355 struct hci_cp_write_local_name cp;
3356
Johan Hedberg13928972013-03-15 17:07:00 -05003357 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003358
Johan Hedberg890ea892013-03-15 17:06:52 -05003359 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003360}
3361
Johan Hedberg13928972013-03-15 17:07:00 -05003362static void set_name_complete(struct hci_dev *hdev, u8 status)
3363{
3364 struct mgmt_cp_set_local_name *cp;
3365 struct pending_cmd *cmd;
3366
3367 BT_DBG("status 0x%02x", status);
3368
3369 hci_dev_lock(hdev);
3370
3371 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3372 if (!cmd)
3373 goto unlock;
3374
3375 cp = cmd->param;
3376
3377 if (status)
3378 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3379 mgmt_status(status));
3380 else
3381 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3382 cp, sizeof(*cp));
3383
3384 mgmt_pending_remove(cmd);
3385
3386unlock:
3387 hci_dev_unlock(hdev);
3388}
3389
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003390static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003391 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003392{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003393 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003394 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003395 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003396 int err;
3397
3398 BT_DBG("");
3399
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003400 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003401
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003402 /* If the old values are the same as the new ones just return a
3403 * direct command complete event.
3404 */
3405 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3406 !memcmp(hdev->short_name, cp->short_name,
3407 sizeof(hdev->short_name))) {
3408 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3409 data, len);
3410 goto failed;
3411 }
3412
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003413 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003414
Johan Hedbergb5235a62012-02-21 14:32:24 +02003415 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003416 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003417
3418 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003419 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003420 if (err < 0)
3421 goto failed;
3422
3423 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003424 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003425
Johan Hedbergb5235a62012-02-21 14:32:24 +02003426 goto failed;
3427 }
3428
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003429 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003430 if (!cmd) {
3431 err = -ENOMEM;
3432 goto failed;
3433 }
3434
Johan Hedberg13928972013-03-15 17:07:00 -05003435 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3436
Johan Hedberg890ea892013-03-15 17:06:52 -05003437 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003438
3439 if (lmp_bredr_capable(hdev)) {
3440 update_name(&req);
3441 update_eir(&req);
3442 }
3443
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003444 /* The name is stored in the scan response data and so
3445 * no need to udpate the advertising data here.
3446 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003447 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003448 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003449
Johan Hedberg13928972013-03-15 17:07:00 -05003450 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003451 if (err < 0)
3452 mgmt_pending_remove(cmd);
3453
3454failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003455 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003456 return err;
3457}
3458
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003459static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003460 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003461{
Szymon Jancc35938b2011-03-22 13:12:21 +01003462 struct pending_cmd *cmd;
3463 int err;
3464
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003465 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003466
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003467 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003468
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003469 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003470 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003471 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003472 goto unlock;
3473 }
3474
Andre Guedes9a1a1992012-07-24 15:03:48 -03003475 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003476 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003477 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003478 goto unlock;
3479 }
3480
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003481 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003483 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003484 goto unlock;
3485 }
3486
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003487 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003488 if (!cmd) {
3489 err = -ENOMEM;
3490 goto unlock;
3491 }
3492
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003493 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3494 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3495 0, NULL);
3496 else
3497 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3498
Szymon Jancc35938b2011-03-22 13:12:21 +01003499 if (err < 0)
3500 mgmt_pending_remove(cmd);
3501
3502unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003503 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003504 return err;
3505}
3506
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003507static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003508 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003509{
Szymon Janc2763eda2011-03-22 13:12:22 +01003510 int err;
3511
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003512 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003513
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003514 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003515
Marcel Holtmannec109112014-01-10 02:07:30 -08003516 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3517 struct mgmt_cp_add_remote_oob_data *cp = data;
3518 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003519
Marcel Holtmannec109112014-01-10 02:07:30 -08003520 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3521 cp->hash, cp->randomizer);
3522 if (err < 0)
3523 status = MGMT_STATUS_FAILED;
3524 else
3525 status = MGMT_STATUS_SUCCESS;
3526
3527 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3528 status, &cp->addr, sizeof(cp->addr));
3529 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3530 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3531 u8 status;
3532
3533 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3534 cp->hash192,
3535 cp->randomizer192,
3536 cp->hash256,
3537 cp->randomizer256);
3538 if (err < 0)
3539 status = MGMT_STATUS_FAILED;
3540 else
3541 status = MGMT_STATUS_SUCCESS;
3542
3543 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3544 status, &cp->addr, sizeof(cp->addr));
3545 } else {
3546 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3547 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3548 MGMT_STATUS_INVALID_PARAMS);
3549 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003550
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003551 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003552 return err;
3553}
3554
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003555static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003556 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003557{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003558 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003559 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003560 int err;
3561
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003562 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003563
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003564 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003565
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003566 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003567 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003568 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003569 else
Szymon Janca6785be2012-12-13 15:11:21 +01003570 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003571
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003572 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003573 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003574
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003575 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003576 return err;
3577}
3578
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003579static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3580{
3581 struct pending_cmd *cmd;
3582 u8 type;
3583 int err;
3584
3585 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3586
3587 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3588 if (!cmd)
3589 return -ENOENT;
3590
3591 type = hdev->discovery.type;
3592
3593 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3594 &type, sizeof(type));
3595 mgmt_pending_remove(cmd);
3596
3597 return err;
3598}
3599
Andre Guedes7c307722013-04-30 15:29:28 -03003600static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3601{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003602 unsigned long timeout = 0;
3603
Andre Guedes7c307722013-04-30 15:29:28 -03003604 BT_DBG("status %d", status);
3605
3606 if (status) {
3607 hci_dev_lock(hdev);
3608 mgmt_start_discovery_failed(hdev, status);
3609 hci_dev_unlock(hdev);
3610 return;
3611 }
3612
3613 hci_dev_lock(hdev);
3614 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3615 hci_dev_unlock(hdev);
3616
3617 switch (hdev->discovery.type) {
3618 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003619 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003620 break;
3621
3622 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003623 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003624 break;
3625
3626 case DISCOV_TYPE_BREDR:
3627 break;
3628
3629 default:
3630 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3631 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003632
3633 if (!timeout)
3634 return;
3635
3636 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003637}
3638
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003639static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003640 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003641{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003642 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003643 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003644 struct hci_cp_le_set_scan_param param_cp;
3645 struct hci_cp_le_set_scan_enable enable_cp;
3646 struct hci_cp_inquiry inq_cp;
3647 struct hci_request req;
3648 /* General inquiry access code (GIAC) */
3649 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003650 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003651 int err;
3652
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003653 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003654
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003655 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003656
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003657 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003658 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003659 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003660 goto failed;
3661 }
3662
Andre Guedes642be6c2012-03-21 00:03:37 -03003663 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3664 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3665 MGMT_STATUS_BUSY);
3666 goto failed;
3667 }
3668
Johan Hedbergff9ef572012-01-04 14:23:45 +02003669 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003670 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003671 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003672 goto failed;
3673 }
3674
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003675 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003676 if (!cmd) {
3677 err = -ENOMEM;
3678 goto failed;
3679 }
3680
Andre Guedes4aab14e2012-02-17 20:39:36 -03003681 hdev->discovery.type = cp->type;
3682
Andre Guedes7c307722013-04-30 15:29:28 -03003683 hci_req_init(&req, hdev);
3684
Andre Guedes4aab14e2012-02-17 20:39:36 -03003685 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003686 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003687 status = mgmt_bredr_support(hdev);
3688 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003689 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003690 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003691 mgmt_pending_remove(cmd);
3692 goto failed;
3693 }
3694
Andre Guedes7c307722013-04-30 15:29:28 -03003695 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3696 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3697 MGMT_STATUS_BUSY);
3698 mgmt_pending_remove(cmd);
3699 goto failed;
3700 }
3701
3702 hci_inquiry_cache_flush(hdev);
3703
3704 memset(&inq_cp, 0, sizeof(inq_cp));
3705 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003706 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003707 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003708 break;
3709
3710 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003711 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003712 status = mgmt_le_support(hdev);
3713 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003714 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003715 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003716 mgmt_pending_remove(cmd);
3717 goto failed;
3718 }
3719
Andre Guedes7c307722013-04-30 15:29:28 -03003720 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003721 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003722 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3723 MGMT_STATUS_NOT_SUPPORTED);
3724 mgmt_pending_remove(cmd);
3725 goto failed;
3726 }
3727
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003728 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003729 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3730 MGMT_STATUS_REJECTED);
3731 mgmt_pending_remove(cmd);
3732 goto failed;
3733 }
3734
Andre Guedesc54c3862014-02-26 20:21:50 -03003735 /* If controller is scanning, it means the background scanning
3736 * is running. Thus, we should temporarily stop it in order to
3737 * set the discovery scanning parameters.
3738 */
3739 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3740 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003741
3742 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003743
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003744 /* All active scans will be done with either a resolvable
3745 * private address (when privacy feature has been enabled)
3746 * or unresolvable private address.
3747 */
3748 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003749 if (err < 0) {
3750 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3751 MGMT_STATUS_FAILED);
3752 mgmt_pending_remove(cmd);
3753 goto failed;
3754 }
3755
Andre Guedes7c307722013-04-30 15:29:28 -03003756 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003757 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3758 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003759 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003760 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3761 &param_cp);
3762
3763 memset(&enable_cp, 0, sizeof(enable_cp));
3764 enable_cp.enable = LE_SCAN_ENABLE;
3765 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3766 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3767 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003768 break;
3769
Andre Guedesf39799f2012-02-17 20:39:35 -03003770 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003771 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3772 MGMT_STATUS_INVALID_PARAMS);
3773 mgmt_pending_remove(cmd);
3774 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003775 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003776
Andre Guedes7c307722013-04-30 15:29:28 -03003777 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003778 if (err < 0)
3779 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003780 else
3781 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003782
3783failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003784 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003785 return err;
3786}
3787
Andre Guedes1183fdc2013-04-30 15:29:35 -03003788static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3789{
3790 struct pending_cmd *cmd;
3791 int err;
3792
3793 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3794 if (!cmd)
3795 return -ENOENT;
3796
3797 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3798 &hdev->discovery.type, sizeof(hdev->discovery.type));
3799 mgmt_pending_remove(cmd);
3800
3801 return err;
3802}
3803
Andre Guedes0e05bba2013-04-30 15:29:33 -03003804static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3805{
3806 BT_DBG("status %d", status);
3807
3808 hci_dev_lock(hdev);
3809
3810 if (status) {
3811 mgmt_stop_discovery_failed(hdev, status);
3812 goto unlock;
3813 }
3814
3815 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3816
3817unlock:
3818 hci_dev_unlock(hdev);
3819}
3820
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003821static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003822 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003823{
Johan Hedbergd9306502012-02-20 23:25:18 +02003824 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003825 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003826 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003827 int err;
3828
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003829 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003830
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003831 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003832
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003833 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003834 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003835 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3836 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003837 goto unlock;
3838 }
3839
3840 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003841 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003842 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3843 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003844 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003845 }
3846
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003847 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003848 if (!cmd) {
3849 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003850 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003851 }
3852
Andre Guedes0e05bba2013-04-30 15:29:33 -03003853 hci_req_init(&req, hdev);
3854
Johan Hedberg21a60d32014-06-10 14:05:58 +03003855 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003856
Johan Hedberg21a60d32014-06-10 14:05:58 +03003857 err = hci_req_run(&req, stop_discovery_complete);
3858 if (!err) {
3859 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003860 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003861 }
3862
Johan Hedberg21a60d32014-06-10 14:05:58 +03003863 mgmt_pending_remove(cmd);
3864
3865 /* If no HCI commands were sent we're done */
3866 if (err == -ENODATA) {
3867 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3868 &mgmt_cp->type, sizeof(mgmt_cp->type));
3869 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3870 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003871
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003872unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003873 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003874 return err;
3875}
3876
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003877static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003878 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003879{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003880 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003881 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003882 int err;
3883
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003884 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003885
Johan Hedberg561aafb2012-01-04 13:31:59 +02003886 hci_dev_lock(hdev);
3887
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003888 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003889 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3890 MGMT_STATUS_FAILED, &cp->addr,
3891 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003892 goto failed;
3893 }
3894
Johan Hedberga198e7b2012-02-17 14:27:06 +02003895 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003896 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003897 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3898 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3899 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003900 goto failed;
3901 }
3902
3903 if (cp->name_known) {
3904 e->name_state = NAME_KNOWN;
3905 list_del(&e->list);
3906 } else {
3907 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003908 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003909 }
3910
Johan Hedberge3846622013-01-09 15:29:33 +02003911 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3912 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003913
3914failed:
3915 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003916 return err;
3917}
3918
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003919static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003920 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003921{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003922 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003923 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003924 int err;
3925
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003926 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003927
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003928 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003929 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3930 MGMT_STATUS_INVALID_PARAMS,
3931 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003932
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003933 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003934
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003935 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003936 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003937 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003938 goto done;
3939 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003940
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003941 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3942 sk);
3943 status = MGMT_STATUS_SUCCESS;
3944
3945done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003946 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003947 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003948
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003949 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003950
3951 return err;
3952}
3953
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003954static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003955 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003956{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003957 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003958 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003959 int err;
3960
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003961 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003962
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003963 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003964 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3965 MGMT_STATUS_INVALID_PARAMS,
3966 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003968 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003969
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003970 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003971 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003972 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003973 goto done;
3974 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003975
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003976 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3977 sk);
3978 status = MGMT_STATUS_SUCCESS;
3979
3980done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003981 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003982 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003983
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003984 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003985
3986 return err;
3987}
3988
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003989static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3990 u16 len)
3991{
3992 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003993 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003994 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003995 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003996
3997 BT_DBG("%s", hdev->name);
3998
Szymon Jancc72d4b82012-03-16 16:02:57 +01003999 source = __le16_to_cpu(cp->source);
4000
4001 if (source > 0x0002)
4002 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4003 MGMT_STATUS_INVALID_PARAMS);
4004
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004005 hci_dev_lock(hdev);
4006
Szymon Jancc72d4b82012-03-16 16:02:57 +01004007 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004008 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4009 hdev->devid_product = __le16_to_cpu(cp->product);
4010 hdev->devid_version = __le16_to_cpu(cp->version);
4011
4012 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4013
Johan Hedberg890ea892013-03-15 17:06:52 -05004014 hci_req_init(&req, hdev);
4015 update_eir(&req);
4016 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004017
4018 hci_dev_unlock(hdev);
4019
4020 return err;
4021}
4022
Johan Hedberg4375f102013-09-25 13:26:10 +03004023static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4024{
4025 struct cmd_lookup match = { NULL, hdev };
4026
4027 if (status) {
4028 u8 mgmt_err = mgmt_status(status);
4029
4030 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4031 cmd_status_rsp, &mgmt_err);
4032 return;
4033 }
4034
4035 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4036 &match);
4037
4038 new_settings(hdev, match.sk);
4039
4040 if (match.sk)
4041 sock_put(match.sk);
4042}
4043
Marcel Holtmann21b51872013-10-10 09:47:53 -07004044static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4045 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004046{
4047 struct mgmt_mode *cp = data;
4048 struct pending_cmd *cmd;
4049 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004050 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004051 int err;
4052
4053 BT_DBG("request for %s", hdev->name);
4054
Johan Hedberge6fe7982013-10-02 15:45:22 +03004055 status = mgmt_le_support(hdev);
4056 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004057 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004058 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004059
4060 if (cp->val != 0x00 && cp->val != 0x01)
4061 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4062 MGMT_STATUS_INVALID_PARAMS);
4063
4064 hci_dev_lock(hdev);
4065
4066 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004067 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004068
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004069 /* The following conditions are ones which mean that we should
4070 * not do any HCI communication but directly send a mgmt
4071 * response to user space (after toggling the flag if
4072 * necessary).
4073 */
4074 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004075 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004076 bool changed = false;
4077
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004078 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4079 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004080 changed = true;
4081 }
4082
4083 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4084 if (err < 0)
4085 goto unlock;
4086
4087 if (changed)
4088 err = new_settings(hdev, sk);
4089
4090 goto unlock;
4091 }
4092
4093 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4094 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4095 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4096 MGMT_STATUS_BUSY);
4097 goto unlock;
4098 }
4099
4100 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4101 if (!cmd) {
4102 err = -ENOMEM;
4103 goto unlock;
4104 }
4105
4106 hci_req_init(&req, hdev);
4107
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004108 if (val)
4109 enable_advertising(&req);
4110 else
4111 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004112
4113 err = hci_req_run(&req, set_advertising_complete);
4114 if (err < 0)
4115 mgmt_pending_remove(cmd);
4116
4117unlock:
4118 hci_dev_unlock(hdev);
4119 return err;
4120}
4121
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004122static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4123 void *data, u16 len)
4124{
4125 struct mgmt_cp_set_static_address *cp = data;
4126 int err;
4127
4128 BT_DBG("%s", hdev->name);
4129
Marcel Holtmann62af4442013-10-02 22:10:32 -07004130 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004131 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004132 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004133
4134 if (hdev_is_powered(hdev))
4135 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4136 MGMT_STATUS_REJECTED);
4137
4138 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4139 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4140 return cmd_status(sk, hdev->id,
4141 MGMT_OP_SET_STATIC_ADDRESS,
4142 MGMT_STATUS_INVALID_PARAMS);
4143
4144 /* Two most significant bits shall be set */
4145 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4146 return cmd_status(sk, hdev->id,
4147 MGMT_OP_SET_STATIC_ADDRESS,
4148 MGMT_STATUS_INVALID_PARAMS);
4149 }
4150
4151 hci_dev_lock(hdev);
4152
4153 bacpy(&hdev->static_addr, &cp->bdaddr);
4154
4155 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4156
4157 hci_dev_unlock(hdev);
4158
4159 return err;
4160}
4161
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004162static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4163 void *data, u16 len)
4164{
4165 struct mgmt_cp_set_scan_params *cp = data;
4166 __u16 interval, window;
4167 int err;
4168
4169 BT_DBG("%s", hdev->name);
4170
4171 if (!lmp_le_capable(hdev))
4172 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4173 MGMT_STATUS_NOT_SUPPORTED);
4174
4175 interval = __le16_to_cpu(cp->interval);
4176
4177 if (interval < 0x0004 || interval > 0x4000)
4178 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4179 MGMT_STATUS_INVALID_PARAMS);
4180
4181 window = __le16_to_cpu(cp->window);
4182
4183 if (window < 0x0004 || window > 0x4000)
4184 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4185 MGMT_STATUS_INVALID_PARAMS);
4186
Marcel Holtmann899e1072013-10-14 09:55:32 -07004187 if (window > interval)
4188 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4189 MGMT_STATUS_INVALID_PARAMS);
4190
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004191 hci_dev_lock(hdev);
4192
4193 hdev->le_scan_interval = interval;
4194 hdev->le_scan_window = window;
4195
4196 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4197
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004198 /* If background scan is running, restart it so new parameters are
4199 * loaded.
4200 */
4201 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4202 hdev->discovery.state == DISCOVERY_STOPPED) {
4203 struct hci_request req;
4204
4205 hci_req_init(&req, hdev);
4206
4207 hci_req_add_le_scan_disable(&req);
4208 hci_req_add_le_passive_scan(&req);
4209
4210 hci_req_run(&req, NULL);
4211 }
4212
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004213 hci_dev_unlock(hdev);
4214
4215 return err;
4216}
4217
Johan Hedberg33e38b32013-03-15 17:07:05 -05004218static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4219{
4220 struct pending_cmd *cmd;
4221
4222 BT_DBG("status 0x%02x", status);
4223
4224 hci_dev_lock(hdev);
4225
4226 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4227 if (!cmd)
4228 goto unlock;
4229
4230 if (status) {
4231 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4232 mgmt_status(status));
4233 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004234 struct mgmt_mode *cp = cmd->param;
4235
4236 if (cp->val)
4237 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4238 else
4239 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4240
Johan Hedberg33e38b32013-03-15 17:07:05 -05004241 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4242 new_settings(hdev, cmd->sk);
4243 }
4244
4245 mgmt_pending_remove(cmd);
4246
4247unlock:
4248 hci_dev_unlock(hdev);
4249}
4250
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004251static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004252 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004253{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004254 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004255 struct pending_cmd *cmd;
4256 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004257 int err;
4258
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004259 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004260
Johan Hedberg56f87902013-10-02 13:43:13 +03004261 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4262 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004263 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4264 MGMT_STATUS_NOT_SUPPORTED);
4265
Johan Hedberga7e80f22013-01-09 16:05:19 +02004266 if (cp->val != 0x00 && cp->val != 0x01)
4267 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4268 MGMT_STATUS_INVALID_PARAMS);
4269
Johan Hedberg5400c042012-02-21 16:40:33 +02004270 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004271 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004272 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004273
4274 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004275 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004276 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004277
4278 hci_dev_lock(hdev);
4279
Johan Hedberg05cbf292013-03-15 17:07:07 -05004280 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4281 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4282 MGMT_STATUS_BUSY);
4283 goto unlock;
4284 }
4285
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004286 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4287 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4288 hdev);
4289 goto unlock;
4290 }
4291
Johan Hedberg33e38b32013-03-15 17:07:05 -05004292 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4293 data, len);
4294 if (!cmd) {
4295 err = -ENOMEM;
4296 goto unlock;
4297 }
4298
4299 hci_req_init(&req, hdev);
4300
Johan Hedberg406d7802013-03-15 17:07:09 -05004301 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004302
4303 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004304 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004305 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004306 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004307 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004308 }
4309
Johan Hedberg33e38b32013-03-15 17:07:05 -05004310unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004311 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004312
Antti Julkuf6422ec2011-06-22 13:11:56 +03004313 return err;
4314}
4315
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004316static void set_bredr_scan(struct hci_request *req)
4317{
4318 struct hci_dev *hdev = req->hdev;
4319 u8 scan = 0;
4320
4321 /* Ensure that fast connectable is disabled. This function will
4322 * not do anything if the page scan parameters are already what
4323 * they should be.
4324 */
4325 write_fast_connectable(req, false);
4326
4327 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4328 scan |= SCAN_PAGE;
4329 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4330 scan |= SCAN_INQUIRY;
4331
4332 if (scan)
4333 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4334}
4335
Johan Hedberg0663ca22013-10-02 13:43:14 +03004336static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4337{
4338 struct pending_cmd *cmd;
4339
4340 BT_DBG("status 0x%02x", status);
4341
4342 hci_dev_lock(hdev);
4343
4344 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4345 if (!cmd)
4346 goto unlock;
4347
4348 if (status) {
4349 u8 mgmt_err = mgmt_status(status);
4350
4351 /* We need to restore the flag if related HCI commands
4352 * failed.
4353 */
4354 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4355
4356 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4357 } else {
4358 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4359 new_settings(hdev, cmd->sk);
4360 }
4361
4362 mgmt_pending_remove(cmd);
4363
4364unlock:
4365 hci_dev_unlock(hdev);
4366}
4367
4368static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4369{
4370 struct mgmt_mode *cp = data;
4371 struct pending_cmd *cmd;
4372 struct hci_request req;
4373 int err;
4374
4375 BT_DBG("request for %s", hdev->name);
4376
4377 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4378 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4379 MGMT_STATUS_NOT_SUPPORTED);
4380
4381 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4382 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4383 MGMT_STATUS_REJECTED);
4384
4385 if (cp->val != 0x00 && cp->val != 0x01)
4386 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4387 MGMT_STATUS_INVALID_PARAMS);
4388
4389 hci_dev_lock(hdev);
4390
4391 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4392 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4393 goto unlock;
4394 }
4395
4396 if (!hdev_is_powered(hdev)) {
4397 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004398 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4399 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4400 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4401 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4402 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4403 }
4404
4405 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4406
4407 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4408 if (err < 0)
4409 goto unlock;
4410
4411 err = new_settings(hdev, sk);
4412 goto unlock;
4413 }
4414
4415 /* Reject disabling when powered on */
4416 if (!cp->val) {
4417 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4418 MGMT_STATUS_REJECTED);
4419 goto unlock;
4420 }
4421
4422 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4423 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4424 MGMT_STATUS_BUSY);
4425 goto unlock;
4426 }
4427
4428 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4429 if (!cmd) {
4430 err = -ENOMEM;
4431 goto unlock;
4432 }
4433
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004434 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004435 * generates the correct flags.
4436 */
4437 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4438
4439 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004440
4441 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4442 set_bredr_scan(&req);
4443
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004444 /* Since only the advertising data flags will change, there
4445 * is no need to update the scan response data.
4446 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004447 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004448
Johan Hedberg0663ca22013-10-02 13:43:14 +03004449 err = hci_req_run(&req, set_bredr_complete);
4450 if (err < 0)
4451 mgmt_pending_remove(cmd);
4452
4453unlock:
4454 hci_dev_unlock(hdev);
4455 return err;
4456}
4457
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004458static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4459 void *data, u16 len)
4460{
4461 struct mgmt_mode *cp = data;
4462 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004463 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004464 int err;
4465
4466 BT_DBG("request for %s", hdev->name);
4467
4468 status = mgmt_bredr_support(hdev);
4469 if (status)
4470 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4471 status);
4472
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004473 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004474 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004475 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4476 MGMT_STATUS_NOT_SUPPORTED);
4477
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004478 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004479 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4480 MGMT_STATUS_INVALID_PARAMS);
4481
4482 hci_dev_lock(hdev);
4483
4484 if (!hdev_is_powered(hdev)) {
4485 bool changed;
4486
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004487 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004488 changed = !test_and_set_bit(HCI_SC_ENABLED,
4489 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004490 if (cp->val == 0x02)
4491 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4492 else
4493 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4494 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004495 changed = test_and_clear_bit(HCI_SC_ENABLED,
4496 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004497 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4498 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004499
4500 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4501 if (err < 0)
4502 goto failed;
4503
4504 if (changed)
4505 err = new_settings(hdev, sk);
4506
4507 goto failed;
4508 }
4509
4510 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4511 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4512 MGMT_STATUS_BUSY);
4513 goto failed;
4514 }
4515
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004516 val = !!cp->val;
4517
4518 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4519 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004520 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4521 goto failed;
4522 }
4523
4524 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4525 if (!cmd) {
4526 err = -ENOMEM;
4527 goto failed;
4528 }
4529
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004530 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004531 if (err < 0) {
4532 mgmt_pending_remove(cmd);
4533 goto failed;
4534 }
4535
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004536 if (cp->val == 0x02)
4537 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4538 else
4539 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4540
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004541failed:
4542 hci_dev_unlock(hdev);
4543 return err;
4544}
4545
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004546static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4547 void *data, u16 len)
4548{
4549 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004550 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004551 int err;
4552
4553 BT_DBG("request for %s", hdev->name);
4554
Johan Hedbergb97109792014-06-24 14:00:28 +03004555 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004556 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4557 MGMT_STATUS_INVALID_PARAMS);
4558
4559 hci_dev_lock(hdev);
4560
4561 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004562 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4563 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004564 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004565 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4566 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004567
Johan Hedbergb97109792014-06-24 14:00:28 +03004568 if (cp->val == 0x02)
4569 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4570 &hdev->dev_flags);
4571 else
4572 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4573 &hdev->dev_flags);
4574
4575 if (hdev_is_powered(hdev) && use_changed &&
4576 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4577 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4578 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4579 sizeof(mode), &mode);
4580 }
4581
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004582 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4583 if (err < 0)
4584 goto unlock;
4585
4586 if (changed)
4587 err = new_settings(hdev, sk);
4588
4589unlock:
4590 hci_dev_unlock(hdev);
4591 return err;
4592}
4593
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004594static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4595 u16 len)
4596{
4597 struct mgmt_cp_set_privacy *cp = cp_data;
4598 bool changed;
4599 int err;
4600
4601 BT_DBG("request for %s", hdev->name);
4602
4603 if (!lmp_le_capable(hdev))
4604 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4605 MGMT_STATUS_NOT_SUPPORTED);
4606
4607 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4608 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4609 MGMT_STATUS_INVALID_PARAMS);
4610
4611 if (hdev_is_powered(hdev))
4612 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4613 MGMT_STATUS_REJECTED);
4614
4615 hci_dev_lock(hdev);
4616
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004617 /* If user space supports this command it is also expected to
4618 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4619 */
4620 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4621
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004622 if (cp->privacy) {
4623 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4624 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4625 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4626 } else {
4627 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4628 memset(hdev->irk, 0, sizeof(hdev->irk));
4629 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4630 }
4631
4632 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4633 if (err < 0)
4634 goto unlock;
4635
4636 if (changed)
4637 err = new_settings(hdev, sk);
4638
4639unlock:
4640 hci_dev_unlock(hdev);
4641 return err;
4642}
4643
Johan Hedberg41edf162014-02-18 10:19:35 +02004644static bool irk_is_valid(struct mgmt_irk_info *irk)
4645{
4646 switch (irk->addr.type) {
4647 case BDADDR_LE_PUBLIC:
4648 return true;
4649
4650 case BDADDR_LE_RANDOM:
4651 /* Two most significant bits shall be set */
4652 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4653 return false;
4654 return true;
4655 }
4656
4657 return false;
4658}
4659
4660static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4661 u16 len)
4662{
4663 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004664 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4665 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004666 u16 irk_count, expected_len;
4667 int i, err;
4668
4669 BT_DBG("request for %s", hdev->name);
4670
4671 if (!lmp_le_capable(hdev))
4672 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4673 MGMT_STATUS_NOT_SUPPORTED);
4674
4675 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004676 if (irk_count > max_irk_count) {
4677 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4678 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4679 MGMT_STATUS_INVALID_PARAMS);
4680 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004681
4682 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4683 if (expected_len != len) {
4684 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004685 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004686 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4687 MGMT_STATUS_INVALID_PARAMS);
4688 }
4689
4690 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4691
4692 for (i = 0; i < irk_count; i++) {
4693 struct mgmt_irk_info *key = &cp->irks[i];
4694
4695 if (!irk_is_valid(key))
4696 return cmd_status(sk, hdev->id,
4697 MGMT_OP_LOAD_IRKS,
4698 MGMT_STATUS_INVALID_PARAMS);
4699 }
4700
4701 hci_dev_lock(hdev);
4702
4703 hci_smp_irks_clear(hdev);
4704
4705 for (i = 0; i < irk_count; i++) {
4706 struct mgmt_irk_info *irk = &cp->irks[i];
4707 u8 addr_type;
4708
4709 if (irk->addr.type == BDADDR_LE_PUBLIC)
4710 addr_type = ADDR_LE_DEV_PUBLIC;
4711 else
4712 addr_type = ADDR_LE_DEV_RANDOM;
4713
4714 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4715 BDADDR_ANY);
4716 }
4717
4718 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4719
4720 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4721
4722 hci_dev_unlock(hdev);
4723
4724 return err;
4725}
4726
Johan Hedberg3f706b72013-01-20 14:27:16 +02004727static bool ltk_is_valid(struct mgmt_ltk_info *key)
4728{
4729 if (key->master != 0x00 && key->master != 0x01)
4730 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004731
4732 switch (key->addr.type) {
4733 case BDADDR_LE_PUBLIC:
4734 return true;
4735
4736 case BDADDR_LE_RANDOM:
4737 /* Two most significant bits shall be set */
4738 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4739 return false;
4740 return true;
4741 }
4742
4743 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004744}
4745
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004746static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004747 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004748{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004749 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004750 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4751 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004752 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004753 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004754
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004755 BT_DBG("request for %s", hdev->name);
4756
4757 if (!lmp_le_capable(hdev))
4758 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4759 MGMT_STATUS_NOT_SUPPORTED);
4760
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004761 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004762 if (key_count > max_key_count) {
4763 BT_ERR("load_ltks: too big key_count value %u", key_count);
4764 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4765 MGMT_STATUS_INVALID_PARAMS);
4766 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004767
4768 expected_len = sizeof(*cp) + key_count *
4769 sizeof(struct mgmt_ltk_info);
4770 if (expected_len != len) {
4771 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004772 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004773 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004774 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004775 }
4776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004777 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004778
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004779 for (i = 0; i < key_count; i++) {
4780 struct mgmt_ltk_info *key = &cp->keys[i];
4781
Johan Hedberg3f706b72013-01-20 14:27:16 +02004782 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004783 return cmd_status(sk, hdev->id,
4784 MGMT_OP_LOAD_LONG_TERM_KEYS,
4785 MGMT_STATUS_INVALID_PARAMS);
4786 }
4787
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004788 hci_dev_lock(hdev);
4789
4790 hci_smp_ltks_clear(hdev);
4791
4792 for (i = 0; i < key_count; i++) {
4793 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004794 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004795
4796 if (key->addr.type == BDADDR_LE_PUBLIC)
4797 addr_type = ADDR_LE_DEV_PUBLIC;
4798 else
4799 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004800
4801 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004802 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004803 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004804 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004805
Johan Hedberg61b43352014-05-29 19:36:53 +03004806 switch (key->type) {
4807 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004808 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004809 break;
4810 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004811 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004812 break;
4813 default:
4814 continue;
4815 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004816
Johan Hedberg35d70272014-02-19 14:57:47 +02004817 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004818 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004819 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004820 }
4821
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004822 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4823 NULL, 0);
4824
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004825 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004826
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004827 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004828}
4829
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004830struct cmd_conn_lookup {
4831 struct hci_conn *conn;
4832 bool valid_tx_power;
4833 u8 mgmt_status;
4834};
4835
4836static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4837{
4838 struct cmd_conn_lookup *match = data;
4839 struct mgmt_cp_get_conn_info *cp;
4840 struct mgmt_rp_get_conn_info rp;
4841 struct hci_conn *conn = cmd->user_data;
4842
4843 if (conn != match->conn)
4844 return;
4845
4846 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4847
4848 memset(&rp, 0, sizeof(rp));
4849 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4850 rp.addr.type = cp->addr.type;
4851
4852 if (!match->mgmt_status) {
4853 rp.rssi = conn->rssi;
4854
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004855 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004856 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004857 rp.max_tx_power = conn->max_tx_power;
4858 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004859 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004860 rp.max_tx_power = HCI_TX_POWER_INVALID;
4861 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004862 }
4863
4864 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4865 match->mgmt_status, &rp, sizeof(rp));
4866
4867 hci_conn_drop(conn);
4868
4869 mgmt_pending_remove(cmd);
4870}
4871
4872static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4873{
4874 struct hci_cp_read_rssi *cp;
4875 struct hci_conn *conn;
4876 struct cmd_conn_lookup match;
4877 u16 handle;
4878
4879 BT_DBG("status 0x%02x", status);
4880
4881 hci_dev_lock(hdev);
4882
4883 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004884 * otherwise we assume it's not valid. At the moment we assume that
4885 * either both or none of current and max values are valid to keep code
4886 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004887 */
4888 match.valid_tx_power = !status;
4889
4890 /* Commands sent in request are either Read RSSI or Read Transmit Power
4891 * Level so we check which one was last sent to retrieve connection
4892 * handle. Both commands have handle as first parameter so it's safe to
4893 * cast data on the same command struct.
4894 *
4895 * First command sent is always Read RSSI and we fail only if it fails.
4896 * In other case we simply override error to indicate success as we
4897 * already remembered if TX power value is actually valid.
4898 */
4899 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4900 if (!cp) {
4901 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4902 status = 0;
4903 }
4904
4905 if (!cp) {
4906 BT_ERR("invalid sent_cmd in response");
4907 goto unlock;
4908 }
4909
4910 handle = __le16_to_cpu(cp->handle);
4911 conn = hci_conn_hash_lookup_handle(hdev, handle);
4912 if (!conn) {
4913 BT_ERR("unknown handle (%d) in response", handle);
4914 goto unlock;
4915 }
4916
4917 match.conn = conn;
4918 match.mgmt_status = mgmt_status(status);
4919
4920 /* Cache refresh is complete, now reply for mgmt request for given
4921 * connection only.
4922 */
4923 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4924 get_conn_info_complete, &match);
4925
4926unlock:
4927 hci_dev_unlock(hdev);
4928}
4929
4930static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4931 u16 len)
4932{
4933 struct mgmt_cp_get_conn_info *cp = data;
4934 struct mgmt_rp_get_conn_info rp;
4935 struct hci_conn *conn;
4936 unsigned long conn_info_age;
4937 int err = 0;
4938
4939 BT_DBG("%s", hdev->name);
4940
4941 memset(&rp, 0, sizeof(rp));
4942 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4943 rp.addr.type = cp->addr.type;
4944
4945 if (!bdaddr_type_is_valid(cp->addr.type))
4946 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4947 MGMT_STATUS_INVALID_PARAMS,
4948 &rp, sizeof(rp));
4949
4950 hci_dev_lock(hdev);
4951
4952 if (!hdev_is_powered(hdev)) {
4953 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4954 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4955 goto unlock;
4956 }
4957
4958 if (cp->addr.type == BDADDR_BREDR)
4959 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4960 &cp->addr.bdaddr);
4961 else
4962 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4963
4964 if (!conn || conn->state != BT_CONNECTED) {
4965 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4966 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4967 goto unlock;
4968 }
4969
4970 /* To avoid client trying to guess when to poll again for information we
4971 * calculate conn info age as random value between min/max set in hdev.
4972 */
4973 conn_info_age = hdev->conn_info_min_age +
4974 prandom_u32_max(hdev->conn_info_max_age -
4975 hdev->conn_info_min_age);
4976
4977 /* Query controller to refresh cached values if they are too old or were
4978 * never read.
4979 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004980 if (time_after(jiffies, conn->conn_info_timestamp +
4981 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004982 !conn->conn_info_timestamp) {
4983 struct hci_request req;
4984 struct hci_cp_read_tx_power req_txp_cp;
4985 struct hci_cp_read_rssi req_rssi_cp;
4986 struct pending_cmd *cmd;
4987
4988 hci_req_init(&req, hdev);
4989 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4990 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4991 &req_rssi_cp);
4992
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004993 /* For LE links TX power does not change thus we don't need to
4994 * query for it once value is known.
4995 */
4996 if (!bdaddr_type_is_le(cp->addr.type) ||
4997 conn->tx_power == HCI_TX_POWER_INVALID) {
4998 req_txp_cp.handle = cpu_to_le16(conn->handle);
4999 req_txp_cp.type = 0x00;
5000 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5001 sizeof(req_txp_cp), &req_txp_cp);
5002 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005003
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005004 /* Max TX power needs to be read only once per connection */
5005 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5006 req_txp_cp.handle = cpu_to_le16(conn->handle);
5007 req_txp_cp.type = 0x01;
5008 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5009 sizeof(req_txp_cp), &req_txp_cp);
5010 }
5011
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005012 err = hci_req_run(&req, conn_info_refresh_complete);
5013 if (err < 0)
5014 goto unlock;
5015
5016 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5017 data, len);
5018 if (!cmd) {
5019 err = -ENOMEM;
5020 goto unlock;
5021 }
5022
5023 hci_conn_hold(conn);
5024 cmd->user_data = conn;
5025
5026 conn->conn_info_timestamp = jiffies;
5027 } else {
5028 /* Cache is valid, just reply with values cached in hci_conn */
5029 rp.rssi = conn->rssi;
5030 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005031 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005032
5033 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5034 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5035 }
5036
5037unlock:
5038 hci_dev_unlock(hdev);
5039 return err;
5040}
5041
Johan Hedberg95868422014-06-28 17:54:07 +03005042static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5043{
5044 struct mgmt_cp_get_clock_info *cp;
5045 struct mgmt_rp_get_clock_info rp;
5046 struct hci_cp_read_clock *hci_cp;
5047 struct pending_cmd *cmd;
5048 struct hci_conn *conn;
5049
5050 BT_DBG("%s status %u", hdev->name, status);
5051
5052 hci_dev_lock(hdev);
5053
5054 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5055 if (!hci_cp)
5056 goto unlock;
5057
5058 if (hci_cp->which) {
5059 u16 handle = __le16_to_cpu(hci_cp->handle);
5060 conn = hci_conn_hash_lookup_handle(hdev, handle);
5061 } else {
5062 conn = NULL;
5063 }
5064
5065 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5066 if (!cmd)
5067 goto unlock;
5068
5069 cp = cmd->param;
5070
5071 memset(&rp, 0, sizeof(rp));
5072 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5073
5074 if (status)
5075 goto send_rsp;
5076
5077 rp.local_clock = cpu_to_le32(hdev->clock);
5078
5079 if (conn) {
5080 rp.piconet_clock = cpu_to_le32(conn->clock);
5081 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5082 }
5083
5084send_rsp:
5085 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5086 &rp, sizeof(rp));
5087 mgmt_pending_remove(cmd);
5088 if (conn)
5089 hci_conn_drop(conn);
5090
5091unlock:
5092 hci_dev_unlock(hdev);
5093}
5094
5095static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5096 u16 len)
5097{
5098 struct mgmt_cp_get_clock_info *cp = data;
5099 struct mgmt_rp_get_clock_info rp;
5100 struct hci_cp_read_clock hci_cp;
5101 struct pending_cmd *cmd;
5102 struct hci_request req;
5103 struct hci_conn *conn;
5104 int err;
5105
5106 BT_DBG("%s", hdev->name);
5107
5108 memset(&rp, 0, sizeof(rp));
5109 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5110 rp.addr.type = cp->addr.type;
5111
5112 if (cp->addr.type != BDADDR_BREDR)
5113 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5114 MGMT_STATUS_INVALID_PARAMS,
5115 &rp, sizeof(rp));
5116
5117 hci_dev_lock(hdev);
5118
5119 if (!hdev_is_powered(hdev)) {
5120 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5121 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5122 goto unlock;
5123 }
5124
5125 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5126 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5127 &cp->addr.bdaddr);
5128 if (!conn || conn->state != BT_CONNECTED) {
5129 err = cmd_complete(sk, hdev->id,
5130 MGMT_OP_GET_CLOCK_INFO,
5131 MGMT_STATUS_NOT_CONNECTED,
5132 &rp, sizeof(rp));
5133 goto unlock;
5134 }
5135 } else {
5136 conn = NULL;
5137 }
5138
5139 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5140 if (!cmd) {
5141 err = -ENOMEM;
5142 goto unlock;
5143 }
5144
5145 hci_req_init(&req, hdev);
5146
5147 memset(&hci_cp, 0, sizeof(hci_cp));
5148 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5149
5150 if (conn) {
5151 hci_conn_hold(conn);
5152 cmd->user_data = conn;
5153
5154 hci_cp.handle = cpu_to_le16(conn->handle);
5155 hci_cp.which = 0x01; /* Piconet clock */
5156 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5157 }
5158
5159 err = hci_req_run(&req, get_clock_info_complete);
5160 if (err < 0)
5161 mgmt_pending_remove(cmd);
5162
5163unlock:
5164 hci_dev_unlock(hdev);
5165 return err;
5166}
5167
Marcel Holtmann8afef092014-06-29 22:28:34 +02005168static void device_added(struct sock *sk, struct hci_dev *hdev,
5169 bdaddr_t *bdaddr, u8 type, u8 action)
5170{
5171 struct mgmt_ev_device_added ev;
5172
5173 bacpy(&ev.addr.bdaddr, bdaddr);
5174 ev.addr.type = type;
5175 ev.action = action;
5176
5177 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5178}
5179
Marcel Holtmann2faade52014-06-29 19:44:03 +02005180static int add_device(struct sock *sk, struct hci_dev *hdev,
5181 void *data, u16 len)
5182{
5183 struct mgmt_cp_add_device *cp = data;
5184 u8 auto_conn, addr_type;
5185 int err;
5186
5187 BT_DBG("%s", hdev->name);
5188
5189 if (!bdaddr_type_is_le(cp->addr.type) ||
5190 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5191 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5192 MGMT_STATUS_INVALID_PARAMS,
5193 &cp->addr, sizeof(cp->addr));
5194
5195 if (cp->action != 0x00 && cp->action != 0x01)
5196 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5197 MGMT_STATUS_INVALID_PARAMS,
5198 &cp->addr, sizeof(cp->addr));
5199
5200 hci_dev_lock(hdev);
5201
5202 if (cp->addr.type == BDADDR_LE_PUBLIC)
5203 addr_type = ADDR_LE_DEV_PUBLIC;
5204 else
5205 addr_type = ADDR_LE_DEV_RANDOM;
5206
5207 if (cp->action)
5208 auto_conn = HCI_AUTO_CONN_ALWAYS;
5209 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005210 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005211
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005212 /* If the connection parameters don't exist for this device,
5213 * they will be created and configured with defaults.
5214 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005215 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5216 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005217 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5218 MGMT_STATUS_FAILED,
5219 &cp->addr, sizeof(cp->addr));
5220 goto unlock;
5221 }
5222
Marcel Holtmann8afef092014-06-29 22:28:34 +02005223 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5224
Marcel Holtmann2faade52014-06-29 19:44:03 +02005225 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5226 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5227
5228unlock:
5229 hci_dev_unlock(hdev);
5230 return err;
5231}
5232
Marcel Holtmann8afef092014-06-29 22:28:34 +02005233static void device_removed(struct sock *sk, struct hci_dev *hdev,
5234 bdaddr_t *bdaddr, u8 type)
5235{
5236 struct mgmt_ev_device_removed ev;
5237
5238 bacpy(&ev.addr.bdaddr, bdaddr);
5239 ev.addr.type = type;
5240
5241 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5242}
5243
Marcel Holtmann2faade52014-06-29 19:44:03 +02005244static int remove_device(struct sock *sk, struct hci_dev *hdev,
5245 void *data, u16 len)
5246{
5247 struct mgmt_cp_remove_device *cp = data;
5248 int err;
5249
5250 BT_DBG("%s", hdev->name);
5251
5252 hci_dev_lock(hdev);
5253
5254 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005255 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005256 u8 addr_type;
5257
5258 if (!bdaddr_type_is_le(cp->addr.type)) {
5259 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5260 MGMT_STATUS_INVALID_PARAMS,
5261 &cp->addr, sizeof(cp->addr));
5262 goto unlock;
5263 }
5264
5265 if (cp->addr.type == BDADDR_LE_PUBLIC)
5266 addr_type = ADDR_LE_DEV_PUBLIC;
5267 else
5268 addr_type = ADDR_LE_DEV_RANDOM;
5269
Johan Hedbergc71593d2014-07-02 17:37:28 +03005270 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5271 addr_type);
5272 if (!params) {
5273 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5274 MGMT_STATUS_INVALID_PARAMS,
5275 &cp->addr, sizeof(cp->addr));
5276 goto unlock;
5277 }
5278
5279 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5280 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5281 MGMT_STATUS_INVALID_PARAMS,
5282 &cp->addr, sizeof(cp->addr));
5283 goto unlock;
5284 }
5285
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005286 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005287 list_del(&params->list);
5288 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005289 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005290
5291 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005292 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005293 struct hci_conn_params *p, *tmp;
5294
Marcel Holtmann2faade52014-06-29 19:44:03 +02005295 if (cp->addr.type) {
5296 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5297 MGMT_STATUS_INVALID_PARAMS,
5298 &cp->addr, sizeof(cp->addr));
5299 goto unlock;
5300 }
5301
Johan Hedberg19de0822014-07-06 13:06:51 +03005302 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5303 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5304 continue;
5305 device_removed(sk, hdev, &p->addr, p->addr_type);
5306 list_del(&p->action);
5307 list_del(&p->list);
5308 kfree(p);
5309 }
5310
5311 BT_DBG("All LE connection parameters were removed");
5312
5313 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005314 }
5315
5316 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5317 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5318
5319unlock:
5320 hci_dev_unlock(hdev);
5321 return err;
5322}
5323
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005324static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5325 u16 len)
5326{
5327 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005328 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5329 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005330 u16 param_count, expected_len;
5331 int i;
5332
5333 if (!lmp_le_capable(hdev))
5334 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5335 MGMT_STATUS_NOT_SUPPORTED);
5336
5337 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005338 if (param_count > max_param_count) {
5339 BT_ERR("load_conn_param: too big param_count value %u",
5340 param_count);
5341 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5342 MGMT_STATUS_INVALID_PARAMS);
5343 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005344
5345 expected_len = sizeof(*cp) + param_count *
5346 sizeof(struct mgmt_conn_param);
5347 if (expected_len != len) {
5348 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5349 expected_len, len);
5350 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5351 MGMT_STATUS_INVALID_PARAMS);
5352 }
5353
5354 BT_DBG("%s param_count %u", hdev->name, param_count);
5355
5356 hci_dev_lock(hdev);
5357
5358 hci_conn_params_clear_disabled(hdev);
5359
5360 for (i = 0; i < param_count; i++) {
5361 struct mgmt_conn_param *param = &cp->params[i];
5362 struct hci_conn_params *hci_param;
5363 u16 min, max, latency, timeout;
5364 u8 addr_type;
5365
5366 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5367 param->addr.type);
5368
5369 if (param->addr.type == BDADDR_LE_PUBLIC) {
5370 addr_type = ADDR_LE_DEV_PUBLIC;
5371 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5372 addr_type = ADDR_LE_DEV_RANDOM;
5373 } else {
5374 BT_ERR("Ignoring invalid connection parameters");
5375 continue;
5376 }
5377
5378 min = le16_to_cpu(param->min_interval);
5379 max = le16_to_cpu(param->max_interval);
5380 latency = le16_to_cpu(param->latency);
5381 timeout = le16_to_cpu(param->timeout);
5382
5383 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5384 min, max, latency, timeout);
5385
5386 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5387 BT_ERR("Ignoring invalid connection parameters");
5388 continue;
5389 }
5390
5391 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5392 addr_type);
5393 if (!hci_param) {
5394 BT_ERR("Failed to add connection parameters");
5395 continue;
5396 }
5397
5398 hci_param->conn_min_interval = min;
5399 hci_param->conn_max_interval = max;
5400 hci_param->conn_latency = latency;
5401 hci_param->supervision_timeout = timeout;
5402 }
5403
5404 hci_dev_unlock(hdev);
5405
5406 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5407}
5408
Marcel Holtmanndbece372014-07-04 18:11:55 +02005409static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5410 void *data, u16 len)
5411{
5412 struct mgmt_cp_set_external_config *cp = data;
5413 bool changed;
5414 int err;
5415
5416 BT_DBG("%s", hdev->name);
5417
5418 if (hdev_is_powered(hdev))
5419 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5420 MGMT_STATUS_REJECTED);
5421
5422 if (cp->config != 0x00 && cp->config != 0x01)
5423 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5424 MGMT_STATUS_INVALID_PARAMS);
5425
5426 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5427 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5428 MGMT_STATUS_NOT_SUPPORTED);
5429
5430 hci_dev_lock(hdev);
5431
5432 if (cp->config)
5433 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5434 &hdev->dev_flags);
5435 else
5436 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5437 &hdev->dev_flags);
5438
5439 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5440 if (err < 0)
5441 goto unlock;
5442
5443 if (!changed)
5444 goto unlock;
5445
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005446 err = new_options(hdev, sk);
5447
Marcel Holtmanndbece372014-07-04 18:11:55 +02005448 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5449 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005450
5451 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5452 set_bit(HCI_CONFIG, &hdev->dev_flags);
5453 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5454
5455 queue_work(hdev->req_workqueue, &hdev->power_on);
5456 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005457 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005458 mgmt_index_added(hdev);
5459 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005460 }
5461
5462unlock:
5463 hci_dev_unlock(hdev);
5464 return err;
5465}
5466
Marcel Holtmann9713c172014-07-06 12:11:15 +02005467static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5468 void *data, u16 len)
5469{
5470 struct mgmt_cp_set_public_address *cp = data;
5471 bool changed;
5472 int err;
5473
5474 BT_DBG("%s", hdev->name);
5475
5476 if (hdev_is_powered(hdev))
5477 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5478 MGMT_STATUS_REJECTED);
5479
5480 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5481 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5482 MGMT_STATUS_INVALID_PARAMS);
5483
5484 if (!hdev->set_bdaddr)
5485 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5486 MGMT_STATUS_NOT_SUPPORTED);
5487
5488 hci_dev_lock(hdev);
5489
5490 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5491 bacpy(&hdev->public_addr, &cp->bdaddr);
5492
5493 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5494 if (err < 0)
5495 goto unlock;
5496
5497 if (!changed)
5498 goto unlock;
5499
5500 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5501 err = new_options(hdev, sk);
5502
5503 if (is_configured(hdev)) {
5504 mgmt_index_removed(hdev);
5505
5506 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5507
5508 set_bit(HCI_CONFIG, &hdev->dev_flags);
5509 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5510
5511 queue_work(hdev->req_workqueue, &hdev->power_on);
5512 }
5513
5514unlock:
5515 hci_dev_unlock(hdev);
5516 return err;
5517}
5518
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005519static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005520 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5521 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005522 bool var_len;
5523 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005524} mgmt_handlers[] = {
5525 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005526 { read_version, false, MGMT_READ_VERSION_SIZE },
5527 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5528 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5529 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5530 { set_powered, false, MGMT_SETTING_SIZE },
5531 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5532 { set_connectable, false, MGMT_SETTING_SIZE },
5533 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5534 { set_pairable, false, MGMT_SETTING_SIZE },
5535 { set_link_security, false, MGMT_SETTING_SIZE },
5536 { set_ssp, false, MGMT_SETTING_SIZE },
5537 { set_hs, false, MGMT_SETTING_SIZE },
5538 { set_le, false, MGMT_SETTING_SIZE },
5539 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5540 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5541 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5542 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5543 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5544 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5545 { disconnect, false, MGMT_DISCONNECT_SIZE },
5546 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5547 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5548 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5549 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5550 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5551 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5552 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5553 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5554 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5555 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5556 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5557 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005558 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005559 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5560 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5561 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5562 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5563 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5564 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005565 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005566 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005567 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005568 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005569 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005570 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005571 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005572 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005573 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005574 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005575 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005576 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5577 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005578 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5579 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005580 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005581 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005582 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005583};
5584
Johan Hedberg03811012010-12-08 00:21:06 +02005585int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5586{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005587 void *buf;
5588 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005589 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005590 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005591 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005592 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005593 int err;
5594
5595 BT_DBG("got %zu bytes", msglen);
5596
5597 if (msglen < sizeof(*hdr))
5598 return -EINVAL;
5599
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005600 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005601 if (!buf)
5602 return -ENOMEM;
5603
5604 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5605 err = -EFAULT;
5606 goto done;
5607 }
5608
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005609 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005610 opcode = __le16_to_cpu(hdr->opcode);
5611 index = __le16_to_cpu(hdr->index);
5612 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005613
5614 if (len != msglen - sizeof(*hdr)) {
5615 err = -EINVAL;
5616 goto done;
5617 }
5618
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005619 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005620 hdev = hci_dev_get(index);
5621 if (!hdev) {
5622 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005623 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005624 goto done;
5625 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005626
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005627 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005628 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005629 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005630 err = cmd_status(sk, index, opcode,
5631 MGMT_STATUS_INVALID_INDEX);
5632 goto done;
5633 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005634
5635 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005636 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005637 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5638 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005639 err = cmd_status(sk, index, opcode,
5640 MGMT_STATUS_INVALID_INDEX);
5641 goto done;
5642 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005643 }
5644
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005645 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005646 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005647 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005648 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005649 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005650 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005651 }
5652
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005653 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5654 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5655 err = cmd_status(sk, index, opcode,
5656 MGMT_STATUS_INVALID_INDEX);
5657 goto done;
5658 }
5659
5660 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5661 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005662 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005663 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005664 goto done;
5665 }
5666
Johan Hedbergbe22b542012-03-01 22:24:41 +02005667 handler = &mgmt_handlers[opcode];
5668
5669 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005670 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005671 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005672 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005673 goto done;
5674 }
5675
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005676 if (hdev)
5677 mgmt_init_hdev(sk, hdev);
5678
5679 cp = buf + sizeof(*hdr);
5680
Johan Hedbergbe22b542012-03-01 22:24:41 +02005681 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005682 if (err < 0)
5683 goto done;
5684
Johan Hedberg03811012010-12-08 00:21:06 +02005685 err = msglen;
5686
5687done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005688 if (hdev)
5689 hci_dev_put(hdev);
5690
Johan Hedberg03811012010-12-08 00:21:06 +02005691 kfree(buf);
5692 return err;
5693}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005694
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005695void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005696{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005697 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005698 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005699
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005700 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5701 return;
5702
5703 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5704 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5705 else
5706 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005707}
5708
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005709void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005710{
Johan Hedberg5f159032012-03-02 03:13:19 +02005711 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005712
Marcel Holtmann1514b892013-10-06 08:25:01 -07005713 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005714 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005715
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005716 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5717 return;
5718
Johan Hedberg744cf192011-11-08 20:40:14 +02005719 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005720
Marcel Holtmannedd38962014-07-02 21:30:55 +02005721 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5722 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5723 else
5724 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005725}
5726
Andre Guedes6046dc32014-02-26 20:21:51 -03005727/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005728static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005729{
5730 struct hci_conn_params *p;
5731
5732 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005733 /* Needed for AUTO_OFF case where might not "really"
5734 * have been powered off.
5735 */
5736 list_del_init(&p->action);
5737
5738 switch (p->auto_connect) {
5739 case HCI_AUTO_CONN_ALWAYS:
5740 list_add(&p->action, &hdev->pend_le_conns);
5741 break;
5742 case HCI_AUTO_CONN_REPORT:
5743 list_add(&p->action, &hdev->pend_le_reports);
5744 break;
5745 default:
5746 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005747 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005748 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005749
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005750 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005751}
5752
Johan Hedberg229ab392013-03-15 17:06:53 -05005753static void powered_complete(struct hci_dev *hdev, u8 status)
5754{
5755 struct cmd_lookup match = { NULL, hdev };
5756
5757 BT_DBG("status 0x%02x", status);
5758
5759 hci_dev_lock(hdev);
5760
Johan Hedbergd7347f32014-07-04 12:37:23 +03005761 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005762
Johan Hedberg229ab392013-03-15 17:06:53 -05005763 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5764
5765 new_settings(hdev, match.sk);
5766
5767 hci_dev_unlock(hdev);
5768
5769 if (match.sk)
5770 sock_put(match.sk);
5771}
5772
Johan Hedberg70da6242013-03-15 17:06:51 -05005773static int powered_update_hci(struct hci_dev *hdev)
5774{
Johan Hedberg890ea892013-03-15 17:06:52 -05005775 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005776 u8 link_sec;
5777
Johan Hedberg890ea892013-03-15 17:06:52 -05005778 hci_req_init(&req, hdev);
5779
Johan Hedberg70da6242013-03-15 17:06:51 -05005780 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5781 !lmp_host_ssp_capable(hdev)) {
5782 u8 ssp = 1;
5783
Johan Hedberg890ea892013-03-15 17:06:52 -05005784 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005785 }
5786
Johan Hedbergc73eee92013-04-19 18:35:21 +03005787 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5788 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005789 struct hci_cp_write_le_host_supported cp;
5790
5791 cp.le = 1;
5792 cp.simul = lmp_le_br_capable(hdev);
5793
5794 /* Check first if we already have the right
5795 * host state (host features set)
5796 */
5797 if (cp.le != lmp_host_le_capable(hdev) ||
5798 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005799 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5800 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005801 }
5802
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005803 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005804 /* Make sure the controller has a good default for
5805 * advertising data. This also applies to the case
5806 * where BR/EDR was toggled during the AUTO_OFF phase.
5807 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005808 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005809 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005810 update_scan_rsp_data(&req);
5811 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005812
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005813 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5814 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005815 }
5816
Johan Hedberg70da6242013-03-15 17:06:51 -05005817 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5818 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005819 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5820 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005821
5822 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005823 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5824 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005825 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005826 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005827 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005828 }
5829
Johan Hedberg229ab392013-03-15 17:06:53 -05005830 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005831}
5832
Johan Hedberg744cf192011-11-08 20:40:14 +02005833int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005834{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005835 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005836 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5837 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005838 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005839
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005840 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5841 return 0;
5842
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005843 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005844 if (powered_update_hci(hdev) == 0)
5845 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005846
Johan Hedberg229ab392013-03-15 17:06:53 -05005847 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5848 &match);
5849 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005850 }
5851
Johan Hedberg229ab392013-03-15 17:06:53 -05005852 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5853 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5854
5855 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5856 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5857 zero_cod, sizeof(zero_cod), NULL);
5858
5859new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005860 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005861
5862 if (match.sk)
5863 sock_put(match.sk);
5864
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005865 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005866}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005867
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005868void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005869{
5870 struct pending_cmd *cmd;
5871 u8 status;
5872
5873 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5874 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005875 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005876
5877 if (err == -ERFKILL)
5878 status = MGMT_STATUS_RFKILLED;
5879 else
5880 status = MGMT_STATUS_FAILED;
5881
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005882 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005883
5884 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005885}
5886
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005887void mgmt_discoverable_timeout(struct hci_dev *hdev)
5888{
5889 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005890
5891 hci_dev_lock(hdev);
5892
5893 /* When discoverable timeout triggers, then just make sure
5894 * the limited discoverable flag is cleared. Even in the case
5895 * of a timeout triggered from general discoverable, it is
5896 * safe to unconditionally clear the flag.
5897 */
5898 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005899 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005900
5901 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005902 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5903 u8 scan = SCAN_PAGE;
5904 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5905 sizeof(scan), &scan);
5906 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005907 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005908 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005909 hci_req_run(&req, NULL);
5910
5911 hdev->discov_timeout = 0;
5912
Johan Hedberg9a43e252013-10-20 19:00:07 +03005913 new_settings(hdev, NULL);
5914
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005915 hci_dev_unlock(hdev);
5916}
5917
Marcel Holtmann86a75642013-10-15 06:33:54 -07005918void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005919{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005920 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005921
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005922 /* Nothing needed here if there's a pending command since that
5923 * commands request completion callback takes care of everything
5924 * necessary.
5925 */
5926 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005927 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005928
Johan Hedbergbd107992014-02-24 14:52:19 +02005929 /* Powering off may clear the scan mode - don't let that interfere */
5930 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5931 return;
5932
Johan Hedberg9a43e252013-10-20 19:00:07 +03005933 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005934 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005935 } else {
5936 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005937 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005938 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005939
Johan Hedberg9a43e252013-10-20 19:00:07 +03005940 if (changed) {
5941 struct hci_request req;
5942
5943 /* In case this change in discoverable was triggered by
5944 * a disabling of connectable there could be a need to
5945 * update the advertising flags.
5946 */
5947 hci_req_init(&req, hdev);
5948 update_adv_data(&req);
5949 hci_req_run(&req, NULL);
5950
Marcel Holtmann86a75642013-10-15 06:33:54 -07005951 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005952 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005953}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005954
Marcel Holtmanna3309162013-10-15 06:33:55 -07005955void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005956{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005957 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005958
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005959 /* Nothing needed here if there's a pending command since that
5960 * commands request completion callback takes care of everything
5961 * necessary.
5962 */
5963 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005964 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005965
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005966 /* Powering off may clear the scan mode - don't let that interfere */
5967 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5968 return;
5969
Marcel Holtmanna3309162013-10-15 06:33:55 -07005970 if (connectable)
5971 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5972 else
5973 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005974
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005975 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005976 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005977}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005978
Johan Hedberg778b2352014-02-24 14:52:17 +02005979void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5980{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005981 /* Powering off may stop advertising - don't let that interfere */
5982 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5983 return;
5984
Johan Hedberg778b2352014-02-24 14:52:17 +02005985 if (advertising)
5986 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5987 else
5988 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5989}
5990
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005991void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005992{
Johan Hedbergca69b792011-11-11 18:10:00 +02005993 u8 mgmt_err = mgmt_status(status);
5994
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005995 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005996 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005997 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005998
5999 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02006000 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006001 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006002}
6003
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006004void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6005 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006006{
Johan Hedberg86742e12011-11-07 23:13:38 +02006007 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006008
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006009 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006010
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006011 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006012 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006013 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006014 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006015 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006016 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006017
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006018 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006019}
Johan Hedbergf7520542011-01-20 12:34:39 +02006020
Johan Hedbergd7b25452014-05-23 13:19:53 +03006021static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6022{
6023 if (ltk->authenticated)
6024 return MGMT_LTK_AUTHENTICATED;
6025
6026 return MGMT_LTK_UNAUTHENTICATED;
6027}
6028
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006029void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006030{
6031 struct mgmt_ev_new_long_term_key ev;
6032
6033 memset(&ev, 0, sizeof(ev));
6034
Marcel Holtmann5192d302014-02-19 17:11:58 -08006035 /* Devices using resolvable or non-resolvable random addresses
6036 * without providing an indentity resolving key don't require
6037 * to store long term keys. Their addresses will change the
6038 * next time around.
6039 *
6040 * Only when a remote device provides an identity address
6041 * make sure the long term key is stored. If the remote
6042 * identity is known, the long term keys are internally
6043 * mapped to the identity address. So allow static random
6044 * and public addresses here.
6045 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006046 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6047 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6048 ev.store_hint = 0x00;
6049 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006050 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006051
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006052 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006053 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006054 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006055 ev.key.enc_size = key->enc_size;
6056 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006057 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006058
Johan Hedberg2ceba532014-06-16 19:25:16 +03006059 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006060 ev.key.master = 1;
6061
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006062 memcpy(ev.key.val, key->val, sizeof(key->val));
6063
Marcel Holtmann083368f2013-10-15 14:26:29 -07006064 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006065}
6066
Johan Hedberg95fbac82014-02-19 15:18:31 +02006067void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6068{
6069 struct mgmt_ev_new_irk ev;
6070
6071 memset(&ev, 0, sizeof(ev));
6072
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006073 /* For identity resolving keys from devices that are already
6074 * using a public address or static random address, do not
6075 * ask for storing this key. The identity resolving key really
6076 * is only mandatory for devices using resovlable random
6077 * addresses.
6078 *
6079 * Storing all identity resolving keys has the downside that
6080 * they will be also loaded on next boot of they system. More
6081 * identity resolving keys, means more time during scanning is
6082 * needed to actually resolve these addresses.
6083 */
6084 if (bacmp(&irk->rpa, BDADDR_ANY))
6085 ev.store_hint = 0x01;
6086 else
6087 ev.store_hint = 0x00;
6088
Johan Hedberg95fbac82014-02-19 15:18:31 +02006089 bacpy(&ev.rpa, &irk->rpa);
6090 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6091 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6092 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6093
6094 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6095}
6096
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006097void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6098 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006099{
6100 struct mgmt_ev_new_csrk ev;
6101
6102 memset(&ev, 0, sizeof(ev));
6103
6104 /* Devices using resolvable or non-resolvable random addresses
6105 * without providing an indentity resolving key don't require
6106 * to store signature resolving keys. Their addresses will change
6107 * the next time around.
6108 *
6109 * Only when a remote device provides an identity address
6110 * make sure the signature resolving key is stored. So allow
6111 * static random and public addresses here.
6112 */
6113 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6114 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6115 ev.store_hint = 0x00;
6116 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006117 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006118
6119 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6120 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6121 ev.key.master = csrk->master;
6122 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6123
6124 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6125}
6126
Andre Guedesffb5a8272014-07-01 18:10:11 -03006127void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006128 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6129 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006130{
6131 struct mgmt_ev_new_conn_param ev;
6132
Johan Hedbergc103aea2014-07-02 17:37:34 +03006133 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6134 return;
6135
Andre Guedesffb5a8272014-07-01 18:10:11 -03006136 memset(&ev, 0, sizeof(ev));
6137 bacpy(&ev.addr.bdaddr, bdaddr);
6138 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006139 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006140 ev.min_interval = cpu_to_le16(min_interval);
6141 ev.max_interval = cpu_to_le16(max_interval);
6142 ev.latency = cpu_to_le16(latency);
6143 ev.timeout = cpu_to_le16(timeout);
6144
6145 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6146}
6147
Marcel Holtmann94933992013-10-15 10:26:39 -07006148static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6149 u8 data_len)
6150{
6151 eir[eir_len++] = sizeof(type) + data_len;
6152 eir[eir_len++] = type;
6153 memcpy(&eir[eir_len], data, data_len);
6154 eir_len += data_len;
6155
6156 return eir_len;
6157}
6158
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006159void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6160 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6161 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006162{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006163 char buf[512];
6164 struct mgmt_ev_device_connected *ev = (void *) buf;
6165 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006166
Johan Hedbergb644ba32012-01-17 21:48:47 +02006167 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006168 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006169
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006170 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006171
Johan Hedbergb644ba32012-01-17 21:48:47 +02006172 if (name_len > 0)
6173 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006174 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006175
6176 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006177 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006178 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006179
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006180 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006181
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006182 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6183 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006184}
6185
Johan Hedberg8962ee72011-01-20 12:40:27 +02006186static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6187{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006188 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006189 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006190 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006191
Johan Hedberg88c3df12012-02-09 14:27:38 +02006192 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6193 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006194
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006195 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006196 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006197
6198 *sk = cmd->sk;
6199 sock_hold(*sk);
6200
Johan Hedberga664b5b2011-02-19 12:06:02 -03006201 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006202}
6203
Johan Hedberg124f6e32012-02-09 13:50:12 +02006204static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006205{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006206 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006207 struct mgmt_cp_unpair_device *cp = cmd->param;
6208 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006209
6210 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006211 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6212 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006213
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006214 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6215
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006216 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006217
6218 mgmt_pending_remove(cmd);
6219}
6220
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006221void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006222 u8 link_type, u8 addr_type, u8 reason,
6223 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006224{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006225 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006226 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006227 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006228
Johan Hedberg8b064a32014-02-24 14:52:22 +02006229 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6230 if (power_off) {
6231 struct mgmt_mode *cp = power_off->param;
6232
6233 /* The connection is still in hci_conn_hash so test for 1
6234 * instead of 0 to know if this is the last one.
6235 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006236 if (!cp->val && hci_conn_count(hdev) == 1) {
6237 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006238 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006239 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006240 }
6241
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006242 if (!mgmt_connected)
6243 return;
6244
Andre Guedes57eb7762013-10-30 19:01:41 -03006245 if (link_type != ACL_LINK && link_type != LE_LINK)
6246 return;
6247
Johan Hedberg744cf192011-11-08 20:40:14 +02006248 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006249
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006250 bacpy(&ev.addr.bdaddr, bdaddr);
6251 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6252 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006253
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006254 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006255
6256 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006257 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006258
Johan Hedberg124f6e32012-02-09 13:50:12 +02006259 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006260 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006261}
6262
Marcel Holtmann78929242013-10-06 23:55:47 -07006263void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6264 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006265{
Andre Guedes3655bba2013-10-30 19:01:40 -03006266 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6267 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006268 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006269 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006270
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006271 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6272 hdev);
6273
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006274 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006275 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006276 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006277
Andre Guedes3655bba2013-10-30 19:01:40 -03006278 cp = cmd->param;
6279
6280 if (bacmp(bdaddr, &cp->addr.bdaddr))
6281 return;
6282
6283 if (cp->addr.type != bdaddr_type)
6284 return;
6285
Johan Hedberg88c3df12012-02-09 14:27:38 +02006286 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006287 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006288
Marcel Holtmann78929242013-10-06 23:55:47 -07006289 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6290 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006291
Johan Hedberga664b5b2011-02-19 12:06:02 -03006292 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006293}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006294
Marcel Holtmann445608d2013-10-06 23:55:48 -07006295void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6296 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006297{
6298 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006299 struct pending_cmd *power_off;
6300
6301 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6302 if (power_off) {
6303 struct mgmt_mode *cp = power_off->param;
6304
6305 /* The connection is still in hci_conn_hash so test for 1
6306 * instead of 0 to know if this is the last one.
6307 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006308 if (!cp->val && hci_conn_count(hdev) == 1) {
6309 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006310 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006311 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006312 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006313
Johan Hedberg4c659c32011-11-07 23:13:39 +02006314 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006315 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006316 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006317
Marcel Holtmann445608d2013-10-06 23:55:48 -07006318 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006319}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006320
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006321void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006322{
6323 struct mgmt_ev_pin_code_request ev;
6324
Johan Hedbergd8457692012-02-17 14:24:57 +02006325 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006326 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006327 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006328
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006329 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006330}
6331
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006332void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6333 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006334{
6335 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006336 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006337
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006338 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006339 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006340 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006341
Johan Hedbergd8457692012-02-17 14:24:57 +02006342 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006343 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006344
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006345 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6346 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006347
Johan Hedberga664b5b2011-02-19 12:06:02 -03006348 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006349}
6350
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006351void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6352 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006353{
6354 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006355 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006356
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006357 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006358 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006359 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006360
Johan Hedbergd8457692012-02-17 14:24:57 +02006361 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006362 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006363
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006364 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6365 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006366
Johan Hedberga664b5b2011-02-19 12:06:02 -03006367 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006368}
Johan Hedberga5c29682011-02-19 12:05:57 -03006369
Johan Hedberg744cf192011-11-08 20:40:14 +02006370int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006371 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006372 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006373{
6374 struct mgmt_ev_user_confirm_request ev;
6375
Johan Hedberg744cf192011-11-08 20:40:14 +02006376 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006377
Johan Hedberg272d90d2012-02-09 15:26:12 +02006378 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006379 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006380 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006381 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006382
Johan Hedberg744cf192011-11-08 20:40:14 +02006383 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006384 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006385}
6386
Johan Hedberg272d90d2012-02-09 15:26:12 +02006387int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006388 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006389{
6390 struct mgmt_ev_user_passkey_request ev;
6391
6392 BT_DBG("%s", hdev->name);
6393
Johan Hedberg272d90d2012-02-09 15:26:12 +02006394 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006395 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006396
6397 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006398 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006399}
6400
Brian Gix0df4c182011-11-16 13:53:13 -08006401static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006402 u8 link_type, u8 addr_type, u8 status,
6403 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006404{
6405 struct pending_cmd *cmd;
6406 struct mgmt_rp_user_confirm_reply rp;
6407 int err;
6408
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006409 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006410 if (!cmd)
6411 return -ENOENT;
6412
Johan Hedberg272d90d2012-02-09 15:26:12 +02006413 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006414 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006415 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006416 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006417
Johan Hedberga664b5b2011-02-19 12:06:02 -03006418 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006419
6420 return err;
6421}
6422
Johan Hedberg744cf192011-11-08 20:40:14 +02006423int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006424 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006425{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006426 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006427 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006428}
6429
Johan Hedberg272d90d2012-02-09 15:26:12 +02006430int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006431 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006432{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006433 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006434 status,
6435 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006436}
Johan Hedberg2a611692011-02-19 12:06:00 -03006437
Brian Gix604086b2011-11-23 08:28:33 -08006438int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006439 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006440{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006441 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006442 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006443}
6444
Johan Hedberg272d90d2012-02-09 15:26:12 +02006445int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006446 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006447{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006448 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006449 status,
6450 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006451}
6452
Johan Hedberg92a25252012-09-06 18:39:26 +03006453int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6454 u8 link_type, u8 addr_type, u32 passkey,
6455 u8 entered)
6456{
6457 struct mgmt_ev_passkey_notify ev;
6458
6459 BT_DBG("%s", hdev->name);
6460
6461 bacpy(&ev.addr.bdaddr, bdaddr);
6462 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6463 ev.passkey = __cpu_to_le32(passkey);
6464 ev.entered = entered;
6465
6466 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6467}
6468
Marcel Holtmanne5460992013-10-15 14:26:23 -07006469void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6470 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006471{
6472 struct mgmt_ev_auth_failed ev;
6473
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006474 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006475 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006476 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006477
Marcel Holtmanne5460992013-10-15 14:26:23 -07006478 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006479}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006480
Marcel Holtmann464996a2013-10-15 14:26:24 -07006481void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006482{
6483 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006484 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006485
6486 if (status) {
6487 u8 mgmt_err = mgmt_status(status);
6488 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006489 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006490 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006491 }
6492
Marcel Holtmann464996a2013-10-15 14:26:24 -07006493 if (test_bit(HCI_AUTH, &hdev->flags))
6494 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6495 &hdev->dev_flags);
6496 else
6497 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6498 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006499
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006500 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006501 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006502
Johan Hedberg47990ea2012-02-22 11:58:37 +02006503 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006504 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006505
6506 if (match.sk)
6507 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006508}
6509
Johan Hedberg890ea892013-03-15 17:06:52 -05006510static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006511{
Johan Hedberg890ea892013-03-15 17:06:52 -05006512 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006513 struct hci_cp_write_eir cp;
6514
Johan Hedberg976eb202012-10-24 21:12:01 +03006515 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006516 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006517
Johan Hedbergc80da272012-02-22 15:38:48 +02006518 memset(hdev->eir, 0, sizeof(hdev->eir));
6519
Johan Hedbergcacaf522012-02-21 00:52:42 +02006520 memset(&cp, 0, sizeof(cp));
6521
Johan Hedberg890ea892013-03-15 17:06:52 -05006522 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006523}
6524
Marcel Holtmann3e248562013-10-15 14:26:25 -07006525void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006526{
6527 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006528 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006529 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006530
6531 if (status) {
6532 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006533
6534 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006535 &hdev->dev_flags)) {
6536 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006537 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006538 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006539
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006540 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6541 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006542 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006543 }
6544
6545 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006546 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006547 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006548 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6549 if (!changed)
6550 changed = test_and_clear_bit(HCI_HS_ENABLED,
6551 &hdev->dev_flags);
6552 else
6553 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006554 }
6555
6556 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6557
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006558 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006559 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006560
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006561 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006562 sock_put(match.sk);
6563
Johan Hedberg890ea892013-03-15 17:06:52 -05006564 hci_req_init(&req, hdev);
6565
Johan Hedberg37699722014-06-24 14:00:27 +03006566 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6567 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6568 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6569 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006570 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006571 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006572 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006573 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006574
6575 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006576}
6577
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006578void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6579{
6580 struct cmd_lookup match = { NULL, hdev };
6581 bool changed = false;
6582
6583 if (status) {
6584 u8 mgmt_err = mgmt_status(status);
6585
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006586 if (enable) {
6587 if (test_and_clear_bit(HCI_SC_ENABLED,
6588 &hdev->dev_flags))
6589 new_settings(hdev, NULL);
6590 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6591 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006592
6593 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6594 cmd_status_rsp, &mgmt_err);
6595 return;
6596 }
6597
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006598 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006599 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006600 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006601 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006602 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6603 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006604
6605 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6606 settings_rsp, &match);
6607
6608 if (changed)
6609 new_settings(hdev, match.sk);
6610
6611 if (match.sk)
6612 sock_put(match.sk);
6613}
6614
Johan Hedberg92da6092013-03-15 17:06:55 -05006615static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006616{
6617 struct cmd_lookup *match = data;
6618
Johan Hedberg90e70452012-02-23 23:09:40 +02006619 if (match->sk == NULL) {
6620 match->sk = cmd->sk;
6621 sock_hold(match->sk);
6622 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006623}
6624
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006625void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6626 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006627{
Johan Hedberg90e70452012-02-23 23:09:40 +02006628 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006629
Johan Hedberg92da6092013-03-15 17:06:55 -05006630 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6631 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6632 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006633
6634 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006635 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6636 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006637
6638 if (match.sk)
6639 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006640}
6641
Marcel Holtmann7667da32013-10-15 14:26:27 -07006642void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006643{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006644 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006645 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006646
Johan Hedberg13928972013-03-15 17:07:00 -05006647 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006648 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006649
6650 memset(&ev, 0, sizeof(ev));
6651 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006652 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006653
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006654 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006655 if (!cmd) {
6656 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006657
Johan Hedberg13928972013-03-15 17:07:00 -05006658 /* If this is a HCI command related to powering on the
6659 * HCI dev don't send any mgmt signals.
6660 */
6661 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006662 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006663 }
6664
Marcel Holtmann7667da32013-10-15 14:26:27 -07006665 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6666 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006667}
Szymon Jancc35938b2011-03-22 13:12:21 +01006668
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006669void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6670 u8 *randomizer192, u8 *hash256,
6671 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006672{
6673 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006674
Johan Hedberg744cf192011-11-08 20:40:14 +02006675 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006676
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006677 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006678 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006679 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006680
6681 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006682 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6683 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006684 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006685 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6686 hash256 && randomizer256) {
6687 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006688
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006689 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6690 memcpy(rp.randomizer192, randomizer192,
6691 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006692
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006693 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6694 memcpy(rp.randomizer256, randomizer256,
6695 sizeof(rp.randomizer256));
6696
6697 cmd_complete(cmd->sk, hdev->id,
6698 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6699 &rp, sizeof(rp));
6700 } else {
6701 struct mgmt_rp_read_local_oob_data rp;
6702
6703 memcpy(rp.hash, hash192, sizeof(rp.hash));
6704 memcpy(rp.randomizer, randomizer192,
6705 sizeof(rp.randomizer));
6706
6707 cmd_complete(cmd->sk, hdev->id,
6708 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6709 &rp, sizeof(rp));
6710 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006711 }
6712
6713 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006714}
Johan Hedberge17acd42011-03-30 23:57:16 +03006715
Marcel Holtmann901801b2013-10-06 23:55:51 -07006716void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006717 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6718 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006719{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006720 char buf[512];
6721 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006722 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006723
Johan Hedberg75ce2082014-07-02 22:42:01 +03006724 /* Don't send events for a non-kernel initiated discovery. With
6725 * LE one exception is if we have pend_le_reports > 0 in which
6726 * case we're doing passive scanning and want these events.
6727 */
6728 if (!hci_discovery_active(hdev)) {
6729 if (link_type == ACL_LINK)
6730 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006731 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006732 return;
6733 }
Andre Guedes12602d02013-04-30 15:29:40 -03006734
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006735 /* Make sure that the buffer is big enough. The 5 extra bytes
6736 * are for the potential CoD field.
6737 */
6738 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006739 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006740
Johan Hedberg1dc06092012-01-15 21:01:23 +02006741 memset(buf, 0, sizeof(buf));
6742
Johan Hedberg841c5642014-07-07 12:45:54 +03006743 bacpy(&ev->addr.bdaddr, bdaddr);
6744 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006745 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006746 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006747
Johan Hedberg1dc06092012-01-15 21:01:23 +02006748 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006749 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006750
Johan Hedberg1dc06092012-01-15 21:01:23 +02006751 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6752 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006753 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006754
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006755 if (scan_rsp_len > 0)
6756 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6757
6758 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6759 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006760
Marcel Holtmann901801b2013-10-06 23:55:51 -07006761 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006762}
Johan Hedberga88a9652011-03-30 13:18:12 +03006763
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006764void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6765 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006766{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006767 struct mgmt_ev_device_found *ev;
6768 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6769 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006770
Johan Hedbergb644ba32012-01-17 21:48:47 +02006771 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006772
Johan Hedbergb644ba32012-01-17 21:48:47 +02006773 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006774
Johan Hedbergb644ba32012-01-17 21:48:47 +02006775 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006776 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006777 ev->rssi = rssi;
6778
6779 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006780 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006781
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006782 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006783
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006784 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006785}
Johan Hedberg314b2382011-04-27 10:29:57 -04006786
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006787void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006788{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006789 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006790 struct pending_cmd *cmd;
6791
Andre Guedes343fb142011-11-22 17:14:19 -03006792 BT_DBG("%s discovering %u", hdev->name, discovering);
6793
Johan Hedberg164a6e72011-11-01 17:06:44 +02006794 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006795 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006796 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006797 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006798
6799 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006800 u8 type = hdev->discovery.type;
6801
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006802 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6803 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006804 mgmt_pending_remove(cmd);
6805 }
6806
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006807 memset(&ev, 0, sizeof(ev));
6808 ev.type = hdev->discovery.type;
6809 ev.discovering = discovering;
6810
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006811 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006812}
Antti Julku5e762442011-08-25 16:48:02 +03006813
Marcel Holtmann5976e602013-10-06 04:08:14 -07006814static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6815{
6816 BT_DBG("%s status %u", hdev->name, status);
6817
6818 /* Clear the advertising mgmt setting if we failed to re-enable it */
6819 if (status) {
6820 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006821 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006822 }
6823}
6824
6825void mgmt_reenable_advertising(struct hci_dev *hdev)
6826{
6827 struct hci_request req;
6828
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006829 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006830 return;
6831
6832 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6833 return;
6834
6835 hci_req_init(&req, hdev);
6836 enable_advertising(&req);
6837
6838 /* If this fails we have no option but to let user space know
6839 * that we've disabled advertising.
6840 */
6841 if (hci_req_run(&req, adv_enable_complete) < 0) {
6842 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006843 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006844 }
6845}