blob: e253f8e1fa47955ead2c6d1acea711e325a8ea02 [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 Holtmann04c60f02014-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 Hedbergd7b856f2013-10-14 16:20:04 +03001753 if (changed)
1754 new_settings(hdev, cmd->sk);
1755
Johan Hedberg37438c12013-10-14 16:20:05 +03001756remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001757 mgmt_pending_remove(cmd);
1758
1759unlock:
1760 hci_dev_unlock(hdev);
1761}
1762
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001763static int set_connectable_update_settings(struct hci_dev *hdev,
1764 struct sock *sk, u8 val)
1765{
1766 bool changed = false;
1767 int err;
1768
1769 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1770 changed = true;
1771
1772 if (val) {
1773 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1774 } else {
1775 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1776 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1777 }
1778
1779 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1780 if (err < 0)
1781 return err;
1782
1783 if (changed)
1784 return new_settings(hdev, sk);
1785
1786 return 0;
1787}
1788
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001789static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001790 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001791{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001792 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001793 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001794 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001795 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001796 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001797
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001798 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001799
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001800 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1801 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001802 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001803 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001804
Johan Hedberga7e80f22013-01-09 16:05:19 +02001805 if (cp->val != 0x00 && cp->val != 0x01)
1806 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1807 MGMT_STATUS_INVALID_PARAMS);
1808
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001809 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001810
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001811 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001812 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001813 goto failed;
1814 }
1815
1816 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001817 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001818 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001819 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001820 goto failed;
1821 }
1822
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001823 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1824 if (!cmd) {
1825 err = -ENOMEM;
1826 goto failed;
1827 }
1828
Johan Hedberg2b76f452013-03-15 17:07:04 -05001829 hci_req_init(&req, hdev);
1830
Johan Hedberg9a43e252013-10-20 19:00:07 +03001831 /* If BR/EDR is not enabled and we disable advertising as a
1832 * by-product of disabling connectable, we need to update the
1833 * advertising flags.
1834 */
1835 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1836 if (!cp->val) {
1837 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1838 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1839 }
1840 update_adv_data(&req);
1841 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001842 if (cp->val) {
1843 scan = SCAN_PAGE;
1844 } else {
1845 scan = 0;
1846
1847 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001848 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001849 cancel_delayed_work(&hdev->discov_off);
1850 }
1851
1852 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1853 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001854
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001855 /* If we're going from non-connectable to connectable or
1856 * vice-versa when fast connectable is enabled ensure that fast
1857 * connectable gets disabled. write_fast_connectable won't do
1858 * anything if the page scan parameters are already what they
1859 * should be.
1860 */
1861 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001862 write_fast_connectable(&req, false);
1863
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001864 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1865 hci_conn_num(hdev, LE_LINK) == 0) {
1866 disable_advertising(&req);
1867 enable_advertising(&req);
1868 }
1869
Johan Hedberg2b76f452013-03-15 17:07:04 -05001870 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001871 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001872 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001873 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001874 err = set_connectable_update_settings(hdev, sk,
1875 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001876 goto failed;
1877 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001878
1879failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001880 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001881 return err;
1882}
1883
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001884static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001885 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001886{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001887 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001888 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001889 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001890
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001891 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892
Johan Hedberga7e80f22013-01-09 16:05:19 +02001893 if (cp->val != 0x00 && cp->val != 0x01)
1894 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1895 MGMT_STATUS_INVALID_PARAMS);
1896
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001897 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001898
1899 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001900 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001901 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001902 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001903
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001904 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001905 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001906 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001907
Marcel Holtmann55594352013-10-06 16:11:57 -07001908 if (changed)
1909 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001910
Marcel Holtmann55594352013-10-06 16:11:57 -07001911unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001912 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001913 return err;
1914}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001915
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001916static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1917 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001918{
1919 struct mgmt_mode *cp = data;
1920 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001921 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001922 int err;
1923
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001924 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001925
Johan Hedberge6fe7982013-10-02 15:45:22 +03001926 status = mgmt_bredr_support(hdev);
1927 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001928 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001929 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001930
Johan Hedberga7e80f22013-01-09 16:05:19 +02001931 if (cp->val != 0x00 && cp->val != 0x01)
1932 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1933 MGMT_STATUS_INVALID_PARAMS);
1934
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001935 hci_dev_lock(hdev);
1936
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001937 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001938 bool changed = false;
1939
1940 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001941 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001942 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1943 changed = true;
1944 }
1945
1946 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1947 if (err < 0)
1948 goto failed;
1949
1950 if (changed)
1951 err = new_settings(hdev, sk);
1952
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001953 goto failed;
1954 }
1955
1956 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001957 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001958 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001959 goto failed;
1960 }
1961
1962 val = !!cp->val;
1963
1964 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1965 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1966 goto failed;
1967 }
1968
1969 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1970 if (!cmd) {
1971 err = -ENOMEM;
1972 goto failed;
1973 }
1974
1975 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1976 if (err < 0) {
1977 mgmt_pending_remove(cmd);
1978 goto failed;
1979 }
1980
1981failed:
1982 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001983 return err;
1984}
1985
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001986static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001987{
1988 struct mgmt_mode *cp = data;
1989 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001990 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001991 int err;
1992
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001993 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001994
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001995 status = mgmt_bredr_support(hdev);
1996 if (status)
1997 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1998
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001999 if (!lmp_ssp_capable(hdev))
2000 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2001 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002002
Johan Hedberga7e80f22013-01-09 16:05:19 +02002003 if (cp->val != 0x00 && cp->val != 0x01)
2004 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2005 MGMT_STATUS_INVALID_PARAMS);
2006
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002007 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002008
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002009 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002010 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002011
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002012 if (cp->val) {
2013 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2014 &hdev->dev_flags);
2015 } else {
2016 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2017 &hdev->dev_flags);
2018 if (!changed)
2019 changed = test_and_clear_bit(HCI_HS_ENABLED,
2020 &hdev->dev_flags);
2021 else
2022 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002023 }
2024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2026 if (err < 0)
2027 goto failed;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002032 goto failed;
2033 }
2034
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002035 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2036 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002037 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2038 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002039 goto failed;
2040 }
2041
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002042 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002043 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2044 goto failed;
2045 }
2046
2047 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2048 if (!cmd) {
2049 err = -ENOMEM;
2050 goto failed;
2051 }
2052
Johan Hedberg37699722014-06-24 14:00:27 +03002053 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2054 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2055 sizeof(cp->val), &cp->val);
2056
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002057 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002058 if (err < 0) {
2059 mgmt_pending_remove(cmd);
2060 goto failed;
2061 }
2062
2063failed:
2064 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002065 return err;
2066}
2067
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002068static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002069{
2070 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002071 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002072 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002073 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002074
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002075 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002076
Johan Hedberge6fe7982013-10-02 15:45:22 +03002077 status = mgmt_bredr_support(hdev);
2078 if (status)
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002080
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002081 if (!lmp_ssp_capable(hdev))
2082 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2083 MGMT_STATUS_NOT_SUPPORTED);
2084
2085 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2086 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2087 MGMT_STATUS_REJECTED);
2088
Johan Hedberga7e80f22013-01-09 16:05:19 +02002089 if (cp->val != 0x00 && cp->val != 0x01)
2090 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2091 MGMT_STATUS_INVALID_PARAMS);
2092
Marcel Holtmannee392692013-10-01 22:59:23 -07002093 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002094
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002095 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002096 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002097 } else {
2098 if (hdev_is_powered(hdev)) {
2099 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2100 MGMT_STATUS_REJECTED);
2101 goto unlock;
2102 }
2103
Marcel Holtmannee392692013-10-01 22:59:23 -07002104 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002105 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002106
2107 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2108 if (err < 0)
2109 goto unlock;
2110
2111 if (changed)
2112 err = new_settings(hdev, sk);
2113
2114unlock:
2115 hci_dev_unlock(hdev);
2116 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002117}
2118
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002119static void le_enable_complete(struct hci_dev *hdev, u8 status)
2120{
2121 struct cmd_lookup match = { NULL, hdev };
2122
2123 if (status) {
2124 u8 mgmt_err = mgmt_status(status);
2125
2126 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2127 &mgmt_err);
2128 return;
2129 }
2130
2131 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2132
2133 new_settings(hdev, match.sk);
2134
2135 if (match.sk)
2136 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002137
2138 /* Make sure the controller has a good default for
2139 * advertising data. Restrict the update to when LE
2140 * has actually been enabled. During power on, the
2141 * update in powered_update_hci will take care of it.
2142 */
2143 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2144 struct hci_request req;
2145
2146 hci_dev_lock(hdev);
2147
2148 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002149 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002150 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002151 hci_req_run(&req, NULL);
2152
2153 hci_dev_unlock(hdev);
2154 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002155}
2156
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002157static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002158{
2159 struct mgmt_mode *cp = data;
2160 struct hci_cp_write_le_host_supported hci_cp;
2161 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002162 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002163 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002164 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002166 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002167
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002168 if (!lmp_le_capable(hdev))
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2170 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002171
Johan Hedberga7e80f22013-01-09 16:05:19 +02002172 if (cp->val != 0x00 && cp->val != 0x01)
2173 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2174 MGMT_STATUS_INVALID_PARAMS);
2175
Johan Hedbergc73eee92013-04-19 18:35:21 +03002176 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002177 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002178 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2179 MGMT_STATUS_REJECTED);
2180
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002181 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002182
2183 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002184 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002185
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002186 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002187 bool changed = false;
2188
2189 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2190 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2191 changed = true;
2192 }
2193
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002194 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2195 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002196 changed = true;
2197 }
2198
Johan Hedberg06199cf2012-02-22 16:37:11 +02002199 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2200 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002201 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002202
2203 if (changed)
2204 err = new_settings(hdev, sk);
2205
Johan Hedberg1de028c2012-02-29 19:55:35 -08002206 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002207 }
2208
Johan Hedberg4375f102013-09-25 13:26:10 +03002209 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2210 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002211 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002212 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002213 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002214 }
2215
2216 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2217 if (!cmd) {
2218 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002219 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002220 }
2221
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002222 hci_req_init(&req, hdev);
2223
Johan Hedberg06199cf2012-02-22 16:37:11 +02002224 memset(&hci_cp, 0, sizeof(hci_cp));
2225
2226 if (val) {
2227 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002228 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002229 } else {
2230 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2231 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002232 }
2233
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002234 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2235 &hci_cp);
2236
2237 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302238 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002240
Johan Hedberg1de028c2012-02-29 19:55:35 -08002241unlock:
2242 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002243 return err;
2244}
2245
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002246/* This is a helper function to test for pending mgmt commands that can
2247 * cause CoD or EIR HCI commands. We can only allow one such pending
2248 * mgmt command at a time since otherwise we cannot easily track what
2249 * the current values are, will be, and based on that calculate if a new
2250 * HCI command needs to be sent and if yes with what value.
2251 */
2252static bool pending_eir_or_class(struct hci_dev *hdev)
2253{
2254 struct pending_cmd *cmd;
2255
2256 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2257 switch (cmd->opcode) {
2258 case MGMT_OP_ADD_UUID:
2259 case MGMT_OP_REMOVE_UUID:
2260 case MGMT_OP_SET_DEV_CLASS:
2261 case MGMT_OP_SET_POWERED:
2262 return true;
2263 }
2264 }
2265
2266 return false;
2267}
2268
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002269static const u8 bluetooth_base_uuid[] = {
2270 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2271 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2272};
2273
2274static u8 get_uuid_size(const u8 *uuid)
2275{
2276 u32 val;
2277
2278 if (memcmp(uuid, bluetooth_base_uuid, 12))
2279 return 128;
2280
2281 val = get_unaligned_le32(&uuid[12]);
2282 if (val > 0xffff)
2283 return 32;
2284
2285 return 16;
2286}
2287
Johan Hedberg92da6092013-03-15 17:06:55 -05002288static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2289{
2290 struct pending_cmd *cmd;
2291
2292 hci_dev_lock(hdev);
2293
2294 cmd = mgmt_pending_find(mgmt_op, hdev);
2295 if (!cmd)
2296 goto unlock;
2297
2298 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2299 hdev->dev_class, 3);
2300
2301 mgmt_pending_remove(cmd);
2302
2303unlock:
2304 hci_dev_unlock(hdev);
2305}
2306
2307static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2308{
2309 BT_DBG("status 0x%02x", status);
2310
2311 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2312}
2313
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002314static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002315{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002316 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002317 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002318 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002319 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002320 int err;
2321
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002322 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002323
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002324 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002325
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002326 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002327 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002328 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002329 goto failed;
2330 }
2331
Andre Guedes92c4c202012-06-07 19:05:44 -03002332 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002333 if (!uuid) {
2334 err = -ENOMEM;
2335 goto failed;
2336 }
2337
2338 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002339 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002340 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002341
Johan Hedbergde66aa62013-01-27 00:31:27 +02002342 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002343
Johan Hedberg890ea892013-03-15 17:06:52 -05002344 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002345
Johan Hedberg890ea892013-03-15 17:06:52 -05002346 update_class(&req);
2347 update_eir(&req);
2348
Johan Hedberg92da6092013-03-15 17:06:55 -05002349 err = hci_req_run(&req, add_uuid_complete);
2350 if (err < 0) {
2351 if (err != -ENODATA)
2352 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002354 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002355 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002356 goto failed;
2357 }
2358
2359 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002360 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002361 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002362 goto failed;
2363 }
2364
2365 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002366
2367failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002368 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002369 return err;
2370}
2371
Johan Hedberg24b78d02012-02-23 23:24:30 +02002372static bool enable_service_cache(struct hci_dev *hdev)
2373{
2374 if (!hdev_is_powered(hdev))
2375 return false;
2376
2377 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002378 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2379 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002380 return true;
2381 }
2382
2383 return false;
2384}
2385
Johan Hedberg92da6092013-03-15 17:06:55 -05002386static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2387{
2388 BT_DBG("status 0x%02x", status);
2389
2390 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2391}
2392
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002393static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002394 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002395{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002396 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002397 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002398 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002399 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 -05002400 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 int err, found;
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002405 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002407 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002410 goto unlock;
2411 }
2412
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002413 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002414 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002415
Johan Hedberg24b78d02012-02-23 23:24:30 +02002416 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002417 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002418 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002419 goto unlock;
2420 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002421
Johan Hedberg9246a862012-02-23 21:33:16 +02002422 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002423 }
2424
2425 found = 0;
2426
Johan Hedberg056341c2013-01-27 00:31:30 +02002427 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002428 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2429 continue;
2430
2431 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002432 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002433 found++;
2434 }
2435
2436 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002437 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002438 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002439 goto unlock;
2440 }
2441
Johan Hedberg9246a862012-02-23 21:33:16 +02002442update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002443 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002444
Johan Hedberg890ea892013-03-15 17:06:52 -05002445 update_class(&req);
2446 update_eir(&req);
2447
Johan Hedberg92da6092013-03-15 17:06:55 -05002448 err = hci_req_run(&req, remove_uuid_complete);
2449 if (err < 0) {
2450 if (err != -ENODATA)
2451 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002452
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002453 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002454 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002455 goto unlock;
2456 }
2457
2458 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002459 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002460 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002461 goto unlock;
2462 }
2463
2464 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002465
2466unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002467 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002468 return err;
2469}
2470
Johan Hedberg92da6092013-03-15 17:06:55 -05002471static void set_class_complete(struct hci_dev *hdev, u8 status)
2472{
2473 BT_DBG("status 0x%02x", status);
2474
2475 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2476}
2477
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002478static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002479 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002480{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002481 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002482 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002483 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002484 int err;
2485
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002486 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002487
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002488 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002489 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2490 MGMT_STATUS_NOT_SUPPORTED);
2491
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002492 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002493
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002494 if (pending_eir_or_class(hdev)) {
2495 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2496 MGMT_STATUS_BUSY);
2497 goto unlock;
2498 }
2499
2500 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2501 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2502 MGMT_STATUS_INVALID_PARAMS);
2503 goto unlock;
2504 }
2505
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002506 hdev->major_class = cp->major;
2507 hdev->minor_class = cp->minor;
2508
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002509 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002510 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002511 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002512 goto unlock;
2513 }
2514
Johan Hedberg890ea892013-03-15 17:06:52 -05002515 hci_req_init(&req, hdev);
2516
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002517 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002518 hci_dev_unlock(hdev);
2519 cancel_delayed_work_sync(&hdev->service_cache);
2520 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002521 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002522 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002523
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 update_class(&req);
2525
Johan Hedberg92da6092013-03-15 17:06:55 -05002526 err = hci_req_run(&req, set_class_complete);
2527 if (err < 0) {
2528 if (err != -ENODATA)
2529 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002530
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002531 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002532 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002533 goto unlock;
2534 }
2535
2536 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002537 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002538 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002539 goto unlock;
2540 }
2541
2542 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002543
Johan Hedbergb5235a62012-02-21 14:32:24 +02002544unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002545 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002546 return err;
2547}
2548
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002549static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002550 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002551{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002552 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002553 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2554 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002555 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002556 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002557 int i;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002558
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002559 BT_DBG("request for %s", hdev->name);
2560
2561 if (!lmp_bredr_capable(hdev))
2562 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2563 MGMT_STATUS_NOT_SUPPORTED);
2564
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002565 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002566 if (key_count > max_key_count) {
2567 BT_ERR("load_link_keys: too big key_count value %u",
2568 key_count);
2569 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2570 MGMT_STATUS_INVALID_PARAMS);
2571 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002572
Johan Hedberg86742e12011-11-07 23:13:38 +02002573 expected_len = sizeof(*cp) + key_count *
2574 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002575 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002576 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002577 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002578 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002579 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002580 }
2581
Johan Hedberg4ae14302013-01-20 14:27:13 +02002582 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2583 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2584 MGMT_STATUS_INVALID_PARAMS);
2585
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002586 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002587 key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002588
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002589 for (i = 0; i < key_count; i++) {
2590 struct mgmt_link_key_info *key = &cp->keys[i];
2591
Marcel Holtmann8e991132014-01-10 02:07:25 -08002592 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002593 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2594 MGMT_STATUS_INVALID_PARAMS);
2595 }
2596
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002597 hci_dev_lock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002598
2599 hci_link_keys_clear(hdev);
2600
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002601 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002602 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2603 &hdev->dev_flags);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002604 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002605 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2606 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002607
2608 if (changed)
2609 new_settings(hdev, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002610
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002611 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002612 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002613
Johan Hedberg58e92932014-06-24 14:00:26 +03002614 /* Always ignore debug keys and require a new pairing if
2615 * the user wants to use them.
2616 */
2617 if (key->type == HCI_LK_DEBUG_COMBINATION)
2618 continue;
2619
Johan Hedberg7652ff62014-06-24 13:15:49 +03002620 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2621 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002622 }
2623
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002624 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002625
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002626 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002627
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002628 return 0;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002629}
2630
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002631static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002632 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002633{
2634 struct mgmt_ev_device_unpaired ev;
2635
2636 bacpy(&ev.addr.bdaddr, bdaddr);
2637 ev.addr.type = addr_type;
2638
2639 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002640 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002641}
2642
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002643static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002644 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002645{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002646 struct mgmt_cp_unpair_device *cp = data;
2647 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002648 struct hci_cp_disconnect dc;
2649 struct pending_cmd *cmd;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002650 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002651 int err;
2652
Johan Hedberga8a1d192011-11-10 15:54:38 +02002653 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002654 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2655 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002656
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002657 if (!bdaddr_type_is_valid(cp->addr.type))
2658 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2659 MGMT_STATUS_INVALID_PARAMS,
2660 &rp, sizeof(rp));
2661
Johan Hedberg118da702013-01-20 14:27:20 +02002662 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2663 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2664 MGMT_STATUS_INVALID_PARAMS,
2665 &rp, sizeof(rp));
2666
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002667 hci_dev_lock(hdev);
2668
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002669 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002670 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002671 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002672 goto unlock;
2673 }
2674
Johan Hedberge0b2b272014-02-18 17:14:31 +02002675 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002676 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002677 } else {
2678 u8 addr_type;
2679
2680 if (cp->addr.type == BDADDR_LE_PUBLIC)
2681 addr_type = ADDR_LE_DEV_PUBLIC;
2682 else
2683 addr_type = ADDR_LE_DEV_RANDOM;
2684
Johan Hedberga7ec7332014-02-18 17:14:35 +02002685 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2686
Andre Guedesa9b0a042014-02-26 20:21:52 -03002687 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2688
Johan Hedberge0b2b272014-02-18 17:14:31 +02002689 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2690 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002691
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002692 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002693 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002694 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002695 goto unlock;
2696 }
2697
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002698 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002699 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002700 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002701 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002702 else
2703 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002704 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002705 } else {
2706 conn = NULL;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002707 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002708
Johan Hedberga8a1d192011-11-10 15:54:38 +02002709 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002710 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002711 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002712 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002713 goto unlock;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002714 }
2715
Johan Hedberg124f6e32012-02-09 13:50:12 +02002716 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002717 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002718 if (!cmd) {
2719 err = -ENOMEM;
2720 goto unlock;
2721 }
2722
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002723 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002724 dc.reason = 0x13; /* Remote User Terminated Connection */
2725 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2726 if (err < 0)
2727 mgmt_pending_remove(cmd);
2728
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002729unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002730 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002731 return err;
2732}
2733
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002734static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002735 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002736{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002737 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002738 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002739 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002740 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002741 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002742 int err;
2743
2744 BT_DBG("");
2745
Johan Hedberg06a63b12013-01-20 14:27:21 +02002746 memset(&rp, 0, sizeof(rp));
2747 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2748 rp.addr.type = cp->addr.type;
2749
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002750 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002751 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2752 MGMT_STATUS_INVALID_PARAMS,
2753 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002754
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002755 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002756
2757 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002758 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2759 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002760 goto failed;
2761 }
2762
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002763 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002764 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2765 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002766 goto failed;
2767 }
2768
Andre Guedes591f47f2012-04-24 21:02:49 -03002769 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002770 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2771 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002772 else
2773 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002774
Vishal Agarwalf9607272012-06-13 05:32:43 +05302775 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002776 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2777 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002778 goto failed;
2779 }
2780
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002781 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002782 if (!cmd) {
2783 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002784 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002785 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002786
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002787 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002788 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002789
2790 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2791 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002792 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002793
2794failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002795 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002796 return err;
2797}
2798
Andre Guedes57c14772012-04-24 21:02:50 -03002799static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002800{
2801 switch (link_type) {
2802 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002803 switch (addr_type) {
2804 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002805 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002806
Johan Hedberg48264f02011-11-09 13:58:58 +02002807 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002808 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002809 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002810 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002811
Johan Hedberg4c659c32011-11-07 23:13:39 +02002812 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002813 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002814 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002815 }
2816}
2817
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002818static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2819 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002820{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002821 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002822 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002823 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002824 int err;
2825 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002826
2827 BT_DBG("");
2828
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002829 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002830
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002831 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002832 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002833 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002834 goto unlock;
2835 }
2836
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002837 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002838 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2839 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002840 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002841 }
2842
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002843 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002844 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002845 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002846 err = -ENOMEM;
2847 goto unlock;
2848 }
2849
Johan Hedberg2784eb42011-01-21 13:56:35 +02002850 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002851 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002852 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2853 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002854 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002855 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002856 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002857 continue;
2858 i++;
2859 }
2860
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002861 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002862
Johan Hedberg4c659c32011-11-07 23:13:39 +02002863 /* Recalculate length in case of filtered SCO connections, etc */
2864 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002865
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002866 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002867 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002868
Johan Hedberga38528f2011-01-22 06:46:43 +02002869 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002870
2871unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002872 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002873 return err;
2874}
2875
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002876static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002877 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002878{
2879 struct pending_cmd *cmd;
2880 int err;
2881
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002882 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002883 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002884 if (!cmd)
2885 return -ENOMEM;
2886
Johan Hedbergd8457692012-02-17 14:24:57 +02002887 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002888 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002889 if (err < 0)
2890 mgmt_pending_remove(cmd);
2891
2892 return err;
2893}
2894
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002895static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002896 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002897{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002898 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002899 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002900 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002901 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002902 int err;
2903
2904 BT_DBG("");
2905
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002906 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002907
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002908 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002909 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002910 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002911 goto failed;
2912 }
2913
Johan Hedbergd8457692012-02-17 14:24:57 +02002914 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002915 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002916 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002917 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002918 goto failed;
2919 }
2920
2921 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002922 struct mgmt_cp_pin_code_neg_reply ncp;
2923
2924 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002925
2926 BT_ERR("PIN code is not 16 bytes long");
2927
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002928 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002929 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002930 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002931 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002932
2933 goto failed;
2934 }
2935
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002936 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002937 if (!cmd) {
2938 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002939 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002940 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002941
Johan Hedbergd8457692012-02-17 14:24:57 +02002942 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002943 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002944 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002945
2946 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2947 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002948 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002949
2950failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002951 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002952 return err;
2953}
2954
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002955static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2956 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002957{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002958 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002959
2960 BT_DBG("");
2961
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002962 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2963 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2964 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2965
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002966 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002967
2968 hdev->io_capability = cp->io_capability;
2969
2970 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002971 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002972
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002973 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002974
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002975 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2976 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002977}
2978
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002979static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002980{
2981 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002982 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002983
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002984 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002985 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2986 continue;
2987
Johan Hedberge9a416b2011-02-19 12:05:56 -03002988 if (cmd->user_data != conn)
2989 continue;
2990
2991 return cmd;
2992 }
2993
2994 return NULL;
2995}
2996
2997static void pairing_complete(struct pending_cmd *cmd, u8 status)
2998{
2999 struct mgmt_rp_pair_device rp;
3000 struct hci_conn *conn = cmd->user_data;
3001
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003002 bacpy(&rp.addr.bdaddr, &conn->dst);
3003 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003005 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003006 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003007
3008 /* So we don't get further callbacks for this connection */
3009 conn->connect_cfm_cb = NULL;
3010 conn->security_cfm_cb = NULL;
3011 conn->disconn_cfm_cb = NULL;
3012
David Herrmann76a68ba2013-04-06 20:28:37 +02003013 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003014
Johan Hedberga664b5b2011-02-19 12:06:02 -03003015 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003016}
3017
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003018void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3019{
3020 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3021 struct pending_cmd *cmd;
3022
3023 cmd = find_pairing(conn);
3024 if (cmd)
3025 pairing_complete(cmd, status);
3026}
3027
Johan Hedberge9a416b2011-02-19 12:05:56 -03003028static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3029{
3030 struct pending_cmd *cmd;
3031
3032 BT_DBG("status %u", status);
3033
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003034 cmd = find_pairing(conn);
3035 if (!cmd)
3036 BT_DBG("Unable to find a pending command");
3037 else
Johan Hedberge2113262012-02-18 15:20:03 +02003038 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003039}
3040
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003041static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303042{
3043 struct pending_cmd *cmd;
3044
3045 BT_DBG("status %u", status);
3046
3047 if (!status)
3048 return;
3049
3050 cmd = find_pairing(conn);
3051 if (!cmd)
3052 BT_DBG("Unable to find a pending command");
3053 else
3054 pairing_complete(cmd, mgmt_status(status));
3055}
3056
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003057static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003058 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003059{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003060 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003061 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003062 struct pending_cmd *cmd;
3063 u8 sec_level, auth_type;
3064 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003065 int err;
3066
3067 BT_DBG("");
3068
Szymon Jancf950a30e2013-01-18 12:48:07 +01003069 memset(&rp, 0, sizeof(rp));
3070 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3071 rp.addr.type = cp->addr.type;
3072
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003073 if (!bdaddr_type_is_valid(cp->addr.type))
3074 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3075 MGMT_STATUS_INVALID_PARAMS,
3076 &rp, sizeof(rp));
3077
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003078 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3079 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3080 MGMT_STATUS_INVALID_PARAMS,
3081 &rp, sizeof(rp));
3082
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003083 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003084
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003085 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003086 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3087 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003088 goto unlock;
3089 }
3090
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003091 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003092 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003093
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003094 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003095 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3096 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003097 } else {
3098 u8 addr_type;
3099
3100 /* Convert from L2CAP channel address type to HCI address type
3101 */
3102 if (cp->addr.type == BDADDR_LE_PUBLIC)
3103 addr_type = ADDR_LE_DEV_PUBLIC;
3104 else
3105 addr_type = ADDR_LE_DEV_RANDOM;
3106
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003107 /* When pairing a new device, it is expected to remember
3108 * this device for future connections. Adding the connection
3109 * parameter information ahead of time allows tracking
3110 * of the slave preferred values and will speed up any
3111 * further connection establishment.
3112 *
3113 * If connection parameters already exist, then they
3114 * will be kept and this function does nothing.
3115 */
3116 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3117
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003118 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03003119 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003120 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003121
Ville Tervo30e76272011-02-22 16:10:53 -03003122 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003123 int status;
3124
3125 if (PTR_ERR(conn) == -EBUSY)
3126 status = MGMT_STATUS_BUSY;
3127 else
3128 status = MGMT_STATUS_CONNECT_FAILED;
3129
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003130 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003131 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003132 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003133 goto unlock;
3134 }
3135
3136 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003137 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003138 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003139 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003140 goto unlock;
3141 }
3142
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003143 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003144 if (!cmd) {
3145 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003146 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003147 goto unlock;
3148 }
3149
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003150 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003151 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003152 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003153 conn->security_cfm_cb = pairing_complete_cb;
3154 conn->disconn_cfm_cb = pairing_complete_cb;
3155 } else {
3156 conn->connect_cfm_cb = le_pairing_complete_cb;
3157 conn->security_cfm_cb = le_pairing_complete_cb;
3158 conn->disconn_cfm_cb = le_pairing_complete_cb;
3159 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003160
Johan Hedberge9a416b2011-02-19 12:05:56 -03003161 conn->io_capability = cp->io_cap;
3162 cmd->user_data = conn;
3163
3164 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003165 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166 pairing_complete(cmd, 0);
3167
3168 err = 0;
3169
3170unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003171 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003172 return err;
3173}
3174
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003175static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3176 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003177{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003178 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003179 struct pending_cmd *cmd;
3180 struct hci_conn *conn;
3181 int err;
3182
3183 BT_DBG("");
3184
Johan Hedberg28424702012-02-02 04:02:29 +02003185 hci_dev_lock(hdev);
3186
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003187 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003188 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003189 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003190 goto unlock;
3191 }
3192
Johan Hedberg28424702012-02-02 04:02:29 +02003193 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3194 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003195 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003196 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003197 goto unlock;
3198 }
3199
3200 conn = cmd->user_data;
3201
3202 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003203 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003204 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003205 goto unlock;
3206 }
3207
3208 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3209
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003210 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003211 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003212unlock:
3213 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003214 return err;
3215}
3216
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003217static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003218 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003219 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003220{
Johan Hedberga5c29682011-02-19 12:05:57 -03003221 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003222 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003223 int err;
3224
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003225 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003226
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003227 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003228 err = cmd_complete(sk, hdev->id, mgmt_op,
3229 MGMT_STATUS_NOT_POWERED, addr,
3230 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003231 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003232 }
3233
Johan Hedberg1707c602013-03-15 17:07:15 -05003234 if (addr->type == BDADDR_BREDR)
3235 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003236 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003237 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003238
Johan Hedberg272d90d2012-02-09 15:26:12 +02003239 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003240 err = cmd_complete(sk, hdev->id, mgmt_op,
3241 MGMT_STATUS_NOT_CONNECTED, addr,
3242 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003243 goto done;
3244 }
3245
Johan Hedberg1707c602013-03-15 17:07:15 -05003246 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003247 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003248 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003249 err = cmd_complete(sk, hdev->id, mgmt_op,
3250 MGMT_STATUS_SUCCESS, addr,
3251 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003252 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003253 err = cmd_complete(sk, hdev->id, mgmt_op,
3254 MGMT_STATUS_FAILED, addr,
3255 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003256
Brian Gix47c15e22011-11-16 13:53:14 -08003257 goto done;
3258 }
3259
Johan Hedberg1707c602013-03-15 17:07:15 -05003260 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003261 if (!cmd) {
3262 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003263 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003264 }
3265
Brian Gix0df4c182011-11-16 13:53:13 -08003266 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003267 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3268 struct hci_cp_user_passkey_reply cp;
3269
Johan Hedberg1707c602013-03-15 17:07:15 -05003270 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003271 cp.passkey = passkey;
3272 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3273 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003274 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3275 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003276
Johan Hedberga664b5b2011-02-19 12:06:02 -03003277 if (err < 0)
3278 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003279
Brian Gix0df4c182011-11-16 13:53:13 -08003280done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003281 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003282 return err;
3283}
3284
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303285static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3286 void *data, u16 len)
3287{
3288 struct mgmt_cp_pin_code_neg_reply *cp = data;
3289
3290 BT_DBG("");
3291
Johan Hedberg1707c602013-03-15 17:07:15 -05003292 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303293 MGMT_OP_PIN_CODE_NEG_REPLY,
3294 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3295}
3296
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003297static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3298 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003299{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003300 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003301
3302 BT_DBG("");
3303
3304 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003306 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003307
Johan Hedberg1707c602013-03-15 17:07:15 -05003308 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003309 MGMT_OP_USER_CONFIRM_REPLY,
3310 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003311}
3312
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003313static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003314 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003315{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003316 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003317
3318 BT_DBG("");
3319
Johan Hedberg1707c602013-03-15 17:07:15 -05003320 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003321 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3322 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003323}
3324
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003325static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3326 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003327{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003328 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003329
3330 BT_DBG("");
3331
Johan Hedberg1707c602013-03-15 17:07:15 -05003332 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003333 MGMT_OP_USER_PASSKEY_REPLY,
3334 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003335}
3336
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003337static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003338 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003339{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003340 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003341
3342 BT_DBG("");
3343
Johan Hedberg1707c602013-03-15 17:07:15 -05003344 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003345 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3346 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003347}
3348
Johan Hedberg13928972013-03-15 17:07:00 -05003349static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003350{
Johan Hedberg13928972013-03-15 17:07:00 -05003351 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003352 struct hci_cp_write_local_name cp;
3353
Johan Hedberg13928972013-03-15 17:07:00 -05003354 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003355
Johan Hedberg890ea892013-03-15 17:06:52 -05003356 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003357}
3358
Johan Hedberg13928972013-03-15 17:07:00 -05003359static void set_name_complete(struct hci_dev *hdev, u8 status)
3360{
3361 struct mgmt_cp_set_local_name *cp;
3362 struct pending_cmd *cmd;
3363
3364 BT_DBG("status 0x%02x", status);
3365
3366 hci_dev_lock(hdev);
3367
3368 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3369 if (!cmd)
3370 goto unlock;
3371
3372 cp = cmd->param;
3373
3374 if (status)
3375 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3376 mgmt_status(status));
3377 else
3378 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3379 cp, sizeof(*cp));
3380
3381 mgmt_pending_remove(cmd);
3382
3383unlock:
3384 hci_dev_unlock(hdev);
3385}
3386
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003387static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003388 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003389{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003390 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003391 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003392 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003393 int err;
3394
3395 BT_DBG("");
3396
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003397 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003398
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003399 /* If the old values are the same as the new ones just return a
3400 * direct command complete event.
3401 */
3402 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3403 !memcmp(hdev->short_name, cp->short_name,
3404 sizeof(hdev->short_name))) {
3405 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3406 data, len);
3407 goto failed;
3408 }
3409
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003410 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003411
Johan Hedbergb5235a62012-02-21 14:32:24 +02003412 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003413 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003414
3415 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003416 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003417 if (err < 0)
3418 goto failed;
3419
3420 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003421 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003422
Johan Hedbergb5235a62012-02-21 14:32:24 +02003423 goto failed;
3424 }
3425
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003426 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003427 if (!cmd) {
3428 err = -ENOMEM;
3429 goto failed;
3430 }
3431
Johan Hedberg13928972013-03-15 17:07:00 -05003432 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3433
Johan Hedberg890ea892013-03-15 17:06:52 -05003434 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003435
3436 if (lmp_bredr_capable(hdev)) {
3437 update_name(&req);
3438 update_eir(&req);
3439 }
3440
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003441 /* The name is stored in the scan response data and so
3442 * no need to udpate the advertising data here.
3443 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003444 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003445 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003446
Johan Hedberg13928972013-03-15 17:07:00 -05003447 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003448 if (err < 0)
3449 mgmt_pending_remove(cmd);
3450
3451failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003452 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003453 return err;
3454}
3455
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003456static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003457 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003458{
Szymon Jancc35938b2011-03-22 13:12:21 +01003459 struct pending_cmd *cmd;
3460 int err;
3461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003462 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003463
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003464 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003465
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003466 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003467 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003468 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003469 goto unlock;
3470 }
3471
Andre Guedes9a1a1992012-07-24 15:03:48 -03003472 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003473 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003474 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003475 goto unlock;
3476 }
3477
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003478 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003479 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003480 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003481 goto unlock;
3482 }
3483
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003484 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003485 if (!cmd) {
3486 err = -ENOMEM;
3487 goto unlock;
3488 }
3489
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003490 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3491 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3492 0, NULL);
3493 else
3494 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3495
Szymon Jancc35938b2011-03-22 13:12:21 +01003496 if (err < 0)
3497 mgmt_pending_remove(cmd);
3498
3499unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003500 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003501 return err;
3502}
3503
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003504static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003505 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003506{
Szymon Janc2763eda2011-03-22 13:12:22 +01003507 int err;
3508
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003509 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003510
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003511 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003512
Marcel Holtmannec109112014-01-10 02:07:30 -08003513 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3514 struct mgmt_cp_add_remote_oob_data *cp = data;
3515 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003516
Marcel Holtmannec109112014-01-10 02:07:30 -08003517 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3518 cp->hash, cp->randomizer);
3519 if (err < 0)
3520 status = MGMT_STATUS_FAILED;
3521 else
3522 status = MGMT_STATUS_SUCCESS;
3523
3524 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3525 status, &cp->addr, sizeof(cp->addr));
3526 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3527 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3528 u8 status;
3529
3530 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3531 cp->hash192,
3532 cp->randomizer192,
3533 cp->hash256,
3534 cp->randomizer256);
3535 if (err < 0)
3536 status = MGMT_STATUS_FAILED;
3537 else
3538 status = MGMT_STATUS_SUCCESS;
3539
3540 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3541 status, &cp->addr, sizeof(cp->addr));
3542 } else {
3543 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3544 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3545 MGMT_STATUS_INVALID_PARAMS);
3546 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003547
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003548 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003549 return err;
3550}
3551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003552static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003553 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003554{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003555 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003556 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003557 int err;
3558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003559 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003560
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003561 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003562
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003563 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003564 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003565 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003566 else
Szymon Janca6785be2012-12-13 15:11:21 +01003567 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003568
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003569 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003570 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003571
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003572 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003573 return err;
3574}
3575
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003576static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3577{
3578 struct pending_cmd *cmd;
3579 u8 type;
3580 int err;
3581
3582 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3583
3584 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3585 if (!cmd)
3586 return -ENOENT;
3587
3588 type = hdev->discovery.type;
3589
3590 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3591 &type, sizeof(type));
3592 mgmt_pending_remove(cmd);
3593
3594 return err;
3595}
3596
Andre Guedes7c307722013-04-30 15:29:28 -03003597static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3598{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003599 unsigned long timeout = 0;
3600
Andre Guedes7c307722013-04-30 15:29:28 -03003601 BT_DBG("status %d", status);
3602
3603 if (status) {
3604 hci_dev_lock(hdev);
3605 mgmt_start_discovery_failed(hdev, status);
3606 hci_dev_unlock(hdev);
3607 return;
3608 }
3609
3610 hci_dev_lock(hdev);
3611 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3612 hci_dev_unlock(hdev);
3613
3614 switch (hdev->discovery.type) {
3615 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003616 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003617 break;
3618
3619 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003620 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003621 break;
3622
3623 case DISCOV_TYPE_BREDR:
3624 break;
3625
3626 default:
3627 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3628 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003629
3630 if (!timeout)
3631 return;
3632
3633 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003634}
3635
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003636static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003637 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003638{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003639 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003640 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003641 struct hci_cp_le_set_scan_param param_cp;
3642 struct hci_cp_le_set_scan_enable enable_cp;
3643 struct hci_cp_inquiry inq_cp;
3644 struct hci_request req;
3645 /* General inquiry access code (GIAC) */
3646 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003647 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003648 int err;
3649
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003650 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003651
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003652 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003653
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003654 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003655 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003656 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003657 goto failed;
3658 }
3659
Andre Guedes642be6c2012-03-21 00:03:37 -03003660 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3661 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3662 MGMT_STATUS_BUSY);
3663 goto failed;
3664 }
3665
Johan Hedbergff9ef572012-01-04 14:23:45 +02003666 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003667 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003668 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003669 goto failed;
3670 }
3671
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003672 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003673 if (!cmd) {
3674 err = -ENOMEM;
3675 goto failed;
3676 }
3677
Andre Guedes4aab14e2012-02-17 20:39:36 -03003678 hdev->discovery.type = cp->type;
3679
Andre Guedes7c307722013-04-30 15:29:28 -03003680 hci_req_init(&req, hdev);
3681
Andre Guedes4aab14e2012-02-17 20:39:36 -03003682 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003683 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003684 status = mgmt_bredr_support(hdev);
3685 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003686 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003687 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003688 mgmt_pending_remove(cmd);
3689 goto failed;
3690 }
3691
Andre Guedes7c307722013-04-30 15:29:28 -03003692 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3693 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3694 MGMT_STATUS_BUSY);
3695 mgmt_pending_remove(cmd);
3696 goto failed;
3697 }
3698
3699 hci_inquiry_cache_flush(hdev);
3700
3701 memset(&inq_cp, 0, sizeof(inq_cp));
3702 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003703 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003704 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003705 break;
3706
3707 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003708 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003709 status = mgmt_le_support(hdev);
3710 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003711 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003712 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003713 mgmt_pending_remove(cmd);
3714 goto failed;
3715 }
3716
Andre Guedes7c307722013-04-30 15:29:28 -03003717 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003718 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003719 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3720 MGMT_STATUS_NOT_SUPPORTED);
3721 mgmt_pending_remove(cmd);
3722 goto failed;
3723 }
3724
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003725 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003726 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3727 MGMT_STATUS_REJECTED);
3728 mgmt_pending_remove(cmd);
3729 goto failed;
3730 }
3731
Andre Guedesc54c3862014-02-26 20:21:50 -03003732 /* If controller is scanning, it means the background scanning
3733 * is running. Thus, we should temporarily stop it in order to
3734 * set the discovery scanning parameters.
3735 */
3736 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3737 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003738
3739 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003740
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003741 /* All active scans will be done with either a resolvable
3742 * private address (when privacy feature has been enabled)
3743 * or unresolvable private address.
3744 */
3745 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003746 if (err < 0) {
3747 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3748 MGMT_STATUS_FAILED);
3749 mgmt_pending_remove(cmd);
3750 goto failed;
3751 }
3752
Andre Guedes7c307722013-04-30 15:29:28 -03003753 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003754 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3755 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003756 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003757 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3758 &param_cp);
3759
3760 memset(&enable_cp, 0, sizeof(enable_cp));
3761 enable_cp.enable = LE_SCAN_ENABLE;
3762 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3763 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3764 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003765 break;
3766
Andre Guedesf39799f2012-02-17 20:39:35 -03003767 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003768 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3769 MGMT_STATUS_INVALID_PARAMS);
3770 mgmt_pending_remove(cmd);
3771 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003772 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003773
Andre Guedes7c307722013-04-30 15:29:28 -03003774 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003775 if (err < 0)
3776 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003777 else
3778 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003779
3780failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003781 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003782 return err;
3783}
3784
Andre Guedes1183fdc2013-04-30 15:29:35 -03003785static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3786{
3787 struct pending_cmd *cmd;
3788 int err;
3789
3790 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3791 if (!cmd)
3792 return -ENOENT;
3793
3794 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3795 &hdev->discovery.type, sizeof(hdev->discovery.type));
3796 mgmt_pending_remove(cmd);
3797
3798 return err;
3799}
3800
Andre Guedes0e05bba2013-04-30 15:29:33 -03003801static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3802{
3803 BT_DBG("status %d", status);
3804
3805 hci_dev_lock(hdev);
3806
3807 if (status) {
3808 mgmt_stop_discovery_failed(hdev, status);
3809 goto unlock;
3810 }
3811
3812 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3813
3814unlock:
3815 hci_dev_unlock(hdev);
3816}
3817
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003818static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003819 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003820{
Johan Hedbergd9306502012-02-20 23:25:18 +02003821 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003822 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003823 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003824 int err;
3825
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003826 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003827
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003828 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003829
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003830 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003831 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003832 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3833 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003834 goto unlock;
3835 }
3836
3837 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003838 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003839 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3840 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003841 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003842 }
3843
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003844 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003845 if (!cmd) {
3846 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003847 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003848 }
3849
Andre Guedes0e05bba2013-04-30 15:29:33 -03003850 hci_req_init(&req, hdev);
3851
Johan Hedberg21a60d32014-06-10 14:05:58 +03003852 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003853
Johan Hedberg21a60d32014-06-10 14:05:58 +03003854 err = hci_req_run(&req, stop_discovery_complete);
3855 if (!err) {
3856 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003857 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003858 }
3859
Johan Hedberg21a60d32014-06-10 14:05:58 +03003860 mgmt_pending_remove(cmd);
3861
3862 /* If no HCI commands were sent we're done */
3863 if (err == -ENODATA) {
3864 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3865 &mgmt_cp->type, sizeof(mgmt_cp->type));
3866 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3867 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003868
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003869unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003870 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003871 return err;
3872}
3873
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003874static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003875 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003876{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003877 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003878 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003879 int err;
3880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003881 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003882
Johan Hedberg561aafb2012-01-04 13:31:59 +02003883 hci_dev_lock(hdev);
3884
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003885 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003886 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3887 MGMT_STATUS_FAILED, &cp->addr,
3888 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003889 goto failed;
3890 }
3891
Johan Hedberga198e7b2012-02-17 14:27:06 +02003892 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003893 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003894 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3895 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3896 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003897 goto failed;
3898 }
3899
3900 if (cp->name_known) {
3901 e->name_state = NAME_KNOWN;
3902 list_del(&e->list);
3903 } else {
3904 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003905 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003906 }
3907
Johan Hedberge3846622013-01-09 15:29:33 +02003908 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3909 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003910
3911failed:
3912 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003913 return err;
3914}
3915
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003916static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003917 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003918{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003919 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003920 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003921 int err;
3922
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003923 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003924
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003925 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003926 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3927 MGMT_STATUS_INVALID_PARAMS,
3928 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003929
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003930 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003931
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003932 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003933 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003934 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003935 goto done;
3936 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003937
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003938 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3939 sk);
3940 status = MGMT_STATUS_SUCCESS;
3941
3942done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003943 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003944 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003945
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003946 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003947
3948 return err;
3949}
3950
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003951static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003952 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003953{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003954 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003955 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003956 int err;
3957
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003958 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003959
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003960 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003961 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3962 MGMT_STATUS_INVALID_PARAMS,
3963 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003964
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003965 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003966
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003967 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003968 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003969 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003970 goto done;
3971 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003972
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003973 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3974 sk);
3975 status = MGMT_STATUS_SUCCESS;
3976
3977done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003978 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003979 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003980
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003981 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003982
3983 return err;
3984}
3985
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003986static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3987 u16 len)
3988{
3989 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003990 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003991 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003992 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003993
3994 BT_DBG("%s", hdev->name);
3995
Szymon Jancc72d4b82012-03-16 16:02:57 +01003996 source = __le16_to_cpu(cp->source);
3997
3998 if (source > 0x0002)
3999 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4000 MGMT_STATUS_INVALID_PARAMS);
4001
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004002 hci_dev_lock(hdev);
4003
Szymon Jancc72d4b82012-03-16 16:02:57 +01004004 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004005 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4006 hdev->devid_product = __le16_to_cpu(cp->product);
4007 hdev->devid_version = __le16_to_cpu(cp->version);
4008
4009 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4010
Johan Hedberg890ea892013-03-15 17:06:52 -05004011 hci_req_init(&req, hdev);
4012 update_eir(&req);
4013 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004014
4015 hci_dev_unlock(hdev);
4016
4017 return err;
4018}
4019
Johan Hedberg4375f102013-09-25 13:26:10 +03004020static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4021{
4022 struct cmd_lookup match = { NULL, hdev };
4023
4024 if (status) {
4025 u8 mgmt_err = mgmt_status(status);
4026
4027 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4028 cmd_status_rsp, &mgmt_err);
4029 return;
4030 }
4031
4032 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4033 &match);
4034
4035 new_settings(hdev, match.sk);
4036
4037 if (match.sk)
4038 sock_put(match.sk);
4039}
4040
Marcel Holtmann21b51872013-10-10 09:47:53 -07004041static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4042 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004043{
4044 struct mgmt_mode *cp = data;
4045 struct pending_cmd *cmd;
4046 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004047 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004048 int err;
4049
4050 BT_DBG("request for %s", hdev->name);
4051
Johan Hedberge6fe7982013-10-02 15:45:22 +03004052 status = mgmt_le_support(hdev);
4053 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004054 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004055 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004056
4057 if (cp->val != 0x00 && cp->val != 0x01)
4058 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4059 MGMT_STATUS_INVALID_PARAMS);
4060
4061 hci_dev_lock(hdev);
4062
4063 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004064 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004065
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004066 /* The following conditions are ones which mean that we should
4067 * not do any HCI communication but directly send a mgmt
4068 * response to user space (after toggling the flag if
4069 * necessary).
4070 */
4071 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004072 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004073 bool changed = false;
4074
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004075 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4076 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004077 changed = true;
4078 }
4079
4080 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4081 if (err < 0)
4082 goto unlock;
4083
4084 if (changed)
4085 err = new_settings(hdev, sk);
4086
4087 goto unlock;
4088 }
4089
4090 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4091 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4092 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4093 MGMT_STATUS_BUSY);
4094 goto unlock;
4095 }
4096
4097 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4098 if (!cmd) {
4099 err = -ENOMEM;
4100 goto unlock;
4101 }
4102
4103 hci_req_init(&req, hdev);
4104
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004105 if (val)
4106 enable_advertising(&req);
4107 else
4108 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004109
4110 err = hci_req_run(&req, set_advertising_complete);
4111 if (err < 0)
4112 mgmt_pending_remove(cmd);
4113
4114unlock:
4115 hci_dev_unlock(hdev);
4116 return err;
4117}
4118
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004119static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4120 void *data, u16 len)
4121{
4122 struct mgmt_cp_set_static_address *cp = data;
4123 int err;
4124
4125 BT_DBG("%s", hdev->name);
4126
Marcel Holtmann62af4442013-10-02 22:10:32 -07004127 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004128 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004129 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004130
4131 if (hdev_is_powered(hdev))
4132 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4133 MGMT_STATUS_REJECTED);
4134
4135 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4136 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4137 return cmd_status(sk, hdev->id,
4138 MGMT_OP_SET_STATIC_ADDRESS,
4139 MGMT_STATUS_INVALID_PARAMS);
4140
4141 /* Two most significant bits shall be set */
4142 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4143 return cmd_status(sk, hdev->id,
4144 MGMT_OP_SET_STATIC_ADDRESS,
4145 MGMT_STATUS_INVALID_PARAMS);
4146 }
4147
4148 hci_dev_lock(hdev);
4149
4150 bacpy(&hdev->static_addr, &cp->bdaddr);
4151
4152 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4153
4154 hci_dev_unlock(hdev);
4155
4156 return err;
4157}
4158
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004159static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4160 void *data, u16 len)
4161{
4162 struct mgmt_cp_set_scan_params *cp = data;
4163 __u16 interval, window;
4164 int err;
4165
4166 BT_DBG("%s", hdev->name);
4167
4168 if (!lmp_le_capable(hdev))
4169 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4170 MGMT_STATUS_NOT_SUPPORTED);
4171
4172 interval = __le16_to_cpu(cp->interval);
4173
4174 if (interval < 0x0004 || interval > 0x4000)
4175 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4176 MGMT_STATUS_INVALID_PARAMS);
4177
4178 window = __le16_to_cpu(cp->window);
4179
4180 if (window < 0x0004 || window > 0x4000)
4181 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4182 MGMT_STATUS_INVALID_PARAMS);
4183
Marcel Holtmann899e1072013-10-14 09:55:32 -07004184 if (window > interval)
4185 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4186 MGMT_STATUS_INVALID_PARAMS);
4187
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004188 hci_dev_lock(hdev);
4189
4190 hdev->le_scan_interval = interval;
4191 hdev->le_scan_window = window;
4192
4193 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4194
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004195 /* If background scan is running, restart it so new parameters are
4196 * loaded.
4197 */
4198 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4199 hdev->discovery.state == DISCOVERY_STOPPED) {
4200 struct hci_request req;
4201
4202 hci_req_init(&req, hdev);
4203
4204 hci_req_add_le_scan_disable(&req);
4205 hci_req_add_le_passive_scan(&req);
4206
4207 hci_req_run(&req, NULL);
4208 }
4209
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004210 hci_dev_unlock(hdev);
4211
4212 return err;
4213}
4214
Johan Hedberg33e38b32013-03-15 17:07:05 -05004215static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4216{
4217 struct pending_cmd *cmd;
4218
4219 BT_DBG("status 0x%02x", status);
4220
4221 hci_dev_lock(hdev);
4222
4223 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4224 if (!cmd)
4225 goto unlock;
4226
4227 if (status) {
4228 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4229 mgmt_status(status));
4230 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004231 struct mgmt_mode *cp = cmd->param;
4232
4233 if (cp->val)
4234 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4235 else
4236 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4237
Johan Hedberg33e38b32013-03-15 17:07:05 -05004238 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4239 new_settings(hdev, cmd->sk);
4240 }
4241
4242 mgmt_pending_remove(cmd);
4243
4244unlock:
4245 hci_dev_unlock(hdev);
4246}
4247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004248static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004249 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004250{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004251 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004252 struct pending_cmd *cmd;
4253 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004254 int err;
4255
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004256 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004257
Johan Hedberg56f87902013-10-02 13:43:13 +03004258 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4259 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004260 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4261 MGMT_STATUS_NOT_SUPPORTED);
4262
Johan Hedberga7e80f22013-01-09 16:05:19 +02004263 if (cp->val != 0x00 && cp->val != 0x01)
4264 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4265 MGMT_STATUS_INVALID_PARAMS);
4266
Johan Hedberg5400c042012-02-21 16:40:33 +02004267 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004268 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004269 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004270
4271 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004272 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004273 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004274
4275 hci_dev_lock(hdev);
4276
Johan Hedberg05cbf292013-03-15 17:07:07 -05004277 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4278 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4279 MGMT_STATUS_BUSY);
4280 goto unlock;
4281 }
4282
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004283 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4284 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4285 hdev);
4286 goto unlock;
4287 }
4288
Johan Hedberg33e38b32013-03-15 17:07:05 -05004289 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4290 data, len);
4291 if (!cmd) {
4292 err = -ENOMEM;
4293 goto unlock;
4294 }
4295
4296 hci_req_init(&req, hdev);
4297
Johan Hedberg406d7802013-03-15 17:07:09 -05004298 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004299
4300 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004301 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004302 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004303 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004304 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004305 }
4306
Johan Hedberg33e38b32013-03-15 17:07:05 -05004307unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004308 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004309
Antti Julkuf6422ec2011-06-22 13:11:56 +03004310 return err;
4311}
4312
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004313static void set_bredr_scan(struct hci_request *req)
4314{
4315 struct hci_dev *hdev = req->hdev;
4316 u8 scan = 0;
4317
4318 /* Ensure that fast connectable is disabled. This function will
4319 * not do anything if the page scan parameters are already what
4320 * they should be.
4321 */
4322 write_fast_connectable(req, false);
4323
4324 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4325 scan |= SCAN_PAGE;
4326 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4327 scan |= SCAN_INQUIRY;
4328
4329 if (scan)
4330 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4331}
4332
Johan Hedberg0663ca22013-10-02 13:43:14 +03004333static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4334{
4335 struct pending_cmd *cmd;
4336
4337 BT_DBG("status 0x%02x", status);
4338
4339 hci_dev_lock(hdev);
4340
4341 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4342 if (!cmd)
4343 goto unlock;
4344
4345 if (status) {
4346 u8 mgmt_err = mgmt_status(status);
4347
4348 /* We need to restore the flag if related HCI commands
4349 * failed.
4350 */
4351 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4352
4353 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4354 } else {
4355 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4356 new_settings(hdev, cmd->sk);
4357 }
4358
4359 mgmt_pending_remove(cmd);
4360
4361unlock:
4362 hci_dev_unlock(hdev);
4363}
4364
4365static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4366{
4367 struct mgmt_mode *cp = data;
4368 struct pending_cmd *cmd;
4369 struct hci_request req;
4370 int err;
4371
4372 BT_DBG("request for %s", hdev->name);
4373
4374 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4375 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4376 MGMT_STATUS_NOT_SUPPORTED);
4377
4378 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4379 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4380 MGMT_STATUS_REJECTED);
4381
4382 if (cp->val != 0x00 && cp->val != 0x01)
4383 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4384 MGMT_STATUS_INVALID_PARAMS);
4385
4386 hci_dev_lock(hdev);
4387
4388 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4389 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4390 goto unlock;
4391 }
4392
4393 if (!hdev_is_powered(hdev)) {
4394 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004395 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4396 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4397 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4398 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4399 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4400 }
4401
4402 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4403
4404 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4405 if (err < 0)
4406 goto unlock;
4407
4408 err = new_settings(hdev, sk);
4409 goto unlock;
4410 }
4411
4412 /* Reject disabling when powered on */
4413 if (!cp->val) {
4414 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4415 MGMT_STATUS_REJECTED);
4416 goto unlock;
4417 }
4418
4419 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4420 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4421 MGMT_STATUS_BUSY);
4422 goto unlock;
4423 }
4424
4425 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4426 if (!cmd) {
4427 err = -ENOMEM;
4428 goto unlock;
4429 }
4430
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004431 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004432 * generates the correct flags.
4433 */
4434 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4435
4436 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004437
4438 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4439 set_bredr_scan(&req);
4440
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004441 /* Since only the advertising data flags will change, there
4442 * is no need to update the scan response data.
4443 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004444 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004445
Johan Hedberg0663ca22013-10-02 13:43:14 +03004446 err = hci_req_run(&req, set_bredr_complete);
4447 if (err < 0)
4448 mgmt_pending_remove(cmd);
4449
4450unlock:
4451 hci_dev_unlock(hdev);
4452 return err;
4453}
4454
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004455static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4456 void *data, u16 len)
4457{
4458 struct mgmt_mode *cp = data;
4459 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004460 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004461 int err;
4462
4463 BT_DBG("request for %s", hdev->name);
4464
4465 status = mgmt_bredr_support(hdev);
4466 if (status)
4467 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4468 status);
4469
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004470 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004471 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004472 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4473 MGMT_STATUS_NOT_SUPPORTED);
4474
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004475 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004476 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4477 MGMT_STATUS_INVALID_PARAMS);
4478
4479 hci_dev_lock(hdev);
4480
4481 if (!hdev_is_powered(hdev)) {
4482 bool changed;
4483
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004484 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004485 changed = !test_and_set_bit(HCI_SC_ENABLED,
4486 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004487 if (cp->val == 0x02)
4488 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4489 else
4490 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4491 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004492 changed = test_and_clear_bit(HCI_SC_ENABLED,
4493 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004494 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4495 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004496
4497 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4498 if (err < 0)
4499 goto failed;
4500
4501 if (changed)
4502 err = new_settings(hdev, sk);
4503
4504 goto failed;
4505 }
4506
4507 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4508 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4509 MGMT_STATUS_BUSY);
4510 goto failed;
4511 }
4512
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004513 val = !!cp->val;
4514
4515 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4516 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004517 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4518 goto failed;
4519 }
4520
4521 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4522 if (!cmd) {
4523 err = -ENOMEM;
4524 goto failed;
4525 }
4526
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004527 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004528 if (err < 0) {
4529 mgmt_pending_remove(cmd);
4530 goto failed;
4531 }
4532
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004533 if (cp->val == 0x02)
4534 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4535 else
4536 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4537
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004538failed:
4539 hci_dev_unlock(hdev);
4540 return err;
4541}
4542
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004543static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4544 void *data, u16 len)
4545{
4546 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004547 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004548 int err;
4549
4550 BT_DBG("request for %s", hdev->name);
4551
Johan Hedbergb97109792014-06-24 14:00:28 +03004552 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004553 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4554 MGMT_STATUS_INVALID_PARAMS);
4555
4556 hci_dev_lock(hdev);
4557
4558 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004559 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4560 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004561 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004562 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4563 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004564
Johan Hedbergb97109792014-06-24 14:00:28 +03004565 if (cp->val == 0x02)
4566 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4567 &hdev->dev_flags);
4568 else
4569 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4570 &hdev->dev_flags);
4571
4572 if (hdev_is_powered(hdev) && use_changed &&
4573 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4574 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4575 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4576 sizeof(mode), &mode);
4577 }
4578
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004579 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4580 if (err < 0)
4581 goto unlock;
4582
4583 if (changed)
4584 err = new_settings(hdev, sk);
4585
4586unlock:
4587 hci_dev_unlock(hdev);
4588 return err;
4589}
4590
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004591static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4592 u16 len)
4593{
4594 struct mgmt_cp_set_privacy *cp = cp_data;
4595 bool changed;
4596 int err;
4597
4598 BT_DBG("request for %s", hdev->name);
4599
4600 if (!lmp_le_capable(hdev))
4601 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4602 MGMT_STATUS_NOT_SUPPORTED);
4603
4604 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4605 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4606 MGMT_STATUS_INVALID_PARAMS);
4607
4608 if (hdev_is_powered(hdev))
4609 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4610 MGMT_STATUS_REJECTED);
4611
4612 hci_dev_lock(hdev);
4613
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004614 /* If user space supports this command it is also expected to
4615 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4616 */
4617 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4618
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004619 if (cp->privacy) {
4620 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4621 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4622 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4623 } else {
4624 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4625 memset(hdev->irk, 0, sizeof(hdev->irk));
4626 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4627 }
4628
4629 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4630 if (err < 0)
4631 goto unlock;
4632
4633 if (changed)
4634 err = new_settings(hdev, sk);
4635
4636unlock:
4637 hci_dev_unlock(hdev);
4638 return err;
4639}
4640
Johan Hedberg41edf162014-02-18 10:19:35 +02004641static bool irk_is_valid(struct mgmt_irk_info *irk)
4642{
4643 switch (irk->addr.type) {
4644 case BDADDR_LE_PUBLIC:
4645 return true;
4646
4647 case BDADDR_LE_RANDOM:
4648 /* Two most significant bits shall be set */
4649 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4650 return false;
4651 return true;
4652 }
4653
4654 return false;
4655}
4656
4657static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4658 u16 len)
4659{
4660 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004661 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4662 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004663 u16 irk_count, expected_len;
4664 int i, err;
4665
4666 BT_DBG("request for %s", hdev->name);
4667
4668 if (!lmp_le_capable(hdev))
4669 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4670 MGMT_STATUS_NOT_SUPPORTED);
4671
4672 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004673 if (irk_count > max_irk_count) {
4674 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4675 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4676 MGMT_STATUS_INVALID_PARAMS);
4677 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004678
4679 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4680 if (expected_len != len) {
4681 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004682 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004683 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4684 MGMT_STATUS_INVALID_PARAMS);
4685 }
4686
4687 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4688
4689 for (i = 0; i < irk_count; i++) {
4690 struct mgmt_irk_info *key = &cp->irks[i];
4691
4692 if (!irk_is_valid(key))
4693 return cmd_status(sk, hdev->id,
4694 MGMT_OP_LOAD_IRKS,
4695 MGMT_STATUS_INVALID_PARAMS);
4696 }
4697
4698 hci_dev_lock(hdev);
4699
4700 hci_smp_irks_clear(hdev);
4701
4702 for (i = 0; i < irk_count; i++) {
4703 struct mgmt_irk_info *irk = &cp->irks[i];
4704 u8 addr_type;
4705
4706 if (irk->addr.type == BDADDR_LE_PUBLIC)
4707 addr_type = ADDR_LE_DEV_PUBLIC;
4708 else
4709 addr_type = ADDR_LE_DEV_RANDOM;
4710
4711 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4712 BDADDR_ANY);
4713 }
4714
4715 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4716
4717 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4718
4719 hci_dev_unlock(hdev);
4720
4721 return err;
4722}
4723
Johan Hedberg3f706b72013-01-20 14:27:16 +02004724static bool ltk_is_valid(struct mgmt_ltk_info *key)
4725{
4726 if (key->master != 0x00 && key->master != 0x01)
4727 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004728
4729 switch (key->addr.type) {
4730 case BDADDR_LE_PUBLIC:
4731 return true;
4732
4733 case BDADDR_LE_RANDOM:
4734 /* Two most significant bits shall be set */
4735 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4736 return false;
4737 return true;
4738 }
4739
4740 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004741}
4742
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004743static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004744 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004745{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004746 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004747 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4748 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004749 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004750 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004751
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004752 BT_DBG("request for %s", hdev->name);
4753
4754 if (!lmp_le_capable(hdev))
4755 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4756 MGMT_STATUS_NOT_SUPPORTED);
4757
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004758 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004759 if (key_count > max_key_count) {
4760 BT_ERR("load_ltks: too big key_count value %u", key_count);
4761 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4762 MGMT_STATUS_INVALID_PARAMS);
4763 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004764
4765 expected_len = sizeof(*cp) + key_count *
4766 sizeof(struct mgmt_ltk_info);
4767 if (expected_len != len) {
4768 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004769 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004770 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004771 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004772 }
4773
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004774 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004775
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004776 for (i = 0; i < key_count; i++) {
4777 struct mgmt_ltk_info *key = &cp->keys[i];
4778
Johan Hedberg3f706b72013-01-20 14:27:16 +02004779 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004780 return cmd_status(sk, hdev->id,
4781 MGMT_OP_LOAD_LONG_TERM_KEYS,
4782 MGMT_STATUS_INVALID_PARAMS);
4783 }
4784
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004785 hci_dev_lock(hdev);
4786
4787 hci_smp_ltks_clear(hdev);
4788
4789 for (i = 0; i < key_count; i++) {
4790 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004791 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004792
4793 if (key->addr.type == BDADDR_LE_PUBLIC)
4794 addr_type = ADDR_LE_DEV_PUBLIC;
4795 else
4796 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004797
4798 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004799 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004800 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004801 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004802
Johan Hedberg61b43352014-05-29 19:36:53 +03004803 switch (key->type) {
4804 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004805 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004806 break;
4807 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004808 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004809 break;
4810 default:
4811 continue;
4812 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004813
Johan Hedberg35d70272014-02-19 14:57:47 +02004814 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004815 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004816 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004817 }
4818
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004819 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4820 NULL, 0);
4821
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004822 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004823
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004824 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004825}
4826
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004827struct cmd_conn_lookup {
4828 struct hci_conn *conn;
4829 bool valid_tx_power;
4830 u8 mgmt_status;
4831};
4832
4833static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4834{
4835 struct cmd_conn_lookup *match = data;
4836 struct mgmt_cp_get_conn_info *cp;
4837 struct mgmt_rp_get_conn_info rp;
4838 struct hci_conn *conn = cmd->user_data;
4839
4840 if (conn != match->conn)
4841 return;
4842
4843 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4844
4845 memset(&rp, 0, sizeof(rp));
4846 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4847 rp.addr.type = cp->addr.type;
4848
4849 if (!match->mgmt_status) {
4850 rp.rssi = conn->rssi;
4851
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004852 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004853 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004854 rp.max_tx_power = conn->max_tx_power;
4855 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004856 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004857 rp.max_tx_power = HCI_TX_POWER_INVALID;
4858 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004859 }
4860
4861 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4862 match->mgmt_status, &rp, sizeof(rp));
4863
4864 hci_conn_drop(conn);
4865
4866 mgmt_pending_remove(cmd);
4867}
4868
4869static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4870{
4871 struct hci_cp_read_rssi *cp;
4872 struct hci_conn *conn;
4873 struct cmd_conn_lookup match;
4874 u16 handle;
4875
4876 BT_DBG("status 0x%02x", status);
4877
4878 hci_dev_lock(hdev);
4879
4880 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004881 * otherwise we assume it's not valid. At the moment we assume that
4882 * either both or none of current and max values are valid to keep code
4883 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004884 */
4885 match.valid_tx_power = !status;
4886
4887 /* Commands sent in request are either Read RSSI or Read Transmit Power
4888 * Level so we check which one was last sent to retrieve connection
4889 * handle. Both commands have handle as first parameter so it's safe to
4890 * cast data on the same command struct.
4891 *
4892 * First command sent is always Read RSSI and we fail only if it fails.
4893 * In other case we simply override error to indicate success as we
4894 * already remembered if TX power value is actually valid.
4895 */
4896 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4897 if (!cp) {
4898 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4899 status = 0;
4900 }
4901
4902 if (!cp) {
4903 BT_ERR("invalid sent_cmd in response");
4904 goto unlock;
4905 }
4906
4907 handle = __le16_to_cpu(cp->handle);
4908 conn = hci_conn_hash_lookup_handle(hdev, handle);
4909 if (!conn) {
4910 BT_ERR("unknown handle (%d) in response", handle);
4911 goto unlock;
4912 }
4913
4914 match.conn = conn;
4915 match.mgmt_status = mgmt_status(status);
4916
4917 /* Cache refresh is complete, now reply for mgmt request for given
4918 * connection only.
4919 */
4920 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4921 get_conn_info_complete, &match);
4922
4923unlock:
4924 hci_dev_unlock(hdev);
4925}
4926
4927static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4928 u16 len)
4929{
4930 struct mgmt_cp_get_conn_info *cp = data;
4931 struct mgmt_rp_get_conn_info rp;
4932 struct hci_conn *conn;
4933 unsigned long conn_info_age;
4934 int err = 0;
4935
4936 BT_DBG("%s", hdev->name);
4937
4938 memset(&rp, 0, sizeof(rp));
4939 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4940 rp.addr.type = cp->addr.type;
4941
4942 if (!bdaddr_type_is_valid(cp->addr.type))
4943 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4944 MGMT_STATUS_INVALID_PARAMS,
4945 &rp, sizeof(rp));
4946
4947 hci_dev_lock(hdev);
4948
4949 if (!hdev_is_powered(hdev)) {
4950 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4951 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4952 goto unlock;
4953 }
4954
4955 if (cp->addr.type == BDADDR_BREDR)
4956 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4957 &cp->addr.bdaddr);
4958 else
4959 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4960
4961 if (!conn || conn->state != BT_CONNECTED) {
4962 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4963 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4964 goto unlock;
4965 }
4966
4967 /* To avoid client trying to guess when to poll again for information we
4968 * calculate conn info age as random value between min/max set in hdev.
4969 */
4970 conn_info_age = hdev->conn_info_min_age +
4971 prandom_u32_max(hdev->conn_info_max_age -
4972 hdev->conn_info_min_age);
4973
4974 /* Query controller to refresh cached values if they are too old or were
4975 * never read.
4976 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004977 if (time_after(jiffies, conn->conn_info_timestamp +
4978 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004979 !conn->conn_info_timestamp) {
4980 struct hci_request req;
4981 struct hci_cp_read_tx_power req_txp_cp;
4982 struct hci_cp_read_rssi req_rssi_cp;
4983 struct pending_cmd *cmd;
4984
4985 hci_req_init(&req, hdev);
4986 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4987 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4988 &req_rssi_cp);
4989
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004990 /* For LE links TX power does not change thus we don't need to
4991 * query for it once value is known.
4992 */
4993 if (!bdaddr_type_is_le(cp->addr.type) ||
4994 conn->tx_power == HCI_TX_POWER_INVALID) {
4995 req_txp_cp.handle = cpu_to_le16(conn->handle);
4996 req_txp_cp.type = 0x00;
4997 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4998 sizeof(req_txp_cp), &req_txp_cp);
4999 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005000
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005001 /* Max TX power needs to be read only once per connection */
5002 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5003 req_txp_cp.handle = cpu_to_le16(conn->handle);
5004 req_txp_cp.type = 0x01;
5005 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5006 sizeof(req_txp_cp), &req_txp_cp);
5007 }
5008
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005009 err = hci_req_run(&req, conn_info_refresh_complete);
5010 if (err < 0)
5011 goto unlock;
5012
5013 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5014 data, len);
5015 if (!cmd) {
5016 err = -ENOMEM;
5017 goto unlock;
5018 }
5019
5020 hci_conn_hold(conn);
5021 cmd->user_data = conn;
5022
5023 conn->conn_info_timestamp = jiffies;
5024 } else {
5025 /* Cache is valid, just reply with values cached in hci_conn */
5026 rp.rssi = conn->rssi;
5027 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005028 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005029
5030 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5031 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5032 }
5033
5034unlock:
5035 hci_dev_unlock(hdev);
5036 return err;
5037}
5038
Johan Hedberg95868422014-06-28 17:54:07 +03005039static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5040{
5041 struct mgmt_cp_get_clock_info *cp;
5042 struct mgmt_rp_get_clock_info rp;
5043 struct hci_cp_read_clock *hci_cp;
5044 struct pending_cmd *cmd;
5045 struct hci_conn *conn;
5046
5047 BT_DBG("%s status %u", hdev->name, status);
5048
5049 hci_dev_lock(hdev);
5050
5051 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5052 if (!hci_cp)
5053 goto unlock;
5054
5055 if (hci_cp->which) {
5056 u16 handle = __le16_to_cpu(hci_cp->handle);
5057 conn = hci_conn_hash_lookup_handle(hdev, handle);
5058 } else {
5059 conn = NULL;
5060 }
5061
5062 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5063 if (!cmd)
5064 goto unlock;
5065
5066 cp = cmd->param;
5067
5068 memset(&rp, 0, sizeof(rp));
5069 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5070
5071 if (status)
5072 goto send_rsp;
5073
5074 rp.local_clock = cpu_to_le32(hdev->clock);
5075
5076 if (conn) {
5077 rp.piconet_clock = cpu_to_le32(conn->clock);
5078 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5079 }
5080
5081send_rsp:
5082 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5083 &rp, sizeof(rp));
5084 mgmt_pending_remove(cmd);
5085 if (conn)
5086 hci_conn_drop(conn);
5087
5088unlock:
5089 hci_dev_unlock(hdev);
5090}
5091
5092static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5093 u16 len)
5094{
5095 struct mgmt_cp_get_clock_info *cp = data;
5096 struct mgmt_rp_get_clock_info rp;
5097 struct hci_cp_read_clock hci_cp;
5098 struct pending_cmd *cmd;
5099 struct hci_request req;
5100 struct hci_conn *conn;
5101 int err;
5102
5103 BT_DBG("%s", hdev->name);
5104
5105 memset(&rp, 0, sizeof(rp));
5106 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5107 rp.addr.type = cp->addr.type;
5108
5109 if (cp->addr.type != BDADDR_BREDR)
5110 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5111 MGMT_STATUS_INVALID_PARAMS,
5112 &rp, sizeof(rp));
5113
5114 hci_dev_lock(hdev);
5115
5116 if (!hdev_is_powered(hdev)) {
5117 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5118 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5119 goto unlock;
5120 }
5121
5122 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5123 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5124 &cp->addr.bdaddr);
5125 if (!conn || conn->state != BT_CONNECTED) {
5126 err = cmd_complete(sk, hdev->id,
5127 MGMT_OP_GET_CLOCK_INFO,
5128 MGMT_STATUS_NOT_CONNECTED,
5129 &rp, sizeof(rp));
5130 goto unlock;
5131 }
5132 } else {
5133 conn = NULL;
5134 }
5135
5136 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5137 if (!cmd) {
5138 err = -ENOMEM;
5139 goto unlock;
5140 }
5141
5142 hci_req_init(&req, hdev);
5143
5144 memset(&hci_cp, 0, sizeof(hci_cp));
5145 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5146
5147 if (conn) {
5148 hci_conn_hold(conn);
5149 cmd->user_data = conn;
5150
5151 hci_cp.handle = cpu_to_le16(conn->handle);
5152 hci_cp.which = 0x01; /* Piconet clock */
5153 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5154 }
5155
5156 err = hci_req_run(&req, get_clock_info_complete);
5157 if (err < 0)
5158 mgmt_pending_remove(cmd);
5159
5160unlock:
5161 hci_dev_unlock(hdev);
5162 return err;
5163}
5164
Marcel Holtmann8afef092014-06-29 22:28:34 +02005165static void device_added(struct sock *sk, struct hci_dev *hdev,
5166 bdaddr_t *bdaddr, u8 type, u8 action)
5167{
5168 struct mgmt_ev_device_added ev;
5169
5170 bacpy(&ev.addr.bdaddr, bdaddr);
5171 ev.addr.type = type;
5172 ev.action = action;
5173
5174 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5175}
5176
Marcel Holtmann2faade52014-06-29 19:44:03 +02005177static int add_device(struct sock *sk, struct hci_dev *hdev,
5178 void *data, u16 len)
5179{
5180 struct mgmt_cp_add_device *cp = data;
5181 u8 auto_conn, addr_type;
5182 int err;
5183
5184 BT_DBG("%s", hdev->name);
5185
5186 if (!bdaddr_type_is_le(cp->addr.type) ||
5187 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5188 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5189 MGMT_STATUS_INVALID_PARAMS,
5190 &cp->addr, sizeof(cp->addr));
5191
5192 if (cp->action != 0x00 && cp->action != 0x01)
5193 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5194 MGMT_STATUS_INVALID_PARAMS,
5195 &cp->addr, sizeof(cp->addr));
5196
5197 hci_dev_lock(hdev);
5198
5199 if (cp->addr.type == BDADDR_LE_PUBLIC)
5200 addr_type = ADDR_LE_DEV_PUBLIC;
5201 else
5202 addr_type = ADDR_LE_DEV_RANDOM;
5203
5204 if (cp->action)
5205 auto_conn = HCI_AUTO_CONN_ALWAYS;
5206 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005207 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005208
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005209 /* If the connection parameters don't exist for this device,
5210 * they will be created and configured with defaults.
5211 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005212 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5213 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005214 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5215 MGMT_STATUS_FAILED,
5216 &cp->addr, sizeof(cp->addr));
5217 goto unlock;
5218 }
5219
Marcel Holtmann8afef092014-06-29 22:28:34 +02005220 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5221
Marcel Holtmann2faade52014-06-29 19:44:03 +02005222 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5223 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5224
5225unlock:
5226 hci_dev_unlock(hdev);
5227 return err;
5228}
5229
Marcel Holtmann8afef092014-06-29 22:28:34 +02005230static void device_removed(struct sock *sk, struct hci_dev *hdev,
5231 bdaddr_t *bdaddr, u8 type)
5232{
5233 struct mgmt_ev_device_removed ev;
5234
5235 bacpy(&ev.addr.bdaddr, bdaddr);
5236 ev.addr.type = type;
5237
5238 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5239}
5240
Marcel Holtmann2faade52014-06-29 19:44:03 +02005241static int remove_device(struct sock *sk, struct hci_dev *hdev,
5242 void *data, u16 len)
5243{
5244 struct mgmt_cp_remove_device *cp = data;
5245 int err;
5246
5247 BT_DBG("%s", hdev->name);
5248
5249 hci_dev_lock(hdev);
5250
5251 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005252 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005253 u8 addr_type;
5254
5255 if (!bdaddr_type_is_le(cp->addr.type)) {
5256 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5257 MGMT_STATUS_INVALID_PARAMS,
5258 &cp->addr, sizeof(cp->addr));
5259 goto unlock;
5260 }
5261
5262 if (cp->addr.type == BDADDR_LE_PUBLIC)
5263 addr_type = ADDR_LE_DEV_PUBLIC;
5264 else
5265 addr_type = ADDR_LE_DEV_RANDOM;
5266
Johan Hedbergc71593d2014-07-02 17:37:28 +03005267 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5268 addr_type);
5269 if (!params) {
5270 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5271 MGMT_STATUS_INVALID_PARAMS,
5272 &cp->addr, sizeof(cp->addr));
5273 goto unlock;
5274 }
5275
5276 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5277 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5278 MGMT_STATUS_INVALID_PARAMS,
5279 &cp->addr, sizeof(cp->addr));
5280 goto unlock;
5281 }
5282
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005283 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005284 list_del(&params->list);
5285 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005286 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005287
5288 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005289 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005290 struct hci_conn_params *p, *tmp;
5291
Marcel Holtmann2faade52014-06-29 19:44:03 +02005292 if (cp->addr.type) {
5293 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5294 MGMT_STATUS_INVALID_PARAMS,
5295 &cp->addr, sizeof(cp->addr));
5296 goto unlock;
5297 }
5298
Johan Hedberg19de0822014-07-06 13:06:51 +03005299 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5300 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5301 continue;
5302 device_removed(sk, hdev, &p->addr, p->addr_type);
5303 list_del(&p->action);
5304 list_del(&p->list);
5305 kfree(p);
5306 }
5307
5308 BT_DBG("All LE connection parameters were removed");
5309
5310 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005311 }
5312
5313 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5314 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5315
5316unlock:
5317 hci_dev_unlock(hdev);
5318 return err;
5319}
5320
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005321static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5322 u16 len)
5323{
5324 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005325 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5326 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005327 u16 param_count, expected_len;
5328 int i;
5329
5330 if (!lmp_le_capable(hdev))
5331 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5332 MGMT_STATUS_NOT_SUPPORTED);
5333
5334 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005335 if (param_count > max_param_count) {
5336 BT_ERR("load_conn_param: too big param_count value %u",
5337 param_count);
5338 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5339 MGMT_STATUS_INVALID_PARAMS);
5340 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005341
5342 expected_len = sizeof(*cp) + param_count *
5343 sizeof(struct mgmt_conn_param);
5344 if (expected_len != len) {
5345 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5346 expected_len, len);
5347 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5348 MGMT_STATUS_INVALID_PARAMS);
5349 }
5350
5351 BT_DBG("%s param_count %u", hdev->name, param_count);
5352
5353 hci_dev_lock(hdev);
5354
5355 hci_conn_params_clear_disabled(hdev);
5356
5357 for (i = 0; i < param_count; i++) {
5358 struct mgmt_conn_param *param = &cp->params[i];
5359 struct hci_conn_params *hci_param;
5360 u16 min, max, latency, timeout;
5361 u8 addr_type;
5362
5363 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5364 param->addr.type);
5365
5366 if (param->addr.type == BDADDR_LE_PUBLIC) {
5367 addr_type = ADDR_LE_DEV_PUBLIC;
5368 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5369 addr_type = ADDR_LE_DEV_RANDOM;
5370 } else {
5371 BT_ERR("Ignoring invalid connection parameters");
5372 continue;
5373 }
5374
5375 min = le16_to_cpu(param->min_interval);
5376 max = le16_to_cpu(param->max_interval);
5377 latency = le16_to_cpu(param->latency);
5378 timeout = le16_to_cpu(param->timeout);
5379
5380 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5381 min, max, latency, timeout);
5382
5383 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5384 BT_ERR("Ignoring invalid connection parameters");
5385 continue;
5386 }
5387
5388 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5389 addr_type);
5390 if (!hci_param) {
5391 BT_ERR("Failed to add connection parameters");
5392 continue;
5393 }
5394
5395 hci_param->conn_min_interval = min;
5396 hci_param->conn_max_interval = max;
5397 hci_param->conn_latency = latency;
5398 hci_param->supervision_timeout = timeout;
5399 }
5400
5401 hci_dev_unlock(hdev);
5402
5403 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5404}
5405
Marcel Holtmanndbece372014-07-04 18:11:55 +02005406static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5407 void *data, u16 len)
5408{
5409 struct mgmt_cp_set_external_config *cp = data;
5410 bool changed;
5411 int err;
5412
5413 BT_DBG("%s", hdev->name);
5414
5415 if (hdev_is_powered(hdev))
5416 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5417 MGMT_STATUS_REJECTED);
5418
5419 if (cp->config != 0x00 && cp->config != 0x01)
5420 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5421 MGMT_STATUS_INVALID_PARAMS);
5422
5423 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5424 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5425 MGMT_STATUS_NOT_SUPPORTED);
5426
5427 hci_dev_lock(hdev);
5428
5429 if (cp->config)
5430 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5431 &hdev->dev_flags);
5432 else
5433 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5434 &hdev->dev_flags);
5435
5436 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5437 if (err < 0)
5438 goto unlock;
5439
5440 if (!changed)
5441 goto unlock;
5442
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005443 err = new_options(hdev, sk);
5444
Marcel Holtmanndbece372014-07-04 18:11:55 +02005445 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5446 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005447
5448 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5449 set_bit(HCI_CONFIG, &hdev->dev_flags);
5450 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5451
5452 queue_work(hdev->req_workqueue, &hdev->power_on);
5453 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005454 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005455 mgmt_index_added(hdev);
5456 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005457 }
5458
5459unlock:
5460 hci_dev_unlock(hdev);
5461 return err;
5462}
5463
Marcel Holtmann9713c172014-07-06 12:11:15 +02005464static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5465 void *data, u16 len)
5466{
5467 struct mgmt_cp_set_public_address *cp = data;
5468 bool changed;
5469 int err;
5470
5471 BT_DBG("%s", hdev->name);
5472
5473 if (hdev_is_powered(hdev))
5474 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5475 MGMT_STATUS_REJECTED);
5476
5477 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5478 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5479 MGMT_STATUS_INVALID_PARAMS);
5480
5481 if (!hdev->set_bdaddr)
5482 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5483 MGMT_STATUS_NOT_SUPPORTED);
5484
5485 hci_dev_lock(hdev);
5486
5487 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5488 bacpy(&hdev->public_addr, &cp->bdaddr);
5489
5490 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5491 if (err < 0)
5492 goto unlock;
5493
5494 if (!changed)
5495 goto unlock;
5496
5497 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5498 err = new_options(hdev, sk);
5499
5500 if (is_configured(hdev)) {
5501 mgmt_index_removed(hdev);
5502
5503 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5504
5505 set_bit(HCI_CONFIG, &hdev->dev_flags);
5506 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5507
5508 queue_work(hdev->req_workqueue, &hdev->power_on);
5509 }
5510
5511unlock:
5512 hci_dev_unlock(hdev);
5513 return err;
5514}
5515
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005516static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005517 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5518 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005519 bool var_len;
5520 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005521} mgmt_handlers[] = {
5522 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005523 { read_version, false, MGMT_READ_VERSION_SIZE },
5524 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5525 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5526 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5527 { set_powered, false, MGMT_SETTING_SIZE },
5528 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5529 { set_connectable, false, MGMT_SETTING_SIZE },
5530 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5531 { set_pairable, false, MGMT_SETTING_SIZE },
5532 { set_link_security, false, MGMT_SETTING_SIZE },
5533 { set_ssp, false, MGMT_SETTING_SIZE },
5534 { set_hs, false, MGMT_SETTING_SIZE },
5535 { set_le, false, MGMT_SETTING_SIZE },
5536 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5537 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5538 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5539 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5540 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5541 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5542 { disconnect, false, MGMT_DISCONNECT_SIZE },
5543 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5544 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5545 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5546 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5547 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5548 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5549 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5550 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5551 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5552 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5553 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5554 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005555 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005556 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5557 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5558 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5559 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5560 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5561 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005562 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005563 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005564 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005565 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005566 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005567 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005568 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005569 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005570 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005571 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005572 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005573 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5574 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005575 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5576 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005577 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005578 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005579 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005580};
5581
Johan Hedberg03811012010-12-08 00:21:06 +02005582int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5583{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005584 void *buf;
5585 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005586 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005587 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005588 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005589 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005590 int err;
5591
5592 BT_DBG("got %zu bytes", msglen);
5593
5594 if (msglen < sizeof(*hdr))
5595 return -EINVAL;
5596
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005597 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005598 if (!buf)
5599 return -ENOMEM;
5600
5601 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5602 err = -EFAULT;
5603 goto done;
5604 }
5605
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005606 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005607 opcode = __le16_to_cpu(hdr->opcode);
5608 index = __le16_to_cpu(hdr->index);
5609 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005610
5611 if (len != msglen - sizeof(*hdr)) {
5612 err = -EINVAL;
5613 goto done;
5614 }
5615
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005616 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005617 hdev = hci_dev_get(index);
5618 if (!hdev) {
5619 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005620 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005621 goto done;
5622 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005623
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005624 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005625 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005626 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005627 err = cmd_status(sk, index, opcode,
5628 MGMT_STATUS_INVALID_INDEX);
5629 goto done;
5630 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005631
5632 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005633 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005634 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5635 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005636 err = cmd_status(sk, index, opcode,
5637 MGMT_STATUS_INVALID_INDEX);
5638 goto done;
5639 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005640 }
5641
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005642 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005643 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005644 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005645 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005646 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005647 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005648 }
5649
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005650 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5651 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5652 err = cmd_status(sk, index, opcode,
5653 MGMT_STATUS_INVALID_INDEX);
5654 goto done;
5655 }
5656
5657 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5658 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005659 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005660 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005661 goto done;
5662 }
5663
Johan Hedbergbe22b542012-03-01 22:24:41 +02005664 handler = &mgmt_handlers[opcode];
5665
5666 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005667 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005668 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005669 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005670 goto done;
5671 }
5672
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005673 if (hdev)
5674 mgmt_init_hdev(sk, hdev);
5675
5676 cp = buf + sizeof(*hdr);
5677
Johan Hedbergbe22b542012-03-01 22:24:41 +02005678 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005679 if (err < 0)
5680 goto done;
5681
Johan Hedberg03811012010-12-08 00:21:06 +02005682 err = msglen;
5683
5684done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005685 if (hdev)
5686 hci_dev_put(hdev);
5687
Johan Hedberg03811012010-12-08 00:21:06 +02005688 kfree(buf);
5689 return err;
5690}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005691
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005692void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005693{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005694 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005695 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005696
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005697 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5698 return;
5699
5700 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5701 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5702 else
5703 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005704}
5705
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005706void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005707{
Johan Hedberg5f159032012-03-02 03:13:19 +02005708 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005709
Marcel Holtmann1514b892013-10-06 08:25:01 -07005710 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005711 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005712
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005713 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5714 return;
5715
Johan Hedberg744cf192011-11-08 20:40:14 +02005716 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005717
Marcel Holtmannedd38962014-07-02 21:30:55 +02005718 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5719 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5720 else
5721 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005722}
5723
Andre Guedes6046dc32014-02-26 20:21:51 -03005724/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005725static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005726{
5727 struct hci_conn_params *p;
5728
5729 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005730 /* Needed for AUTO_OFF case where might not "really"
5731 * have been powered off.
5732 */
5733 list_del_init(&p->action);
5734
5735 switch (p->auto_connect) {
5736 case HCI_AUTO_CONN_ALWAYS:
5737 list_add(&p->action, &hdev->pend_le_conns);
5738 break;
5739 case HCI_AUTO_CONN_REPORT:
5740 list_add(&p->action, &hdev->pend_le_reports);
5741 break;
5742 default:
5743 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005744 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005745 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005746
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005747 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005748}
5749
Johan Hedberg229ab392013-03-15 17:06:53 -05005750static void powered_complete(struct hci_dev *hdev, u8 status)
5751{
5752 struct cmd_lookup match = { NULL, hdev };
5753
5754 BT_DBG("status 0x%02x", status);
5755
5756 hci_dev_lock(hdev);
5757
Johan Hedbergd7347f32014-07-04 12:37:23 +03005758 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005759
Johan Hedberg229ab392013-03-15 17:06:53 -05005760 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5761
5762 new_settings(hdev, match.sk);
5763
5764 hci_dev_unlock(hdev);
5765
5766 if (match.sk)
5767 sock_put(match.sk);
5768}
5769
Johan Hedberg70da6242013-03-15 17:06:51 -05005770static int powered_update_hci(struct hci_dev *hdev)
5771{
Johan Hedberg890ea892013-03-15 17:06:52 -05005772 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005773 u8 link_sec;
5774
Johan Hedberg890ea892013-03-15 17:06:52 -05005775 hci_req_init(&req, hdev);
5776
Johan Hedberg70da6242013-03-15 17:06:51 -05005777 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5778 !lmp_host_ssp_capable(hdev)) {
5779 u8 ssp = 1;
5780
Johan Hedberg890ea892013-03-15 17:06:52 -05005781 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005782 }
5783
Johan Hedbergc73eee92013-04-19 18:35:21 +03005784 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5785 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005786 struct hci_cp_write_le_host_supported cp;
5787
5788 cp.le = 1;
5789 cp.simul = lmp_le_br_capable(hdev);
5790
5791 /* Check first if we already have the right
5792 * host state (host features set)
5793 */
5794 if (cp.le != lmp_host_le_capable(hdev) ||
5795 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005796 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5797 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005798 }
5799
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005800 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005801 /* Make sure the controller has a good default for
5802 * advertising data. This also applies to the case
5803 * where BR/EDR was toggled during the AUTO_OFF phase.
5804 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005805 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005806 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005807 update_scan_rsp_data(&req);
5808 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005809
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005810 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5811 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005812 }
5813
Johan Hedberg70da6242013-03-15 17:06:51 -05005814 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5815 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005816 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5817 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005818
5819 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005820 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5821 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005822 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005823 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005824 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005825 }
5826
Johan Hedberg229ab392013-03-15 17:06:53 -05005827 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005828}
5829
Johan Hedberg744cf192011-11-08 20:40:14 +02005830int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005831{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005832 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005833 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5834 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005835 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005836
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005837 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5838 return 0;
5839
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005840 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005841 if (powered_update_hci(hdev) == 0)
5842 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005843
Johan Hedberg229ab392013-03-15 17:06:53 -05005844 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5845 &match);
5846 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005847 }
5848
Johan Hedberg229ab392013-03-15 17:06:53 -05005849 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5850 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5851
5852 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5853 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5854 zero_cod, sizeof(zero_cod), NULL);
5855
5856new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005857 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005858
5859 if (match.sk)
5860 sock_put(match.sk);
5861
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005862 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005863}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005864
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005865void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005866{
5867 struct pending_cmd *cmd;
5868 u8 status;
5869
5870 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5871 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005872 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005873
5874 if (err == -ERFKILL)
5875 status = MGMT_STATUS_RFKILLED;
5876 else
5877 status = MGMT_STATUS_FAILED;
5878
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005879 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005880
5881 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005882}
5883
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005884void mgmt_discoverable_timeout(struct hci_dev *hdev)
5885{
5886 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005887
5888 hci_dev_lock(hdev);
5889
5890 /* When discoverable timeout triggers, then just make sure
5891 * the limited discoverable flag is cleared. Even in the case
5892 * of a timeout triggered from general discoverable, it is
5893 * safe to unconditionally clear the flag.
5894 */
5895 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005896 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005897
5898 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005899 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5900 u8 scan = SCAN_PAGE;
5901 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5902 sizeof(scan), &scan);
5903 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005904 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005905 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005906 hci_req_run(&req, NULL);
5907
5908 hdev->discov_timeout = 0;
5909
Johan Hedberg9a43e252013-10-20 19:00:07 +03005910 new_settings(hdev, NULL);
5911
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005912 hci_dev_unlock(hdev);
5913}
5914
Marcel Holtmann86a75642013-10-15 06:33:54 -07005915void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005916{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005917 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005918
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005919 /* Nothing needed here if there's a pending command since that
5920 * commands request completion callback takes care of everything
5921 * necessary.
5922 */
5923 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005924 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005925
Johan Hedbergbd107992014-02-24 14:52:19 +02005926 /* Powering off may clear the scan mode - don't let that interfere */
5927 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5928 return;
5929
Johan Hedberg9a43e252013-10-20 19:00:07 +03005930 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005931 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005932 } else {
5933 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005934 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005935 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005936
Johan Hedberg9a43e252013-10-20 19:00:07 +03005937 if (changed) {
5938 struct hci_request req;
5939
5940 /* In case this change in discoverable was triggered by
5941 * a disabling of connectable there could be a need to
5942 * update the advertising flags.
5943 */
5944 hci_req_init(&req, hdev);
5945 update_adv_data(&req);
5946 hci_req_run(&req, NULL);
5947
Marcel Holtmann86a75642013-10-15 06:33:54 -07005948 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005949 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005950}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005951
Marcel Holtmanna3309162013-10-15 06:33:55 -07005952void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005953{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005954 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005955
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005956 /* Nothing needed here if there's a pending command since that
5957 * commands request completion callback takes care of everything
5958 * necessary.
5959 */
5960 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005961 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005962
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005963 /* Powering off may clear the scan mode - don't let that interfere */
5964 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5965 return;
5966
Marcel Holtmanna3309162013-10-15 06:33:55 -07005967 if (connectable)
5968 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5969 else
5970 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005971
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005972 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005973 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005974}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02005975
Johan Hedberg778b2352014-02-24 14:52:17 +02005976void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5977{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005978 /* Powering off may stop advertising - don't let that interfere */
5979 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5980 return;
5981
Johan Hedberg778b2352014-02-24 14:52:17 +02005982 if (advertising)
5983 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5984 else
5985 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5986}
5987
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005988void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005989{
Johan Hedbergca69b792011-11-11 18:10:00 +02005990 u8 mgmt_err = mgmt_status(status);
5991
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005992 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005993 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005994 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005995
5996 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005997 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005998 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005999}
6000
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006001void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6002 bool persistent)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006003{
Johan Hedberg86742e12011-11-07 23:13:38 +02006004 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006005
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006006 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006007
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006008 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006009 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006010 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006011 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006012 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006013 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006014
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006015 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006016}
Johan Hedbergf7520542011-01-20 12:34:39 +02006017
Johan Hedbergd7b25452014-05-23 13:19:53 +03006018static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6019{
6020 if (ltk->authenticated)
6021 return MGMT_LTK_AUTHENTICATED;
6022
6023 return MGMT_LTK_UNAUTHENTICATED;
6024}
6025
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006026void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006027{
6028 struct mgmt_ev_new_long_term_key ev;
6029
6030 memset(&ev, 0, sizeof(ev));
6031
Marcel Holtmann5192d302014-02-19 17:11:58 -08006032 /* Devices using resolvable or non-resolvable random addresses
6033 * without providing an indentity resolving key don't require
6034 * to store long term keys. Their addresses will change the
6035 * next time around.
6036 *
6037 * Only when a remote device provides an identity address
6038 * make sure the long term key is stored. If the remote
6039 * identity is known, the long term keys are internally
6040 * mapped to the identity address. So allow static random
6041 * and public addresses here.
6042 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006043 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6044 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6045 ev.store_hint = 0x00;
6046 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006047 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006048
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006049 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006050 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006051 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006052 ev.key.enc_size = key->enc_size;
6053 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006054 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006055
Johan Hedberg2ceba532014-06-16 19:25:16 +03006056 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006057 ev.key.master = 1;
6058
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006059 memcpy(ev.key.val, key->val, sizeof(key->val));
6060
Marcel Holtmann083368f2013-10-15 14:26:29 -07006061 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006062}
6063
Johan Hedberg95fbac82014-02-19 15:18:31 +02006064void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6065{
6066 struct mgmt_ev_new_irk ev;
6067
6068 memset(&ev, 0, sizeof(ev));
6069
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006070 /* For identity resolving keys from devices that are already
6071 * using a public address or static random address, do not
6072 * ask for storing this key. The identity resolving key really
6073 * is only mandatory for devices using resovlable random
6074 * addresses.
6075 *
6076 * Storing all identity resolving keys has the downside that
6077 * they will be also loaded on next boot of they system. More
6078 * identity resolving keys, means more time during scanning is
6079 * needed to actually resolve these addresses.
6080 */
6081 if (bacmp(&irk->rpa, BDADDR_ANY))
6082 ev.store_hint = 0x01;
6083 else
6084 ev.store_hint = 0x00;
6085
Johan Hedberg95fbac82014-02-19 15:18:31 +02006086 bacpy(&ev.rpa, &irk->rpa);
6087 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6088 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6089 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6090
6091 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6092}
6093
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006094void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6095 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006096{
6097 struct mgmt_ev_new_csrk ev;
6098
6099 memset(&ev, 0, sizeof(ev));
6100
6101 /* Devices using resolvable or non-resolvable random addresses
6102 * without providing an indentity resolving key don't require
6103 * to store signature resolving keys. Their addresses will change
6104 * the next time around.
6105 *
6106 * Only when a remote device provides an identity address
6107 * make sure the signature resolving key is stored. So allow
6108 * static random and public addresses here.
6109 */
6110 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6111 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6112 ev.store_hint = 0x00;
6113 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006114 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006115
6116 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6117 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6118 ev.key.master = csrk->master;
6119 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6120
6121 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6122}
6123
Andre Guedesffb5a8272014-07-01 18:10:11 -03006124void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006125 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6126 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006127{
6128 struct mgmt_ev_new_conn_param ev;
6129
Johan Hedbergc103aea2014-07-02 17:37:34 +03006130 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6131 return;
6132
Andre Guedesffb5a8272014-07-01 18:10:11 -03006133 memset(&ev, 0, sizeof(ev));
6134 bacpy(&ev.addr.bdaddr, bdaddr);
6135 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006136 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006137 ev.min_interval = cpu_to_le16(min_interval);
6138 ev.max_interval = cpu_to_le16(max_interval);
6139 ev.latency = cpu_to_le16(latency);
6140 ev.timeout = cpu_to_le16(timeout);
6141
6142 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6143}
6144
Marcel Holtmann94933992013-10-15 10:26:39 -07006145static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6146 u8 data_len)
6147{
6148 eir[eir_len++] = sizeof(type) + data_len;
6149 eir[eir_len++] = type;
6150 memcpy(&eir[eir_len], data, data_len);
6151 eir_len += data_len;
6152
6153 return eir_len;
6154}
6155
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006156void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6157 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6158 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006159{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006160 char buf[512];
6161 struct mgmt_ev_device_connected *ev = (void *) buf;
6162 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006163
Johan Hedbergb644ba32012-01-17 21:48:47 +02006164 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006165 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006166
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006167 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006168
Johan Hedbergb644ba32012-01-17 21:48:47 +02006169 if (name_len > 0)
6170 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006171 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006172
6173 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006174 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006175 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006176
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006177 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006178
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006179 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6180 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006181}
6182
Johan Hedberg8962ee72011-01-20 12:40:27 +02006183static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6184{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006185 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006186 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006187 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006188
Johan Hedberg88c3df12012-02-09 14:27:38 +02006189 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6190 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006191
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006192 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006193 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006194
6195 *sk = cmd->sk;
6196 sock_hold(*sk);
6197
Johan Hedberga664b5b2011-02-19 12:06:02 -03006198 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006199}
6200
Johan Hedberg124f6e32012-02-09 13:50:12 +02006201static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006202{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006203 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006204 struct mgmt_cp_unpair_device *cp = cmd->param;
6205 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006206
6207 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006208 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6209 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006210
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006211 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6212
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006213 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006214
6215 mgmt_pending_remove(cmd);
6216}
6217
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006218void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006219 u8 link_type, u8 addr_type, u8 reason,
6220 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006221{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006222 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006223 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006224 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006225
Johan Hedberg8b064a32014-02-24 14:52:22 +02006226 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6227 if (power_off) {
6228 struct mgmt_mode *cp = power_off->param;
6229
6230 /* The connection is still in hci_conn_hash so test for 1
6231 * instead of 0 to know if this is the last one.
6232 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006233 if (!cp->val && hci_conn_count(hdev) == 1) {
6234 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006235 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006236 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006237 }
6238
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006239 if (!mgmt_connected)
6240 return;
6241
Andre Guedes57eb7762013-10-30 19:01:41 -03006242 if (link_type != ACL_LINK && link_type != LE_LINK)
6243 return;
6244
Johan Hedberg744cf192011-11-08 20:40:14 +02006245 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006246
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006247 bacpy(&ev.addr.bdaddr, bdaddr);
6248 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6249 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006250
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006251 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006252
6253 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006254 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006255
Johan Hedberg124f6e32012-02-09 13:50:12 +02006256 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006257 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006258}
6259
Marcel Holtmann78929242013-10-06 23:55:47 -07006260void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6261 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006262{
Andre Guedes3655bba2013-10-30 19:01:40 -03006263 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6264 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006265 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006266 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006267
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006268 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6269 hdev);
6270
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006271 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006272 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006273 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006274
Andre Guedes3655bba2013-10-30 19:01:40 -03006275 cp = cmd->param;
6276
6277 if (bacmp(bdaddr, &cp->addr.bdaddr))
6278 return;
6279
6280 if (cp->addr.type != bdaddr_type)
6281 return;
6282
Johan Hedberg88c3df12012-02-09 14:27:38 +02006283 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006284 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006285
Marcel Holtmann78929242013-10-06 23:55:47 -07006286 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6287 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006288
Johan Hedberga664b5b2011-02-19 12:06:02 -03006289 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006290}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006291
Marcel Holtmann445608d2013-10-06 23:55:48 -07006292void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6293 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006294{
6295 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006296 struct pending_cmd *power_off;
6297
6298 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6299 if (power_off) {
6300 struct mgmt_mode *cp = power_off->param;
6301
6302 /* The connection is still in hci_conn_hash so test for 1
6303 * instead of 0 to know if this is the last one.
6304 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006305 if (!cp->val && hci_conn_count(hdev) == 1) {
6306 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006307 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006308 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006309 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006310
Johan Hedberg4c659c32011-11-07 23:13:39 +02006311 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006312 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006313 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006314
Marcel Holtmann445608d2013-10-06 23:55:48 -07006315 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006316}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006317
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006318void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006319{
6320 struct mgmt_ev_pin_code_request ev;
6321
Johan Hedbergd8457692012-02-17 14:24:57 +02006322 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006323 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006324 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006325
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006326 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006327}
6328
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006329void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6330 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006331{
6332 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006333 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006334
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006335 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006336 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006337 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006338
Johan Hedbergd8457692012-02-17 14:24:57 +02006339 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006340 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006341
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006342 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6343 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006344
Johan Hedberga664b5b2011-02-19 12:06:02 -03006345 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006346}
6347
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006348void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6349 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006350{
6351 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006352 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006353
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006354 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006355 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006356 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006357
Johan Hedbergd8457692012-02-17 14:24:57 +02006358 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006359 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006360
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006361 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6362 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006363
Johan Hedberga664b5b2011-02-19 12:06:02 -03006364 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006365}
Johan Hedberga5c29682011-02-19 12:05:57 -03006366
Johan Hedberg744cf192011-11-08 20:40:14 +02006367int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006368 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006369 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006370{
6371 struct mgmt_ev_user_confirm_request ev;
6372
Johan Hedberg744cf192011-11-08 20:40:14 +02006373 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006374
Johan Hedberg272d90d2012-02-09 15:26:12 +02006375 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006376 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006377 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006378 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006379
Johan Hedberg744cf192011-11-08 20:40:14 +02006380 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006381 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006382}
6383
Johan Hedberg272d90d2012-02-09 15:26:12 +02006384int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006385 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006386{
6387 struct mgmt_ev_user_passkey_request ev;
6388
6389 BT_DBG("%s", hdev->name);
6390
Johan Hedberg272d90d2012-02-09 15:26:12 +02006391 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006392 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006393
6394 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006395 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006396}
6397
Brian Gix0df4c182011-11-16 13:53:13 -08006398static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006399 u8 link_type, u8 addr_type, u8 status,
6400 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006401{
6402 struct pending_cmd *cmd;
6403 struct mgmt_rp_user_confirm_reply rp;
6404 int err;
6405
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006406 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006407 if (!cmd)
6408 return -ENOENT;
6409
Johan Hedberg272d90d2012-02-09 15:26:12 +02006410 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006411 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006412 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006413 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006414
Johan Hedberga664b5b2011-02-19 12:06:02 -03006415 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006416
6417 return err;
6418}
6419
Johan Hedberg744cf192011-11-08 20:40:14 +02006420int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006421 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006422{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006423 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006424 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006425}
6426
Johan Hedberg272d90d2012-02-09 15:26:12 +02006427int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006428 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006429{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006430 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006431 status,
6432 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006433}
Johan Hedberg2a611692011-02-19 12:06:00 -03006434
Brian Gix604086b2011-11-23 08:28:33 -08006435int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006436 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006437{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006438 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006439 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006440}
6441
Johan Hedberg272d90d2012-02-09 15:26:12 +02006442int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006443 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006444{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006445 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006446 status,
6447 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006448}
6449
Johan Hedberg92a25252012-09-06 18:39:26 +03006450int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6451 u8 link_type, u8 addr_type, u32 passkey,
6452 u8 entered)
6453{
6454 struct mgmt_ev_passkey_notify ev;
6455
6456 BT_DBG("%s", hdev->name);
6457
6458 bacpy(&ev.addr.bdaddr, bdaddr);
6459 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6460 ev.passkey = __cpu_to_le32(passkey);
6461 ev.entered = entered;
6462
6463 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6464}
6465
Marcel Holtmanne5460992013-10-15 14:26:23 -07006466void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6467 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006468{
6469 struct mgmt_ev_auth_failed ev;
6470
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006471 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006472 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006473 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006474
Marcel Holtmanne5460992013-10-15 14:26:23 -07006475 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006476}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006477
Marcel Holtmann464996a2013-10-15 14:26:24 -07006478void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006479{
6480 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006481 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006482
6483 if (status) {
6484 u8 mgmt_err = mgmt_status(status);
6485 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006486 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006487 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006488 }
6489
Marcel Holtmann464996a2013-10-15 14:26:24 -07006490 if (test_bit(HCI_AUTH, &hdev->flags))
6491 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6492 &hdev->dev_flags);
6493 else
6494 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6495 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006496
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006497 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006498 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006499
Johan Hedberg47990ea2012-02-22 11:58:37 +02006500 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006501 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006502
6503 if (match.sk)
6504 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006505}
6506
Johan Hedberg890ea892013-03-15 17:06:52 -05006507static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006508{
Johan Hedberg890ea892013-03-15 17:06:52 -05006509 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006510 struct hci_cp_write_eir cp;
6511
Johan Hedberg976eb202012-10-24 21:12:01 +03006512 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006513 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006514
Johan Hedbergc80da272012-02-22 15:38:48 +02006515 memset(hdev->eir, 0, sizeof(hdev->eir));
6516
Johan Hedbergcacaf522012-02-21 00:52:42 +02006517 memset(&cp, 0, sizeof(cp));
6518
Johan Hedberg890ea892013-03-15 17:06:52 -05006519 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006520}
6521
Marcel Holtmann3e248562013-10-15 14:26:25 -07006522void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006523{
6524 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006525 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006526 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006527
6528 if (status) {
6529 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006530
6531 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006532 &hdev->dev_flags)) {
6533 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006534 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006535 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006536
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006537 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6538 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006539 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006540 }
6541
6542 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006543 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006544 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006545 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6546 if (!changed)
6547 changed = test_and_clear_bit(HCI_HS_ENABLED,
6548 &hdev->dev_flags);
6549 else
6550 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006551 }
6552
6553 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6554
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006555 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006556 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006557
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006558 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006559 sock_put(match.sk);
6560
Johan Hedberg890ea892013-03-15 17:06:52 -05006561 hci_req_init(&req, hdev);
6562
Johan Hedberg37699722014-06-24 14:00:27 +03006563 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6564 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6565 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6566 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006567 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006568 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006569 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006570 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006571
6572 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006573}
6574
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006575void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6576{
6577 struct cmd_lookup match = { NULL, hdev };
6578 bool changed = false;
6579
6580 if (status) {
6581 u8 mgmt_err = mgmt_status(status);
6582
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006583 if (enable) {
6584 if (test_and_clear_bit(HCI_SC_ENABLED,
6585 &hdev->dev_flags))
6586 new_settings(hdev, NULL);
6587 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6588 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006589
6590 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6591 cmd_status_rsp, &mgmt_err);
6592 return;
6593 }
6594
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006595 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006596 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006597 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006598 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006599 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6600 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006601
6602 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6603 settings_rsp, &match);
6604
6605 if (changed)
6606 new_settings(hdev, match.sk);
6607
6608 if (match.sk)
6609 sock_put(match.sk);
6610}
6611
Johan Hedberg92da6092013-03-15 17:06:55 -05006612static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006613{
6614 struct cmd_lookup *match = data;
6615
Johan Hedberg90e70452012-02-23 23:09:40 +02006616 if (match->sk == NULL) {
6617 match->sk = cmd->sk;
6618 sock_hold(match->sk);
6619 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006620}
6621
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006622void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6623 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006624{
Johan Hedberg90e70452012-02-23 23:09:40 +02006625 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006626
Johan Hedberg92da6092013-03-15 17:06:55 -05006627 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6628 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6629 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006630
6631 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006632 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6633 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006634
6635 if (match.sk)
6636 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006637}
6638
Marcel Holtmann7667da32013-10-15 14:26:27 -07006639void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006640{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006641 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006642 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006643
Johan Hedberg13928972013-03-15 17:07:00 -05006644 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006645 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006646
6647 memset(&ev, 0, sizeof(ev));
6648 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006649 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006650
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006651 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006652 if (!cmd) {
6653 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006654
Johan Hedberg13928972013-03-15 17:07:00 -05006655 /* If this is a HCI command related to powering on the
6656 * HCI dev don't send any mgmt signals.
6657 */
6658 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006659 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006660 }
6661
Marcel Holtmann7667da32013-10-15 14:26:27 -07006662 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6663 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006664}
Szymon Jancc35938b2011-03-22 13:12:21 +01006665
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006666void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6667 u8 *randomizer192, u8 *hash256,
6668 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006669{
6670 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006671
Johan Hedberg744cf192011-11-08 20:40:14 +02006672 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006673
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006674 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006675 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006676 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006677
6678 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006679 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6680 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006681 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006682 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6683 hash256 && randomizer256) {
6684 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006685
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006686 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6687 memcpy(rp.randomizer192, randomizer192,
6688 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006689
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006690 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6691 memcpy(rp.randomizer256, randomizer256,
6692 sizeof(rp.randomizer256));
6693
6694 cmd_complete(cmd->sk, hdev->id,
6695 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6696 &rp, sizeof(rp));
6697 } else {
6698 struct mgmt_rp_read_local_oob_data rp;
6699
6700 memcpy(rp.hash, hash192, sizeof(rp.hash));
6701 memcpy(rp.randomizer, randomizer192,
6702 sizeof(rp.randomizer));
6703
6704 cmd_complete(cmd->sk, hdev->id,
6705 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6706 &rp, sizeof(rp));
6707 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006708 }
6709
6710 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006711}
Johan Hedberge17acd42011-03-30 23:57:16 +03006712
Marcel Holtmann901801b2013-10-06 23:55:51 -07006713void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006714 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6715 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006716{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006717 char buf[512];
6718 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006719 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006720 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006721
Johan Hedberg75ce2082014-07-02 22:42:01 +03006722 /* Don't send events for a non-kernel initiated discovery. With
6723 * LE one exception is if we have pend_le_reports > 0 in which
6724 * case we're doing passive scanning and want these events.
6725 */
6726 if (!hci_discovery_active(hdev)) {
6727 if (link_type == ACL_LINK)
6728 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006729 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006730 return;
6731 }
Andre Guedes12602d02013-04-30 15:29:40 -03006732
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006733 /* Make sure that the buffer is big enough. The 5 extra bytes
6734 * are for the potential CoD field.
6735 */
6736 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006737 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006738
Johan Hedberg1dc06092012-01-15 21:01:23 +02006739 memset(buf, 0, sizeof(buf));
6740
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006741 irk = hci_get_irk(hdev, bdaddr, addr_type);
6742 if (irk) {
6743 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6744 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6745 } else {
6746 bacpy(&ev->addr.bdaddr, bdaddr);
6747 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6748 }
6749
Johan Hedberge319d2e2012-01-15 19:51:59 +02006750 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006751 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006752
Johan Hedberg1dc06092012-01-15 21:01:23 +02006753 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006754 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006755
Johan Hedberg1dc06092012-01-15 21:01:23 +02006756 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6757 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006758 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006759
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006760 if (scan_rsp_len > 0)
6761 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6762
6763 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6764 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006765
Marcel Holtmann901801b2013-10-06 23:55:51 -07006766 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006767}
Johan Hedberga88a9652011-03-30 13:18:12 +03006768
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006769void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6770 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006771{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006772 struct mgmt_ev_device_found *ev;
6773 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6774 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006775
Johan Hedbergb644ba32012-01-17 21:48:47 +02006776 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006777
Johan Hedbergb644ba32012-01-17 21:48:47 +02006778 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006779
Johan Hedbergb644ba32012-01-17 21:48:47 +02006780 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006781 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006782 ev->rssi = rssi;
6783
6784 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006785 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006786
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006787 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006788
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006789 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006790}
Johan Hedberg314b2382011-04-27 10:29:57 -04006791
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006792void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006793{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006794 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006795 struct pending_cmd *cmd;
6796
Andre Guedes343fb142011-11-22 17:14:19 -03006797 BT_DBG("%s discovering %u", hdev->name, discovering);
6798
Johan Hedberg164a6e72011-11-01 17:06:44 +02006799 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006800 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006801 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006802 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006803
6804 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006805 u8 type = hdev->discovery.type;
6806
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006807 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6808 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006809 mgmt_pending_remove(cmd);
6810 }
6811
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006812 memset(&ev, 0, sizeof(ev));
6813 ev.type = hdev->discovery.type;
6814 ev.discovering = discovering;
6815
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006816 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006817}
Antti Julku5e762442011-08-25 16:48:02 +03006818
Marcel Holtmann5976e602013-10-06 04:08:14 -07006819static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6820{
6821 BT_DBG("%s status %u", hdev->name, status);
6822
6823 /* Clear the advertising mgmt setting if we failed to re-enable it */
6824 if (status) {
6825 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006826 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006827 }
6828}
6829
6830void mgmt_reenable_advertising(struct hci_dev *hdev)
6831{
6832 struct hci_request req;
6833
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006834 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006835 return;
6836
6837 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6838 return;
6839
6840 hci_req_init(&req, hdev);
6841 enable_advertising(&req);
6842
6843 /* If this fails we have no option but to let user space know
6844 * that we've disabled advertising.
6845 */
6846 if (hci_req_run(&req, adv_enable_complete) < 0) {
6847 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006848 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006849 }
6850}