blob: 38f05386bc0c41f7221602a04fc2aca64ab62a3b [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200132#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
133 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
134
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135struct pending_cmd {
136 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200137 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100139 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac12014-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001042static void disable_advertising(struct hci_request *req)
1043{
1044 u8 enable = 0x00;
1045
1046 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1047}
1048
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001049static void enable_advertising(struct hci_request *req)
1050{
1051 struct hci_dev *hdev = req->hdev;
1052 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001053 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001054 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001055
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001056 if (hci_conn_num(hdev, LE_LINK) > 0)
1057 return;
1058
1059 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1060 disable_advertising(req);
1061
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001062 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001063 * hci_update_random_address knows that it's safe to go ahead
1064 * and write a new random address. The flag will be set back on
1065 * as soon as the SET_ADV_ENABLE HCI command completes.
1066 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001067 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001068
Johan Hedberga4858cb2014-02-25 19:56:31 +02001069 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001070
Johan Hedberga4858cb2014-02-25 19:56:31 +02001071 /* Set require_privacy to true only when non-connectable
1072 * advertising is used. In that case it is fine to use a
1073 * non-resolvable private address.
1074 */
1075 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001076 return;
1077
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001078 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001079 cp.min_interval = cpu_to_le16(0x0800);
1080 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001081 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001082 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001083 cp.channel_map = hdev->le_adv_channel_map;
1084
1085 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1086
1087 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1088}
1089
Johan Hedberg7d785252011-12-15 00:47:39 +02001090static void service_cache_off(struct work_struct *work)
1091{
1092 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001093 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001094 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001095
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001096 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001097 return;
1098
Johan Hedberg890ea892013-03-15 17:06:52 -05001099 hci_req_init(&req, hdev);
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101 hci_dev_lock(hdev);
1102
Johan Hedberg890ea892013-03-15 17:06:52 -05001103 update_eir(&req);
1104 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001105
1106 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001107
1108 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001109}
1110
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001111static void rpa_expired(struct work_struct *work)
1112{
1113 struct hci_dev *hdev = container_of(work, struct hci_dev,
1114 rpa_expired.work);
1115 struct hci_request req;
1116
1117 BT_DBG("");
1118
1119 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1120
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001121 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122 return;
1123
1124 /* The generation of a new RPA and programming it into the
1125 * controller happens in the enable_advertising() function.
1126 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001127 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001128 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001129 hci_req_run(&req, NULL);
1130}
1131
Johan Hedberg6a919082012-02-28 06:17:26 +02001132static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001133{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001134 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001135 return;
1136
Johan Hedberg4f87da82012-03-02 19:55:56 +02001137 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001139
Johan Hedberg4f87da82012-03-02 19:55:56 +02001140 /* Non-mgmt controlled devices get this bit set
1141 * implicitly so that pairing works for them, however
1142 * for mgmt we require user-space to explicitly enable
1143 * it
1144 */
1145 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001146}
1147
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001148static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001149 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001150{
1151 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001152
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001153 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001154
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001155 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001156
Johan Hedberg03811012010-12-08 00:21:06 +02001157 memset(&rp, 0, sizeof(rp));
1158
Johan Hedberg03811012010-12-08 00:21:06 +02001159 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001160
1161 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001162 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001163
1164 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1165 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1166
1167 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001168
1169 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001170 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001171
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001172 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001174 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001175 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001176}
1177
1178static void mgmt_pending_free(struct pending_cmd *cmd)
1179{
1180 sock_put(cmd->sk);
1181 kfree(cmd->param);
1182 kfree(cmd);
1183}
1184
1185static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 struct hci_dev *hdev, void *data,
1187 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001188{
1189 struct pending_cmd *cmd;
1190
Johan Hedbergfca20012014-06-28 17:54:05 +03001191 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001192 if (!cmd)
1193 return NULL;
1194
1195 cmd->opcode = opcode;
1196 cmd->index = hdev->id;
1197
Andre Guedes12b94562012-06-07 19:05:45 -03001198 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001199 if (!cmd->param) {
1200 kfree(cmd);
1201 return NULL;
1202 }
1203
1204 if (data)
1205 memcpy(cmd->param, data, len);
1206
1207 cmd->sk = sk;
1208 sock_hold(sk);
1209
1210 list_add(&cmd->list, &hdev->mgmt_pending);
1211
1212 return cmd;
1213}
1214
1215static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001216 void (*cb)(struct pending_cmd *cmd,
1217 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001218 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001219{
Andre Guedesa3d09352013-02-01 11:21:30 -03001220 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001221
Andre Guedesa3d09352013-02-01 11:21:30 -03001222 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001223 if (opcode > 0 && cmd->opcode != opcode)
1224 continue;
1225
1226 cb(cmd, data);
1227 }
1228}
1229
Johan Hedberg03811012010-12-08 00:21:06 +02001230static void mgmt_pending_remove(struct pending_cmd *cmd)
1231{
1232 list_del(&cmd->list);
1233 mgmt_pending_free(cmd);
1234}
1235
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001236static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001237{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001238 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001239
Johan Hedbergaee9b212012-02-18 15:07:59 +02001240 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001241 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001242}
1243
Johan Hedberg8b064a32014-02-24 14:52:22 +02001244static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1245{
1246 BT_DBG("%s status 0x%02x", hdev->name, status);
1247
Johan Hedberga3172b72014-02-28 09:33:44 +02001248 if (hci_conn_count(hdev) == 0) {
1249 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001250 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001251 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001252}
1253
Johan Hedberg23a48092014-07-08 16:05:06 +03001254static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001255{
1256 struct hci_dev *hdev = req->hdev;
1257 struct hci_cp_remote_name_req_cancel cp;
1258 struct inquiry_entry *e;
1259
1260 switch (hdev->discovery.state) {
1261 case DISCOVERY_FINDING:
1262 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1263 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1264 } else {
1265 cancel_delayed_work(&hdev->le_scan_disable);
1266 hci_req_add_le_scan_disable(req);
1267 }
1268
Johan Hedberg23a48092014-07-08 16:05:06 +03001269 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001270
1271 case DISCOVERY_RESOLVING:
1272 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1273 NAME_PENDING);
1274 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001275 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001276
1277 bacpy(&cp.bdaddr, &e->data.bdaddr);
1278 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1279 &cp);
1280
Johan Hedberg23a48092014-07-08 16:05:06 +03001281 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001282
1283 default:
1284 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001287 return true;
1288 }
1289
Johan Hedberg21a60d32014-06-10 14:05:58 +03001290 break;
1291 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001292
1293 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001294}
1295
Johan Hedberg8b064a32014-02-24 14:52:22 +02001296static int clean_up_hci_state(struct hci_dev *hdev)
1297{
1298 struct hci_request req;
1299 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001300 bool discov_stopped;
1301 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001302
1303 hci_req_init(&req, hdev);
1304
1305 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1306 test_bit(HCI_PSCAN, &hdev->flags)) {
1307 u8 scan = 0x00;
1308 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1309 }
1310
Johan Hedberg73e082f2014-07-08 15:07:51 +03001311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312 disable_advertising(&req);
1313
Johan Hedberg23a48092014-07-08 16:05:06 +03001314 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001315
1316 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1317 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001318 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001319
Johan Hedbergc9910d02014-02-27 14:35:12 +02001320 switch (conn->state) {
1321 case BT_CONNECTED:
1322 case BT_CONFIG:
1323 dc.handle = cpu_to_le16(conn->handle);
1324 dc.reason = 0x15; /* Terminated due to Power Off */
1325 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1326 break;
1327 case BT_CONNECT:
1328 if (conn->type == LE_LINK)
1329 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1330 0, NULL);
1331 else if (conn->type == ACL_LINK)
1332 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1333 6, &conn->dst);
1334 break;
1335 case BT_CONNECT2:
1336 bacpy(&rej.bdaddr, &conn->dst);
1337 rej.reason = 0x15; /* Terminated due to Power Off */
1338 if (conn->type == ACL_LINK)
1339 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1340 sizeof(rej), &rej);
1341 else if (conn->type == SCO_LINK)
1342 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1343 sizeof(rej), &rej);
1344 break;
1345 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001346 }
1347
Johan Hedberg23a48092014-07-08 16:05:06 +03001348 err = hci_req_run(&req, clean_up_hci_complete);
1349 if (!err && discov_stopped)
1350 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1351
1352 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001353}
1354
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001355static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001356 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001357{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001358 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001359 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001360 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001362 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001363
Johan Hedberga7e80f22013-01-09 16:05:19 +02001364 if (cp->val != 0x00 && cp->val != 0x01)
1365 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1366 MGMT_STATUS_INVALID_PARAMS);
1367
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001368 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001369
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001370 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1371 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1372 MGMT_STATUS_BUSY);
1373 goto failed;
1374 }
1375
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001376 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1377 cancel_delayed_work(&hdev->power_off);
1378
1379 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001380 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1381 data, len);
1382 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001383 goto failed;
1384 }
1385 }
1386
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001387 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001388 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001389 goto failed;
1390 }
1391
Johan Hedberg03811012010-12-08 00:21:06 +02001392 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1393 if (!cmd) {
1394 err = -ENOMEM;
1395 goto failed;
1396 }
1397
Johan Hedberg8b064a32014-02-24 14:52:22 +02001398 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001399 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001400 err = 0;
1401 } else {
1402 /* Disconnect connections, stop scans, etc */
1403 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001404 if (!err)
1405 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1406 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 /* ENODATA means there were no HCI commands queued */
1409 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001410 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001411 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1412 err = 0;
1413 }
1414 }
Johan Hedberg03811012010-12-08 00:21:06 +02001415
1416failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001417 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001418 return err;
1419}
1420
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001421static int new_settings(struct hci_dev *hdev, struct sock *skip)
1422{
1423 __le32 ev;
1424
1425 ev = cpu_to_le32(get_current_settings(hdev));
1426
1427 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1428}
1429
Johan Hedberg91a668b2014-07-09 13:28:26 +03001430int mgmt_new_settings(struct hci_dev *hdev)
1431{
1432 return new_settings(hdev, NULL);
1433}
1434
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001435struct cmd_lookup {
1436 struct sock *sk;
1437 struct hci_dev *hdev;
1438 u8 mgmt_status;
1439};
1440
1441static void settings_rsp(struct pending_cmd *cmd, void *data)
1442{
1443 struct cmd_lookup *match = data;
1444
1445 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1446
1447 list_del(&cmd->list);
1448
1449 if (match->sk == NULL) {
1450 match->sk = cmd->sk;
1451 sock_hold(match->sk);
1452 }
1453
1454 mgmt_pending_free(cmd);
1455}
1456
1457static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1458{
1459 u8 *status = data;
1460
1461 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1462 mgmt_pending_remove(cmd);
1463}
1464
Johan Hedberge6fe7982013-10-02 15:45:22 +03001465static u8 mgmt_bredr_support(struct hci_dev *hdev)
1466{
1467 if (!lmp_bredr_capable(hdev))
1468 return MGMT_STATUS_NOT_SUPPORTED;
1469 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1470 return MGMT_STATUS_REJECTED;
1471 else
1472 return MGMT_STATUS_SUCCESS;
1473}
1474
1475static u8 mgmt_le_support(struct hci_dev *hdev)
1476{
1477 if (!lmp_le_capable(hdev))
1478 return MGMT_STATUS_NOT_SUPPORTED;
1479 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1480 return MGMT_STATUS_REJECTED;
1481 else
1482 return MGMT_STATUS_SUCCESS;
1483}
1484
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001485static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1486{
1487 struct pending_cmd *cmd;
1488 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001489 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001490 bool changed;
1491
1492 BT_DBG("status 0x%02x", status);
1493
1494 hci_dev_lock(hdev);
1495
1496 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1497 if (!cmd)
1498 goto unlock;
1499
1500 if (status) {
1501 u8 mgmt_err = mgmt_status(status);
1502 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001503 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504 goto remove_cmd;
1505 }
1506
1507 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001508 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001509 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1510 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001511
1512 if (hdev->discov_timeout > 0) {
1513 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1514 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1515 to);
1516 }
1517 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001518 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1519 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001520 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521
1522 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1523
1524 if (changed)
1525 new_settings(hdev, cmd->sk);
1526
Marcel Holtmann970ba522013-10-15 06:33:57 -07001527 /* When the discoverable mode gets changed, make sure
1528 * that class of device has the limited discoverable
1529 * bit correctly set.
1530 */
1531 hci_req_init(&req, hdev);
1532 update_class(&req);
1533 hci_req_run(&req, NULL);
1534
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001535remove_cmd:
1536 mgmt_pending_remove(cmd);
1537
1538unlock:
1539 hci_dev_unlock(hdev);
1540}
1541
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001542static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001543 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001544{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001545 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001546 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001547 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001548 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001549 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001550 int err;
1551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001552 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001553
Johan Hedberg9a43e252013-10-20 19:00:07 +03001554 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1555 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001556 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001557 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001558
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001559 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001560 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1561 MGMT_STATUS_INVALID_PARAMS);
1562
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001563 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001564
1565 /* Disabling discoverable requires that no timeout is set,
1566 * and enabling limited discoverable requires a timeout.
1567 */
1568 if ((cp->val == 0x00 && timeout > 0) ||
1569 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001571 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001572
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001573 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001574
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001575 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001576 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001577 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001578 goto failed;
1579 }
1580
1581 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001582 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001583 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001584 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001585 goto failed;
1586 }
1587
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001588 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001589 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001590 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001591 goto failed;
1592 }
1593
1594 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001595 bool changed = false;
1596
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001597 /* Setting limited discoverable when powered off is
1598 * not a valid operation since it requires a timeout
1599 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1600 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001601 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1602 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1603 changed = true;
1604 }
1605
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001606 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001607 if (err < 0)
1608 goto failed;
1609
1610 if (changed)
1611 err = new_settings(hdev, sk);
1612
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001613 goto failed;
1614 }
1615
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001616 /* If the current mode is the same, then just update the timeout
1617 * value with the new value. And if only the timeout gets updated,
1618 * then no need for any HCI transactions.
1619 */
1620 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1621 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1622 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001623 cancel_delayed_work(&hdev->discov_off);
1624 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001625
Marcel Holtmann36261542013-10-15 08:28:51 -07001626 if (cp->val && hdev->discov_timeout > 0) {
1627 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001628 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001629 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001630 }
1631
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001632 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001633 goto failed;
1634 }
1635
1636 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1637 if (!cmd) {
1638 err = -ENOMEM;
1639 goto failed;
1640 }
1641
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001642 /* Cancel any potential discoverable timeout that might be
1643 * still active and store new timeout value. The arming of
1644 * the timeout happens in the complete handler.
1645 */
1646 cancel_delayed_work(&hdev->discov_off);
1647 hdev->discov_timeout = timeout;
1648
Johan Hedbergb456f872013-10-19 23:38:22 +03001649 /* Limited discoverable mode */
1650 if (cp->val == 0x02)
1651 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1652 else
1653 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1654
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001655 hci_req_init(&req, hdev);
1656
Johan Hedberg9a43e252013-10-20 19:00:07 +03001657 /* The procedure for LE-only controllers is much simpler - just
1658 * update the advertising data.
1659 */
1660 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1661 goto update_ad;
1662
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001663 scan = SCAN_PAGE;
1664
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001665 if (cp->val) {
1666 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001667
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001668 if (cp->val == 0x02) {
1669 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001670 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001671 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1672 hci_cp.iac_lap[1] = 0x8b;
1673 hci_cp.iac_lap[2] = 0x9e;
1674 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1675 hci_cp.iac_lap[4] = 0x8b;
1676 hci_cp.iac_lap[5] = 0x9e;
1677 } else {
1678 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001679 hci_cp.num_iac = 1;
1680 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1681 hci_cp.iac_lap[1] = 0x8b;
1682 hci_cp.iac_lap[2] = 0x9e;
1683 }
1684
1685 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1686 (hci_cp.num_iac * 3) + 1, &hci_cp);
1687
1688 scan |= SCAN_INQUIRY;
1689 } else {
1690 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1691 }
1692
1693 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001694
Johan Hedberg9a43e252013-10-20 19:00:07 +03001695update_ad:
1696 update_adv_data(&req);
1697
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001698 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001699 if (err < 0)
1700 mgmt_pending_remove(cmd);
1701
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001702failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001703 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001704 return err;
1705}
1706
Johan Hedberg406d7802013-03-15 17:07:09 -05001707static void write_fast_connectable(struct hci_request *req, bool enable)
1708{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001709 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001710 struct hci_cp_write_page_scan_activity acp;
1711 u8 type;
1712
Johan Hedberg547003b2013-10-21 16:51:53 +03001713 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1714 return;
1715
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001716 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1717 return;
1718
Johan Hedberg406d7802013-03-15 17:07:09 -05001719 if (enable) {
1720 type = PAGE_SCAN_TYPE_INTERLACED;
1721
1722 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001723 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001724 } else {
1725 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1726
1727 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001728 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001729 }
1730
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001731 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001732
Johan Hedbergbd98b992013-03-15 17:07:13 -05001733 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1734 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1735 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1736 sizeof(acp), &acp);
1737
1738 if (hdev->page_scan_type != type)
1739 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001740}
1741
Johan Hedberg2b76f452013-03-15 17:07:04 -05001742static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1743{
1744 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001745 struct mgmt_mode *cp;
1746 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001747
1748 BT_DBG("status 0x%02x", status);
1749
1750 hci_dev_lock(hdev);
1751
1752 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1753 if (!cmd)
1754 goto unlock;
1755
Johan Hedberg37438c12013-10-14 16:20:05 +03001756 if (status) {
1757 u8 mgmt_err = mgmt_status(status);
1758 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1759 goto remove_cmd;
1760 }
1761
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001762 cp = cmd->param;
1763 if (cp->val)
1764 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1765 else
1766 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1767
Johan Hedberg2b76f452013-03-15 17:07:04 -05001768 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1769
Johan Hedberg2b7be332014-07-07 14:40:22 +03001770 if (changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001771 new_settings(hdev, cmd->sk);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001772 hci_update_background_scan(hdev);
1773 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001774
Johan Hedberg37438c12013-10-14 16:20:05 +03001775remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001776 mgmt_pending_remove(cmd);
1777
1778unlock:
1779 hci_dev_unlock(hdev);
1780}
1781
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001782static int set_connectable_update_settings(struct hci_dev *hdev,
1783 struct sock *sk, u8 val)
1784{
1785 bool changed = false;
1786 int err;
1787
1788 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1789 changed = true;
1790
1791 if (val) {
1792 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1793 } else {
1794 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1795 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1796 }
1797
1798 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1799 if (err < 0)
1800 return err;
1801
Johan Hedberg562064e2014-07-08 16:35:34 +03001802 if (changed) {
1803 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001804 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001805 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001806
1807 return 0;
1808}
1809
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001810static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001811 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001812{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001813 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001814 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001815 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001816 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001817 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001818
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001819 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001820
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001821 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1822 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001823 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001824 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001825
Johan Hedberga7e80f22013-01-09 16:05:19 +02001826 if (cp->val != 0x00 && cp->val != 0x01)
1827 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1828 MGMT_STATUS_INVALID_PARAMS);
1829
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001830 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001831
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001832 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001833 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001834 goto failed;
1835 }
1836
1837 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001838 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001839 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001840 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001841 goto failed;
1842 }
1843
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001844 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1845 if (!cmd) {
1846 err = -ENOMEM;
1847 goto failed;
1848 }
1849
Johan Hedberg2b76f452013-03-15 17:07:04 -05001850 hci_req_init(&req, hdev);
1851
Johan Hedberg9a43e252013-10-20 19:00:07 +03001852 /* If BR/EDR is not enabled and we disable advertising as a
1853 * by-product of disabling connectable, we need to update the
1854 * advertising flags.
1855 */
1856 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1857 if (!cp->val) {
1858 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1859 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1860 }
1861 update_adv_data(&req);
1862 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001863 if (cp->val) {
1864 scan = SCAN_PAGE;
1865 } else {
1866 scan = 0;
1867
1868 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001869 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001870 cancel_delayed_work(&hdev->discov_off);
1871 }
1872
1873 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1874 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001875
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001876 /* If we're going from non-connectable to connectable or
1877 * vice-versa when fast connectable is enabled ensure that fast
1878 * connectable gets disabled. write_fast_connectable won't do
1879 * anything if the page scan parameters are already what they
1880 * should be.
1881 */
1882 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001883 write_fast_connectable(&req, false);
1884
Johan Hedberge8b12022014-07-10 10:51:27 +03001885 /* Update the advertising parameters if necessary */
1886 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001887 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001888
Johan Hedberg2b76f452013-03-15 17:07:04 -05001889 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001890 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001891 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001892 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001893 err = set_connectable_update_settings(hdev, sk,
1894 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001895 goto failed;
1896 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001897
1898failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001899 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001900 return err;
1901}
1902
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001903static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001904 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001905{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001906 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001907 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001908 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001909
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001910 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001911
Johan Hedberga7e80f22013-01-09 16:05:19 +02001912 if (cp->val != 0x00 && cp->val != 0x01)
1913 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1914 MGMT_STATUS_INVALID_PARAMS);
1915
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001916 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001917
1918 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001919 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001920 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001921 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001922
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001923 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001924 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001925 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001926
Marcel Holtmann55594352013-10-06 16:11:57 -07001927 if (changed)
1928 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001929
Marcel Holtmann55594352013-10-06 16:11:57 -07001930unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001931 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001932 return err;
1933}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001934
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001935static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1936 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001937{
1938 struct mgmt_mode *cp = data;
1939 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001940 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001941 int err;
1942
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001943 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001944
Johan Hedberge6fe7982013-10-02 15:45:22 +03001945 status = mgmt_bredr_support(hdev);
1946 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001947 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001948 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001949
Johan Hedberga7e80f22013-01-09 16:05:19 +02001950 if (cp->val != 0x00 && cp->val != 0x01)
1951 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1952 MGMT_STATUS_INVALID_PARAMS);
1953
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001954 hci_dev_lock(hdev);
1955
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001956 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001957 bool changed = false;
1958
1959 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001960 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001961 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1962 changed = true;
1963 }
1964
1965 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1966 if (err < 0)
1967 goto failed;
1968
1969 if (changed)
1970 err = new_settings(hdev, sk);
1971
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001972 goto failed;
1973 }
1974
1975 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001976 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001977 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001978 goto failed;
1979 }
1980
1981 val = !!cp->val;
1982
1983 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1984 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1985 goto failed;
1986 }
1987
1988 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1989 if (!cmd) {
1990 err = -ENOMEM;
1991 goto failed;
1992 }
1993
1994 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1995 if (err < 0) {
1996 mgmt_pending_remove(cmd);
1997 goto failed;
1998 }
1999
2000failed:
2001 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002002 return err;
2003}
2004
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002005static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002006{
2007 struct mgmt_mode *cp = data;
2008 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002009 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002010 int err;
2011
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002012 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002013
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002014 status = mgmt_bredr_support(hdev);
2015 if (status)
2016 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2017
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002018 if (!lmp_ssp_capable(hdev))
2019 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2020 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002021
Johan Hedberga7e80f22013-01-09 16:05:19 +02002022 if (cp->val != 0x00 && cp->val != 0x01)
2023 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2024 MGMT_STATUS_INVALID_PARAMS);
2025
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002026 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002027
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002028 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002029 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002030
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002031 if (cp->val) {
2032 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2033 &hdev->dev_flags);
2034 } else {
2035 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2036 &hdev->dev_flags);
2037 if (!changed)
2038 changed = test_and_clear_bit(HCI_HS_ENABLED,
2039 &hdev->dev_flags);
2040 else
2041 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002042 }
2043
2044 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2045 if (err < 0)
2046 goto failed;
2047
2048 if (changed)
2049 err = new_settings(hdev, sk);
2050
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002051 goto failed;
2052 }
2053
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002054 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2055 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002056 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2057 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002058 goto failed;
2059 }
2060
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002061 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002062 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2063 goto failed;
2064 }
2065
2066 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2067 if (!cmd) {
2068 err = -ENOMEM;
2069 goto failed;
2070 }
2071
Johan Hedberg37699722014-06-24 14:00:27 +03002072 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2073 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2074 sizeof(cp->val), &cp->val);
2075
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002076 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002077 if (err < 0) {
2078 mgmt_pending_remove(cmd);
2079 goto failed;
2080 }
2081
2082failed:
2083 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002084 return err;
2085}
2086
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002087static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002088{
2089 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002090 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002091 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002092 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002094 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002095
Johan Hedberge6fe7982013-10-02 15:45:22 +03002096 status = mgmt_bredr_support(hdev);
2097 if (status)
2098 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002099
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002100 if (!lmp_ssp_capable(hdev))
2101 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2102 MGMT_STATUS_NOT_SUPPORTED);
2103
2104 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2105 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2106 MGMT_STATUS_REJECTED);
2107
Johan Hedberga7e80f22013-01-09 16:05:19 +02002108 if (cp->val != 0x00 && cp->val != 0x01)
2109 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2110 MGMT_STATUS_INVALID_PARAMS);
2111
Marcel Holtmannee392692013-10-01 22:59:23 -07002112 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002113
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002114 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002115 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002116 } else {
2117 if (hdev_is_powered(hdev)) {
2118 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2119 MGMT_STATUS_REJECTED);
2120 goto unlock;
2121 }
2122
Marcel Holtmannee392692013-10-01 22:59:23 -07002123 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002124 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002125
2126 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2127 if (err < 0)
2128 goto unlock;
2129
2130 if (changed)
2131 err = new_settings(hdev, sk);
2132
2133unlock:
2134 hci_dev_unlock(hdev);
2135 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002136}
2137
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002138static void le_enable_complete(struct hci_dev *hdev, u8 status)
2139{
2140 struct cmd_lookup match = { NULL, hdev };
2141
2142 if (status) {
2143 u8 mgmt_err = mgmt_status(status);
2144
2145 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2146 &mgmt_err);
2147 return;
2148 }
2149
2150 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2151
2152 new_settings(hdev, match.sk);
2153
2154 if (match.sk)
2155 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002156
2157 /* Make sure the controller has a good default for
2158 * advertising data. Restrict the update to when LE
2159 * has actually been enabled. During power on, the
2160 * update in powered_update_hci will take care of it.
2161 */
2162 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2163 struct hci_request req;
2164
2165 hci_dev_lock(hdev);
2166
2167 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002168 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002169 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002170 hci_req_run(&req, NULL);
2171
Johan Hedberga70f4b52014-07-07 15:19:50 +03002172 hci_update_background_scan(hdev);
2173
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002174 hci_dev_unlock(hdev);
2175 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002176}
2177
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002178static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002179{
2180 struct mgmt_mode *cp = data;
2181 struct hci_cp_write_le_host_supported hci_cp;
2182 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002183 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002184 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002185 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002186
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002187 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002188
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002189 if (!lmp_le_capable(hdev))
2190 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2191 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002192
Johan Hedberga7e80f22013-01-09 16:05:19 +02002193 if (cp->val != 0x00 && cp->val != 0x01)
2194 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2195 MGMT_STATUS_INVALID_PARAMS);
2196
Johan Hedbergc73eee92013-04-19 18:35:21 +03002197 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002198 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002199 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2200 MGMT_STATUS_REJECTED);
2201
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002202 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002203
2204 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002205 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002206
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002207 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002208 bool changed = false;
2209
2210 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2211 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2212 changed = true;
2213 }
2214
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002215 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2216 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002217 changed = true;
2218 }
2219
Johan Hedberg06199cf2012-02-22 16:37:11 +02002220 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2221 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002222 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002223
2224 if (changed)
2225 err = new_settings(hdev, sk);
2226
Johan Hedberg1de028c2012-02-29 19:55:35 -08002227 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002228 }
2229
Johan Hedberg4375f102013-09-25 13:26:10 +03002230 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2231 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002232 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002233 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002234 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002235 }
2236
2237 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2238 if (!cmd) {
2239 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002240 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002241 }
2242
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002243 hci_req_init(&req, hdev);
2244
Johan Hedberg06199cf2012-02-22 16:37:11 +02002245 memset(&hci_cp, 0, sizeof(hci_cp));
2246
2247 if (val) {
2248 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002249 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002250 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002251 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002252 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002253 }
2254
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002255 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2256 &hci_cp);
2257
2258 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302259 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002260 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002261
Johan Hedberg1de028c2012-02-29 19:55:35 -08002262unlock:
2263 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002264 return err;
2265}
2266
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002267/* This is a helper function to test for pending mgmt commands that can
2268 * cause CoD or EIR HCI commands. We can only allow one such pending
2269 * mgmt command at a time since otherwise we cannot easily track what
2270 * the current values are, will be, and based on that calculate if a new
2271 * HCI command needs to be sent and if yes with what value.
2272 */
2273static bool pending_eir_or_class(struct hci_dev *hdev)
2274{
2275 struct pending_cmd *cmd;
2276
2277 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2278 switch (cmd->opcode) {
2279 case MGMT_OP_ADD_UUID:
2280 case MGMT_OP_REMOVE_UUID:
2281 case MGMT_OP_SET_DEV_CLASS:
2282 case MGMT_OP_SET_POWERED:
2283 return true;
2284 }
2285 }
2286
2287 return false;
2288}
2289
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002290static const u8 bluetooth_base_uuid[] = {
2291 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2292 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2293};
2294
2295static u8 get_uuid_size(const u8 *uuid)
2296{
2297 u32 val;
2298
2299 if (memcmp(uuid, bluetooth_base_uuid, 12))
2300 return 128;
2301
2302 val = get_unaligned_le32(&uuid[12]);
2303 if (val > 0xffff)
2304 return 32;
2305
2306 return 16;
2307}
2308
Johan Hedberg92da6092013-03-15 17:06:55 -05002309static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2310{
2311 struct pending_cmd *cmd;
2312
2313 hci_dev_lock(hdev);
2314
2315 cmd = mgmt_pending_find(mgmt_op, hdev);
2316 if (!cmd)
2317 goto unlock;
2318
2319 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2320 hdev->dev_class, 3);
2321
2322 mgmt_pending_remove(cmd);
2323
2324unlock:
2325 hci_dev_unlock(hdev);
2326}
2327
2328static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2329{
2330 BT_DBG("status 0x%02x", status);
2331
2332 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2333}
2334
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002335static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002336{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002337 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002338 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002339 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002340 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002341 int err;
2342
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002343 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002344
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002345 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002346
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002347 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002348 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002349 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002350 goto failed;
2351 }
2352
Andre Guedes92c4c202012-06-07 19:05:44 -03002353 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002354 if (!uuid) {
2355 err = -ENOMEM;
2356 goto failed;
2357 }
2358
2359 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002360 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002361 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002362
Johan Hedbergde66aa62013-01-27 00:31:27 +02002363 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002364
Johan Hedberg890ea892013-03-15 17:06:52 -05002365 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002366
Johan Hedberg890ea892013-03-15 17:06:52 -05002367 update_class(&req);
2368 update_eir(&req);
2369
Johan Hedberg92da6092013-03-15 17:06:55 -05002370 err = hci_req_run(&req, add_uuid_complete);
2371 if (err < 0) {
2372 if (err != -ENODATA)
2373 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002374
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002375 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002376 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002377 goto failed;
2378 }
2379
2380 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002381 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002382 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002383 goto failed;
2384 }
2385
2386 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002387
2388failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002389 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002390 return err;
2391}
2392
Johan Hedberg24b78d02012-02-23 23:24:30 +02002393static bool enable_service_cache(struct hci_dev *hdev)
2394{
2395 if (!hdev_is_powered(hdev))
2396 return false;
2397
2398 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002399 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2400 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002401 return true;
2402 }
2403
2404 return false;
2405}
2406
Johan Hedberg92da6092013-03-15 17:06:55 -05002407static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2408{
2409 BT_DBG("status 0x%02x", status);
2410
2411 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2412}
2413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002414static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002415 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002416{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002417 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002418 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002419 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002420 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 -05002421 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422 int err, found;
2423
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002424 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002425
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002426 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002427
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002428 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002429 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002430 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002431 goto unlock;
2432 }
2433
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002434 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002435 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002436
Johan Hedberg24b78d02012-02-23 23:24:30 +02002437 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002438 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002439 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002440 goto unlock;
2441 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002442
Johan Hedberg9246a862012-02-23 21:33:16 +02002443 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002444 }
2445
2446 found = 0;
2447
Johan Hedberg056341c2013-01-27 00:31:30 +02002448 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002449 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2450 continue;
2451
2452 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002453 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002454 found++;
2455 }
2456
2457 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002458 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002459 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002460 goto unlock;
2461 }
2462
Johan Hedberg9246a862012-02-23 21:33:16 +02002463update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002464 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002465
Johan Hedberg890ea892013-03-15 17:06:52 -05002466 update_class(&req);
2467 update_eir(&req);
2468
Johan Hedberg92da6092013-03-15 17:06:55 -05002469 err = hci_req_run(&req, remove_uuid_complete);
2470 if (err < 0) {
2471 if (err != -ENODATA)
2472 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002474 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002475 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002476 goto unlock;
2477 }
2478
2479 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002480 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002481 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002482 goto unlock;
2483 }
2484
2485 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002486
2487unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002488 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002489 return err;
2490}
2491
Johan Hedberg92da6092013-03-15 17:06:55 -05002492static void set_class_complete(struct hci_dev *hdev, u8 status)
2493{
2494 BT_DBG("status 0x%02x", status);
2495
2496 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2497}
2498
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002499static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002500 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002501{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002502 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002503 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002504 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002505 int err;
2506
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002507 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002508
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002509 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002510 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2511 MGMT_STATUS_NOT_SUPPORTED);
2512
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002513 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002514
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002515 if (pending_eir_or_class(hdev)) {
2516 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2517 MGMT_STATUS_BUSY);
2518 goto unlock;
2519 }
2520
2521 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2522 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2523 MGMT_STATUS_INVALID_PARAMS);
2524 goto unlock;
2525 }
2526
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002527 hdev->major_class = cp->major;
2528 hdev->minor_class = cp->minor;
2529
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002530 if (!hdev_is_powered(hdev)) {
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 Hedberg932f5ff2012-02-22 22:11:32 +02002533 goto unlock;
2534 }
2535
Johan Hedberg890ea892013-03-15 17:06:52 -05002536 hci_req_init(&req, hdev);
2537
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002538 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002539 hci_dev_unlock(hdev);
2540 cancel_delayed_work_sync(&hdev->service_cache);
2541 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002543 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002544
Johan Hedberg890ea892013-03-15 17:06:52 -05002545 update_class(&req);
2546
Johan Hedberg92da6092013-03-15 17:06:55 -05002547 err = hci_req_run(&req, set_class_complete);
2548 if (err < 0) {
2549 if (err != -ENODATA)
2550 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002552 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002553 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002554 goto unlock;
2555 }
2556
2557 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002558 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002559 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002560 goto unlock;
2561 }
2562
2563 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002564
Johan Hedbergb5235a62012-02-21 14:32:24 +02002565unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002566 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002567 return err;
2568}
2569
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002570static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002571 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002572{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002573 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002574 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2575 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002576 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002577 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002578 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002579
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002580 BT_DBG("request for %s", hdev->name);
2581
2582 if (!lmp_bredr_capable(hdev))
2583 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2584 MGMT_STATUS_NOT_SUPPORTED);
2585
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002586 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002587 if (key_count > max_key_count) {
2588 BT_ERR("load_link_keys: too big key_count value %u",
2589 key_count);
2590 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2591 MGMT_STATUS_INVALID_PARAMS);
2592 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002593
Johan Hedberg86742e12011-11-07 23:13:38 +02002594 expected_len = sizeof(*cp) + key_count *
2595 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002596 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002597 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002598 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002599 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002600 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002601 }
2602
Johan Hedberg4ae14302013-01-20 14:27:13 +02002603 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2604 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2605 MGMT_STATUS_INVALID_PARAMS);
2606
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002607 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002608 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002609
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002610 for (i = 0; i < key_count; i++) {
2611 struct mgmt_link_key_info *key = &cp->keys[i];
2612
Marcel Holtmann8e991132014-01-10 02:07:25 -08002613 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002614 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2615 MGMT_STATUS_INVALID_PARAMS);
2616 }
2617
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002618 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002619
2620 hci_link_keys_clear(hdev);
2621
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002622 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002623 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2624 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002625 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002626 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2627 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002628
2629 if (changed)
2630 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002631
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002632 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002633 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002634
Johan Hedberg58e92932014-06-24 14:00:26 +03002635 /* Always ignore debug keys and require a new pairing if
2636 * the user wants to use them.
2637 */
2638 if (key->type == HCI_LK_DEBUG_COMBINATION)
2639 continue;
2640
Johan Hedberg7652ff62014-06-24 13:15:49 +03002641 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2642 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002643 }
2644
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002645 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002646
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002647 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002648
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002649 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002650}
2651
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002652static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002653 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002654{
2655 struct mgmt_ev_device_unpaired ev;
2656
2657 bacpy(&ev.addr.bdaddr, bdaddr);
2658 ev.addr.type = addr_type;
2659
2660 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002661 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002662}
2663
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002664static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002665 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002666{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002667 struct mgmt_cp_unpair_device *cp = data;
2668 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002669 struct hci_cp_disconnect dc;
2670 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002671 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002672 int err;
2673
Johan Hedberga8a1d192011-11-10 15:54:38 +02002674 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002675 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2676 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002677
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002678 if (!bdaddr_type_is_valid(cp->addr.type))
2679 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2680 MGMT_STATUS_INVALID_PARAMS,
2681 &rp, sizeof(rp));
2682
Johan Hedberg118da702013-01-20 14:27:20 +02002683 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2684 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2685 MGMT_STATUS_INVALID_PARAMS,
2686 &rp, sizeof(rp));
2687
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002688 hci_dev_lock(hdev);
2689
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002690 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002691 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002692 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002693 goto unlock;
2694 }
2695
Johan Hedberge0b2b272014-02-18 17:14:31 +02002696 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002697 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002698 } else {
2699 u8 addr_type;
2700
2701 if (cp->addr.type == BDADDR_LE_PUBLIC)
2702 addr_type = ADDR_LE_DEV_PUBLIC;
2703 else
2704 addr_type = ADDR_LE_DEV_RANDOM;
2705
Johan Hedberga7ec7332014-02-18 17:14:35 +02002706 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2707
Andre Guedesa9b0a042014-02-26 20:21:52 -03002708 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2709
Johan Hedberge0b2b272014-02-18 17:14:31 +02002710 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2711 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002712
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002713 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002714 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002715 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002716 goto unlock;
2717 }
2718
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002719 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002720 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002721 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002722 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002723 else
2724 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002725 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002726 } else {
2727 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002728 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002729
Johan Hedberga8a1d192011-11-10 15:54:38 +02002730 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002731 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002732 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002733 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002734 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002735 }
2736
Johan Hedberg124f6e32012-02-09 13:50:12 +02002737 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002738 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002739 if (!cmd) {
2740 err = -ENOMEM;
2741 goto unlock;
2742 }
2743
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002744 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002745 dc.reason = 0x13; /* Remote User Terminated Connection */
2746 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2747 if (err < 0)
2748 mgmt_pending_remove(cmd);
2749
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002750unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002751 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002752 return err;
2753}
2754
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002757{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002758 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002759 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002760 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002761 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002762 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002763 int err;
2764
2765 BT_DBG("");
2766
Johan Hedberg06a63b12013-01-20 14:27:21 +02002767 memset(&rp, 0, sizeof(rp));
2768 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2769 rp.addr.type = cp->addr.type;
2770
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002771 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002772 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2773 MGMT_STATUS_INVALID_PARAMS,
2774 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002775
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002776 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002777
2778 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002779 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2780 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002781 goto failed;
2782 }
2783
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002784 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002785 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2786 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002787 goto failed;
2788 }
2789
Andre Guedes591f47f2012-04-24 21:02:49 -03002790 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002791 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2792 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002793 else
2794 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002795
Vishal Agarwalf9607272012-06-13 05:32:43 +05302796 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002797 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2798 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002799 goto failed;
2800 }
2801
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002802 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002803 if (!cmd) {
2804 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002805 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002806 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002807
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002808 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002809 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002810
2811 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2812 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002813 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002814
2815failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002816 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002817 return err;
2818}
2819
Andre Guedes57c14772012-04-24 21:02:50 -03002820static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002821{
2822 switch (link_type) {
2823 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002824 switch (addr_type) {
2825 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002826 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002827
Johan Hedberg48264f02011-11-09 13:58:58 +02002828 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002829 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002830 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002831 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002832
Johan Hedberg4c659c32011-11-07 23:13:39 +02002833 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002834 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002835 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002836 }
2837}
2838
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002839static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2840 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002841{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002842 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002843 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002844 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002845 int err;
2846 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002847
2848 BT_DBG("");
2849
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002850 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002851
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002852 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002853 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002854 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002855 goto unlock;
2856 }
2857
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002858 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002859 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2860 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002861 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002862 }
2863
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002864 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002865 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002866 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002867 err = -ENOMEM;
2868 goto unlock;
2869 }
2870
Johan Hedberg2784eb42011-01-21 13:56:35 +02002871 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002872 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002873 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2874 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002875 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002876 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002877 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002878 continue;
2879 i++;
2880 }
2881
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002882 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002883
Johan Hedberg4c659c32011-11-07 23:13:39 +02002884 /* Recalculate length in case of filtered SCO connections, etc */
2885 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002886
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002887 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002888 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002889
Johan Hedberga38528f2011-01-22 06:46:43 +02002890 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002891
2892unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002893 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002894 return err;
2895}
2896
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002897static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002898 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002899{
2900 struct pending_cmd *cmd;
2901 int err;
2902
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002903 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002904 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002905 if (!cmd)
2906 return -ENOMEM;
2907
Johan Hedbergd8457692012-02-17 14:24:57 +02002908 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002909 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002910 if (err < 0)
2911 mgmt_pending_remove(cmd);
2912
2913 return err;
2914}
2915
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002916static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002917 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002918{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002919 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002920 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002921 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002922 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002923 int err;
2924
2925 BT_DBG("");
2926
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002927 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002928
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002929 if (!hdev_is_powered(hdev)) {
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_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002932 goto failed;
2933 }
2934
Johan Hedbergd8457692012-02-17 14:24:57 +02002935 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002936 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002937 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002938 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002939 goto failed;
2940 }
2941
2942 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002943 struct mgmt_cp_pin_code_neg_reply ncp;
2944
2945 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002946
2947 BT_ERR("PIN code is not 16 bytes long");
2948
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002949 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002950 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002951 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002952 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002953
2954 goto failed;
2955 }
2956
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002957 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002958 if (!cmd) {
2959 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002960 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002961 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002962
Johan Hedbergd8457692012-02-17 14:24:57 +02002963 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002964 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002965 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002966
2967 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2968 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002969 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002970
2971failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002972 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002973 return err;
2974}
2975
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2977 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002978{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002979 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002980
2981 BT_DBG("");
2982
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002983 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2984 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2985 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2986
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002987 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002988
2989 hdev->io_capability = cp->io_capability;
2990
2991 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002992 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002993
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002994 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002995
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002996 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2997 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002998}
2999
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003000static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003001{
3002 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003003 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003005 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003006 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3007 continue;
3008
Johan Hedberge9a416b2011-02-19 12:05:56 -03003009 if (cmd->user_data != conn)
3010 continue;
3011
3012 return cmd;
3013 }
3014
3015 return NULL;
3016}
3017
3018static void pairing_complete(struct pending_cmd *cmd, u8 status)
3019{
3020 struct mgmt_rp_pair_device rp;
3021 struct hci_conn *conn = cmd->user_data;
3022
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003023 bacpy(&rp.addr.bdaddr, &conn->dst);
3024 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003025
Johan Hedbergaee9b212012-02-18 15:07:59 +02003026 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003027 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003028
3029 /* So we don't get further callbacks for this connection */
3030 conn->connect_cfm_cb = NULL;
3031 conn->security_cfm_cb = NULL;
3032 conn->disconn_cfm_cb = NULL;
3033
David Herrmann76a68ba2013-04-06 20:28:37 +02003034 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003035
Johan Hedberga664b5b2011-02-19 12:06:02 -03003036 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003037}
3038
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003039void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3040{
3041 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3042 struct pending_cmd *cmd;
3043
3044 cmd = find_pairing(conn);
3045 if (cmd)
3046 pairing_complete(cmd, status);
3047}
3048
Johan Hedberge9a416b2011-02-19 12:05:56 -03003049static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3050{
3051 struct pending_cmd *cmd;
3052
3053 BT_DBG("status %u", status);
3054
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003055 cmd = find_pairing(conn);
3056 if (!cmd)
3057 BT_DBG("Unable to find a pending command");
3058 else
Johan Hedberge2113262012-02-18 15:20:03 +02003059 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003060}
3061
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003062static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303063{
3064 struct pending_cmd *cmd;
3065
3066 BT_DBG("status %u", status);
3067
3068 if (!status)
3069 return;
3070
3071 cmd = find_pairing(conn);
3072 if (!cmd)
3073 BT_DBG("Unable to find a pending command");
3074 else
3075 pairing_complete(cmd, mgmt_status(status));
3076}
3077
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003078static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003079 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003080{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003081 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003082 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003083 struct pending_cmd *cmd;
3084 u8 sec_level, auth_type;
3085 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003086 int err;
3087
3088 BT_DBG("");
3089
Szymon Jancf950a30e2013-01-18 12:48:07 +01003090 memset(&rp, 0, sizeof(rp));
3091 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3092 rp.addr.type = cp->addr.type;
3093
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003094 if (!bdaddr_type_is_valid(cp->addr.type))
3095 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3096 MGMT_STATUS_INVALID_PARAMS,
3097 &rp, sizeof(rp));
3098
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003099 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3100 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3101 MGMT_STATUS_INVALID_PARAMS,
3102 &rp, sizeof(rp));
3103
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003104 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003105
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003106 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003107 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3108 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003109 goto unlock;
3110 }
3111
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003112 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003113 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003114
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003115 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003116 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3117 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003118 } else {
3119 u8 addr_type;
3120
3121 /* Convert from L2CAP channel address type to HCI address type
3122 */
3123 if (cp->addr.type == BDADDR_LE_PUBLIC)
3124 addr_type = ADDR_LE_DEV_PUBLIC;
3125 else
3126 addr_type = ADDR_LE_DEV_RANDOM;
3127
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003128 /* When pairing a new device, it is expected to remember
3129 * this device for future connections. Adding the connection
3130 * parameter information ahead of time allows tracking
3131 * of the slave preferred values and will speed up any
3132 * further connection establishment.
3133 *
3134 * If connection parameters already exist, then they
3135 * will be kept and this function does nothing.
3136 */
3137 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3138
Johan Hedbergcdd62752014-07-07 15:02:28 +03003139 /* Request a connection with master = true role */
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003140 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedbergcdd62752014-07-07 15:02:28 +03003141 sec_level, HCI_LE_CONN_TIMEOUT, true);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003142 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003143
Ville Tervo30e76272011-02-22 16:10:53 -03003144 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003145 int status;
3146
3147 if (PTR_ERR(conn) == -EBUSY)
3148 status = MGMT_STATUS_BUSY;
3149 else
3150 status = MGMT_STATUS_CONNECT_FAILED;
3151
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003152 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003153 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003154 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003155 goto unlock;
3156 }
3157
3158 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003159 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003160 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003161 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003162 goto unlock;
3163 }
3164
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003165 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166 if (!cmd) {
3167 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003168 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003169 goto unlock;
3170 }
3171
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003172 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003173 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003174 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003175 conn->security_cfm_cb = pairing_complete_cb;
3176 conn->disconn_cfm_cb = pairing_complete_cb;
3177 } else {
3178 conn->connect_cfm_cb = le_pairing_complete_cb;
3179 conn->security_cfm_cb = le_pairing_complete_cb;
3180 conn->disconn_cfm_cb = le_pairing_complete_cb;
3181 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003182
Johan Hedberge9a416b2011-02-19 12:05:56 -03003183 conn->io_capability = cp->io_cap;
3184 cmd->user_data = conn;
3185
3186 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003187 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003188 pairing_complete(cmd, 0);
3189
3190 err = 0;
3191
3192unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003193 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003194 return err;
3195}
3196
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003197static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3198 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003199{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003200 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003201 struct pending_cmd *cmd;
3202 struct hci_conn *conn;
3203 int err;
3204
3205 BT_DBG("");
3206
Johan Hedberg28424702012-02-02 04:02:29 +02003207 hci_dev_lock(hdev);
3208
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003209 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003210 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003211 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003212 goto unlock;
3213 }
3214
Johan Hedberg28424702012-02-02 04:02:29 +02003215 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3216 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003217 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003218 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003219 goto unlock;
3220 }
3221
3222 conn = cmd->user_data;
3223
3224 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003225 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003226 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003227 goto unlock;
3228 }
3229
3230 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3231
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003232 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003233 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003234unlock:
3235 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003236 return err;
3237}
3238
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003239static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003240 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003241 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003242{
Johan Hedberga5c29682011-02-19 12:05:57 -03003243 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003244 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003245 int err;
3246
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003247 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003248
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003249 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003250 err = cmd_complete(sk, hdev->id, mgmt_op,
3251 MGMT_STATUS_NOT_POWERED, addr,
3252 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003253 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003254 }
3255
Johan Hedberg1707c602013-03-15 17:07:15 -05003256 if (addr->type == BDADDR_BREDR)
3257 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003258 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003259 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003260
Johan Hedberg272d90d2012-02-09 15:26:12 +02003261 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003262 err = cmd_complete(sk, hdev->id, mgmt_op,
3263 MGMT_STATUS_NOT_CONNECTED, addr,
3264 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003265 goto done;
3266 }
3267
Johan Hedberg1707c602013-03-15 17:07:15 -05003268 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003269 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003270 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003271 err = cmd_complete(sk, hdev->id, mgmt_op,
3272 MGMT_STATUS_SUCCESS, addr,
3273 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003274 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003275 err = cmd_complete(sk, hdev->id, mgmt_op,
3276 MGMT_STATUS_FAILED, addr,
3277 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003278
Brian Gix47c15e22011-11-16 13:53:14 -08003279 goto done;
3280 }
3281
Johan Hedberg1707c602013-03-15 17:07:15 -05003282 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003283 if (!cmd) {
3284 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003285 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003286 }
3287
Brian Gix0df4c182011-11-16 13:53:13 -08003288 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003289 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3290 struct hci_cp_user_passkey_reply cp;
3291
Johan Hedberg1707c602013-03-15 17:07:15 -05003292 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003293 cp.passkey = passkey;
3294 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3295 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003296 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3297 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003298
Johan Hedberga664b5b2011-02-19 12:06:02 -03003299 if (err < 0)
3300 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003301
Brian Gix0df4c182011-11-16 13:53:13 -08003302done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003303 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003304 return err;
3305}
3306
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303307static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3308 void *data, u16 len)
3309{
3310 struct mgmt_cp_pin_code_neg_reply *cp = data;
3311
3312 BT_DBG("");
3313
Johan Hedberg1707c602013-03-15 17:07:15 -05003314 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303315 MGMT_OP_PIN_CODE_NEG_REPLY,
3316 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3317}
3318
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003319static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3320 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003321{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003322 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003323
3324 BT_DBG("");
3325
3326 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003327 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003328 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003329
Johan Hedberg1707c602013-03-15 17:07:15 -05003330 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003331 MGMT_OP_USER_CONFIRM_REPLY,
3332 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003333}
3334
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003335static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003336 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003337{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003338 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003339
3340 BT_DBG("");
3341
Johan Hedberg1707c602013-03-15 17:07:15 -05003342 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003343 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3344 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003345}
3346
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003347static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3348 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003349{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003350 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003351
3352 BT_DBG("");
3353
Johan Hedberg1707c602013-03-15 17:07:15 -05003354 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003355 MGMT_OP_USER_PASSKEY_REPLY,
3356 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003357}
3358
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003359static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003360 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003361{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003362 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003363
3364 BT_DBG("");
3365
Johan Hedberg1707c602013-03-15 17:07:15 -05003366 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003367 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3368 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003369}
3370
Johan Hedberg13928972013-03-15 17:07:00 -05003371static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003372{
Johan Hedberg13928972013-03-15 17:07:00 -05003373 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003374 struct hci_cp_write_local_name cp;
3375
Johan Hedberg13928972013-03-15 17:07:00 -05003376 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003377
Johan Hedberg890ea892013-03-15 17:06:52 -05003378 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003379}
3380
Johan Hedberg13928972013-03-15 17:07:00 -05003381static void set_name_complete(struct hci_dev *hdev, u8 status)
3382{
3383 struct mgmt_cp_set_local_name *cp;
3384 struct pending_cmd *cmd;
3385
3386 BT_DBG("status 0x%02x", status);
3387
3388 hci_dev_lock(hdev);
3389
3390 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3391 if (!cmd)
3392 goto unlock;
3393
3394 cp = cmd->param;
3395
3396 if (status)
3397 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3398 mgmt_status(status));
3399 else
3400 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3401 cp, sizeof(*cp));
3402
3403 mgmt_pending_remove(cmd);
3404
3405unlock:
3406 hci_dev_unlock(hdev);
3407}
3408
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003409static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003410 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003411{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003412 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003413 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003414 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003415 int err;
3416
3417 BT_DBG("");
3418
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003419 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003420
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003421 /* If the old values are the same as the new ones just return a
3422 * direct command complete event.
3423 */
3424 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3425 !memcmp(hdev->short_name, cp->short_name,
3426 sizeof(hdev->short_name))) {
3427 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3428 data, len);
3429 goto failed;
3430 }
3431
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003432 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003433
Johan Hedbergb5235a62012-02-21 14:32:24 +02003434 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003435 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003436
3437 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003438 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003439 if (err < 0)
3440 goto failed;
3441
3442 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003443 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003444
Johan Hedbergb5235a62012-02-21 14:32:24 +02003445 goto failed;
3446 }
3447
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003448 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003449 if (!cmd) {
3450 err = -ENOMEM;
3451 goto failed;
3452 }
3453
Johan Hedberg13928972013-03-15 17:07:00 -05003454 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3455
Johan Hedberg890ea892013-03-15 17:06:52 -05003456 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003457
3458 if (lmp_bredr_capable(hdev)) {
3459 update_name(&req);
3460 update_eir(&req);
3461 }
3462
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003463 /* The name is stored in the scan response data and so
3464 * no need to udpate the advertising data here.
3465 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003466 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003467 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003468
Johan Hedberg13928972013-03-15 17:07:00 -05003469 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003470 if (err < 0)
3471 mgmt_pending_remove(cmd);
3472
3473failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003474 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003475 return err;
3476}
3477
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003478static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003479 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003480{
Szymon Jancc35938b2011-03-22 13:12:21 +01003481 struct pending_cmd *cmd;
3482 int err;
3483
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003484 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003485
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003486 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003487
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003488 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003489 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003490 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003491 goto unlock;
3492 }
3493
Andre Guedes9a1a1992012-07-24 15:03:48 -03003494 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003495 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003496 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003497 goto unlock;
3498 }
3499
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003500 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003501 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003503 goto unlock;
3504 }
3505
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003506 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003507 if (!cmd) {
3508 err = -ENOMEM;
3509 goto unlock;
3510 }
3511
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003512 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3513 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3514 0, NULL);
3515 else
3516 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3517
Szymon Jancc35938b2011-03-22 13:12:21 +01003518 if (err < 0)
3519 mgmt_pending_remove(cmd);
3520
3521unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003522 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003523 return err;
3524}
3525
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003526static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003527 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003528{
Szymon Janc2763eda2011-03-22 13:12:22 +01003529 int err;
3530
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003531 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003532
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003533 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003534
Marcel Holtmannec109112014-01-10 02:07:30 -08003535 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3536 struct mgmt_cp_add_remote_oob_data *cp = data;
3537 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003538
Marcel Holtmannec109112014-01-10 02:07:30 -08003539 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3540 cp->hash, cp->randomizer);
3541 if (err < 0)
3542 status = MGMT_STATUS_FAILED;
3543 else
3544 status = MGMT_STATUS_SUCCESS;
3545
3546 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3547 status, &cp->addr, sizeof(cp->addr));
3548 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3549 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3550 u8 status;
3551
3552 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3553 cp->hash192,
3554 cp->randomizer192,
3555 cp->hash256,
3556 cp->randomizer256);
3557 if (err < 0)
3558 status = MGMT_STATUS_FAILED;
3559 else
3560 status = MGMT_STATUS_SUCCESS;
3561
3562 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3563 status, &cp->addr, sizeof(cp->addr));
3564 } else {
3565 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3566 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3567 MGMT_STATUS_INVALID_PARAMS);
3568 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003569
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003570 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003571 return err;
3572}
3573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003574static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003575 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003576{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003577 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003578 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003579 int err;
3580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003581 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003582
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003583 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003584
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003585 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003586 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003587 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003588 else
Szymon Janca6785be2012-12-13 15:11:21 +01003589 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003591 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003592 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003593
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003594 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003595 return err;
3596}
3597
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003598static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3599{
3600 struct pending_cmd *cmd;
3601 u8 type;
3602 int err;
3603
3604 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3605
3606 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3607 if (!cmd)
3608 return -ENOENT;
3609
3610 type = hdev->discovery.type;
3611
3612 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3613 &type, sizeof(type));
3614 mgmt_pending_remove(cmd);
3615
3616 return err;
3617}
3618
Andre Guedes7c307722013-04-30 15:29:28 -03003619static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3620{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003621 unsigned long timeout = 0;
3622
Andre Guedes7c307722013-04-30 15:29:28 -03003623 BT_DBG("status %d", status);
3624
3625 if (status) {
3626 hci_dev_lock(hdev);
3627 mgmt_start_discovery_failed(hdev, status);
3628 hci_dev_unlock(hdev);
3629 return;
3630 }
3631
3632 hci_dev_lock(hdev);
3633 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3634 hci_dev_unlock(hdev);
3635
3636 switch (hdev->discovery.type) {
3637 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003638 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003639 break;
3640
3641 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003642 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003643 break;
3644
3645 case DISCOV_TYPE_BREDR:
3646 break;
3647
3648 default:
3649 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3650 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003651
3652 if (!timeout)
3653 return;
3654
3655 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003656}
3657
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003658static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003659 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003660{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003661 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003662 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003663 struct hci_cp_le_set_scan_param param_cp;
3664 struct hci_cp_le_set_scan_enable enable_cp;
3665 struct hci_cp_inquiry inq_cp;
3666 struct hci_request req;
3667 /* General inquiry access code (GIAC) */
3668 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003669 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003670 int err;
3671
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003672 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003673
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003674 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003675
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003676 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003677 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003678 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003679 goto failed;
3680 }
3681
Andre Guedes642be6c2012-03-21 00:03:37 -03003682 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3683 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3684 MGMT_STATUS_BUSY);
3685 goto failed;
3686 }
3687
Johan Hedbergff9ef572012-01-04 14:23:45 +02003688 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003689 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003690 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003691 goto failed;
3692 }
3693
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003694 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003695 if (!cmd) {
3696 err = -ENOMEM;
3697 goto failed;
3698 }
3699
Andre Guedes4aab14e2012-02-17 20:39:36 -03003700 hdev->discovery.type = cp->type;
3701
Andre Guedes7c307722013-04-30 15:29:28 -03003702 hci_req_init(&req, hdev);
3703
Andre Guedes4aab14e2012-02-17 20:39:36 -03003704 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003705 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003706 status = mgmt_bredr_support(hdev);
3707 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003708 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003709 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003710 mgmt_pending_remove(cmd);
3711 goto failed;
3712 }
3713
Andre Guedes7c307722013-04-30 15:29:28 -03003714 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3715 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3716 MGMT_STATUS_BUSY);
3717 mgmt_pending_remove(cmd);
3718 goto failed;
3719 }
3720
3721 hci_inquiry_cache_flush(hdev);
3722
3723 memset(&inq_cp, 0, sizeof(inq_cp));
3724 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003725 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003726 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003727 break;
3728
3729 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003730 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003731 status = mgmt_le_support(hdev);
3732 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003733 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003734 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003735 mgmt_pending_remove(cmd);
3736 goto failed;
3737 }
3738
Andre Guedes7c307722013-04-30 15:29:28 -03003739 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003740 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003741 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3742 MGMT_STATUS_NOT_SUPPORTED);
3743 mgmt_pending_remove(cmd);
3744 goto failed;
3745 }
3746
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003747 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3748 /* Don't let discovery abort an outgoing
3749 * connection attempt that's using directed
3750 * advertising.
3751 */
3752 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3753 BT_CONNECT)) {
3754 err = cmd_status(sk, hdev->id,
3755 MGMT_OP_START_DISCOVERY,
3756 MGMT_STATUS_REJECTED);
3757 mgmt_pending_remove(cmd);
3758 goto failed;
3759 }
3760
3761 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003762 }
3763
Andre Guedesc54c3862014-02-26 20:21:50 -03003764 /* If controller is scanning, it means the background scanning
3765 * is running. Thus, we should temporarily stop it in order to
3766 * set the discovery scanning parameters.
3767 */
3768 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3769 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003770
3771 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003772
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003773 /* All active scans will be done with either a resolvable
3774 * private address (when privacy feature has been enabled)
3775 * or unresolvable private address.
3776 */
3777 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003778 if (err < 0) {
3779 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3780 MGMT_STATUS_FAILED);
3781 mgmt_pending_remove(cmd);
3782 goto failed;
3783 }
3784
Andre Guedes7c307722013-04-30 15:29:28 -03003785 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003786 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3787 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003788 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003789 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3790 &param_cp);
3791
3792 memset(&enable_cp, 0, sizeof(enable_cp));
3793 enable_cp.enable = LE_SCAN_ENABLE;
3794 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3795 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3796 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003797 break;
3798
Andre Guedesf39799f2012-02-17 20:39:35 -03003799 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003800 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3801 MGMT_STATUS_INVALID_PARAMS);
3802 mgmt_pending_remove(cmd);
3803 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003804 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003805
Andre Guedes7c307722013-04-30 15:29:28 -03003806 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003807 if (err < 0)
3808 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003809 else
3810 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003811
3812failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003813 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003814 return err;
3815}
3816
Andre Guedes1183fdc2013-04-30 15:29:35 -03003817static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3818{
3819 struct pending_cmd *cmd;
3820 int err;
3821
3822 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3823 if (!cmd)
3824 return -ENOENT;
3825
3826 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3827 &hdev->discovery.type, sizeof(hdev->discovery.type));
3828 mgmt_pending_remove(cmd);
3829
3830 return err;
3831}
3832
Andre Guedes0e05bba2013-04-30 15:29:33 -03003833static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3834{
3835 BT_DBG("status %d", status);
3836
3837 hci_dev_lock(hdev);
3838
3839 if (status) {
3840 mgmt_stop_discovery_failed(hdev, status);
3841 goto unlock;
3842 }
3843
3844 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3845
3846unlock:
3847 hci_dev_unlock(hdev);
3848}
3849
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003850static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003851 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003852{
Johan Hedbergd9306502012-02-20 23:25:18 +02003853 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003854 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003855 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003856 int err;
3857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003858 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003859
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003860 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003861
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003862 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003863 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003864 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3865 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003866 goto unlock;
3867 }
3868
3869 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003870 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003871 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3872 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003873 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003874 }
3875
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003876 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003877 if (!cmd) {
3878 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003879 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003880 }
3881
Andre Guedes0e05bba2013-04-30 15:29:33 -03003882 hci_req_init(&req, hdev);
3883
Johan Hedberg21a60d32014-06-10 14:05:58 +03003884 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003885
Johan Hedberg21a60d32014-06-10 14:05:58 +03003886 err = hci_req_run(&req, stop_discovery_complete);
3887 if (!err) {
3888 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003889 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003890 }
3891
Johan Hedberg21a60d32014-06-10 14:05:58 +03003892 mgmt_pending_remove(cmd);
3893
3894 /* If no HCI commands were sent we're done */
3895 if (err == -ENODATA) {
3896 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3897 &mgmt_cp->type, sizeof(mgmt_cp->type));
3898 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3899 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003900
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003901unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003902 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003903 return err;
3904}
3905
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003906static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003907 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003908{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003909 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003910 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003911 int err;
3912
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003913 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003914
Johan Hedberg561aafb2012-01-04 13:31:59 +02003915 hci_dev_lock(hdev);
3916
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003917 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003918 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3919 MGMT_STATUS_FAILED, &cp->addr,
3920 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003921 goto failed;
3922 }
3923
Johan Hedberga198e7b2012-02-17 14:27:06 +02003924 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003925 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003926 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3927 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3928 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003929 goto failed;
3930 }
3931
3932 if (cp->name_known) {
3933 e->name_state = NAME_KNOWN;
3934 list_del(&e->list);
3935 } else {
3936 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003937 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003938 }
3939
Johan Hedberge3846622013-01-09 15:29:33 +02003940 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3941 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003942
3943failed:
3944 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003945 return err;
3946}
3947
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003948static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003949 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003950{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003951 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003952 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003953 int err;
3954
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003955 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003956
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003957 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003958 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3959 MGMT_STATUS_INVALID_PARAMS,
3960 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003961
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003962 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003963
Johan Hedbergdcc36c12014-07-09 12:59:13 +03003964 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
3965 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003966 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003967 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003968 goto done;
3969 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003970
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003971 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3972 sk);
3973 status = MGMT_STATUS_SUCCESS;
3974
3975done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003976 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003977 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003978
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003979 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003980
3981 return err;
3982}
3983
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003984static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003985 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003986{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003987 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003988 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003989 int err;
3990
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003991 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003992
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003993 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003994 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3995 MGMT_STATUS_INVALID_PARAMS,
3996 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003997
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003998 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003999
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004000 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4001 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004002 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004003 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004004 goto done;
4005 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004006
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004007 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4008 sk);
4009 status = MGMT_STATUS_SUCCESS;
4010
4011done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004012 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004013 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004014
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004015 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004016
4017 return err;
4018}
4019
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004020static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4021 u16 len)
4022{
4023 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004024 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004025 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004026 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004027
4028 BT_DBG("%s", hdev->name);
4029
Szymon Jancc72d4b82012-03-16 16:02:57 +01004030 source = __le16_to_cpu(cp->source);
4031
4032 if (source > 0x0002)
4033 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4034 MGMT_STATUS_INVALID_PARAMS);
4035
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004036 hci_dev_lock(hdev);
4037
Szymon Jancc72d4b82012-03-16 16:02:57 +01004038 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004039 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4040 hdev->devid_product = __le16_to_cpu(cp->product);
4041 hdev->devid_version = __le16_to_cpu(cp->version);
4042
4043 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4044
Johan Hedberg890ea892013-03-15 17:06:52 -05004045 hci_req_init(&req, hdev);
4046 update_eir(&req);
4047 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004048
4049 hci_dev_unlock(hdev);
4050
4051 return err;
4052}
4053
Johan Hedberg4375f102013-09-25 13:26:10 +03004054static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4055{
4056 struct cmd_lookup match = { NULL, hdev };
4057
4058 if (status) {
4059 u8 mgmt_err = mgmt_status(status);
4060
4061 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4062 cmd_status_rsp, &mgmt_err);
4063 return;
4064 }
4065
Johan Hedbergc93bd152014-07-08 15:07:48 +03004066 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4067 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4068 else
4069 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4070
Johan Hedberg4375f102013-09-25 13:26:10 +03004071 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4072 &match);
4073
4074 new_settings(hdev, match.sk);
4075
4076 if (match.sk)
4077 sock_put(match.sk);
4078}
4079
Marcel Holtmann21b51872013-10-10 09:47:53 -07004080static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4081 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004082{
4083 struct mgmt_mode *cp = data;
4084 struct pending_cmd *cmd;
4085 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004086 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004087 int err;
4088
4089 BT_DBG("request for %s", hdev->name);
4090
Johan Hedberge6fe7982013-10-02 15:45:22 +03004091 status = mgmt_le_support(hdev);
4092 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004093 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004094 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004095
4096 if (cp->val != 0x00 && cp->val != 0x01)
4097 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4098 MGMT_STATUS_INVALID_PARAMS);
4099
4100 hci_dev_lock(hdev);
4101
4102 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004103 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004104
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004105 /* The following conditions are ones which mean that we should
4106 * not do any HCI communication but directly send a mgmt
4107 * response to user space (after toggling the flag if
4108 * necessary).
4109 */
4110 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004111 hci_conn_num(hdev, LE_LINK) > 0 ||
4112 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4113 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004114 bool changed = false;
4115
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004116 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4117 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004118 changed = true;
4119 }
4120
4121 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4122 if (err < 0)
4123 goto unlock;
4124
4125 if (changed)
4126 err = new_settings(hdev, sk);
4127
4128 goto unlock;
4129 }
4130
4131 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4132 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4133 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4134 MGMT_STATUS_BUSY);
4135 goto unlock;
4136 }
4137
4138 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4139 if (!cmd) {
4140 err = -ENOMEM;
4141 goto unlock;
4142 }
4143
4144 hci_req_init(&req, hdev);
4145
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004146 if (val)
4147 enable_advertising(&req);
4148 else
4149 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004150
4151 err = hci_req_run(&req, set_advertising_complete);
4152 if (err < 0)
4153 mgmt_pending_remove(cmd);
4154
4155unlock:
4156 hci_dev_unlock(hdev);
4157 return err;
4158}
4159
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004160static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4161 void *data, u16 len)
4162{
4163 struct mgmt_cp_set_static_address *cp = data;
4164 int err;
4165
4166 BT_DBG("%s", hdev->name);
4167
Marcel Holtmann62af4442013-10-02 22:10:32 -07004168 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004169 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004170 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004171
4172 if (hdev_is_powered(hdev))
4173 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4174 MGMT_STATUS_REJECTED);
4175
4176 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4177 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4178 return cmd_status(sk, hdev->id,
4179 MGMT_OP_SET_STATIC_ADDRESS,
4180 MGMT_STATUS_INVALID_PARAMS);
4181
4182 /* Two most significant bits shall be set */
4183 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4184 return cmd_status(sk, hdev->id,
4185 MGMT_OP_SET_STATIC_ADDRESS,
4186 MGMT_STATUS_INVALID_PARAMS);
4187 }
4188
4189 hci_dev_lock(hdev);
4190
4191 bacpy(&hdev->static_addr, &cp->bdaddr);
4192
4193 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4194
4195 hci_dev_unlock(hdev);
4196
4197 return err;
4198}
4199
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004200static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4201 void *data, u16 len)
4202{
4203 struct mgmt_cp_set_scan_params *cp = data;
4204 __u16 interval, window;
4205 int err;
4206
4207 BT_DBG("%s", hdev->name);
4208
4209 if (!lmp_le_capable(hdev))
4210 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4211 MGMT_STATUS_NOT_SUPPORTED);
4212
4213 interval = __le16_to_cpu(cp->interval);
4214
4215 if (interval < 0x0004 || interval > 0x4000)
4216 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4217 MGMT_STATUS_INVALID_PARAMS);
4218
4219 window = __le16_to_cpu(cp->window);
4220
4221 if (window < 0x0004 || window > 0x4000)
4222 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4223 MGMT_STATUS_INVALID_PARAMS);
4224
Marcel Holtmann899e1072013-10-14 09:55:32 -07004225 if (window > interval)
4226 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4227 MGMT_STATUS_INVALID_PARAMS);
4228
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004229 hci_dev_lock(hdev);
4230
4231 hdev->le_scan_interval = interval;
4232 hdev->le_scan_window = window;
4233
4234 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4235
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004236 /* If background scan is running, restart it so new parameters are
4237 * loaded.
4238 */
4239 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4240 hdev->discovery.state == DISCOVERY_STOPPED) {
4241 struct hci_request req;
4242
4243 hci_req_init(&req, hdev);
4244
4245 hci_req_add_le_scan_disable(&req);
4246 hci_req_add_le_passive_scan(&req);
4247
4248 hci_req_run(&req, NULL);
4249 }
4250
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004251 hci_dev_unlock(hdev);
4252
4253 return err;
4254}
4255
Johan Hedberg33e38b32013-03-15 17:07:05 -05004256static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4257{
4258 struct pending_cmd *cmd;
4259
4260 BT_DBG("status 0x%02x", status);
4261
4262 hci_dev_lock(hdev);
4263
4264 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4265 if (!cmd)
4266 goto unlock;
4267
4268 if (status) {
4269 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4270 mgmt_status(status));
4271 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004272 struct mgmt_mode *cp = cmd->param;
4273
4274 if (cp->val)
4275 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4276 else
4277 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4278
Johan Hedberg33e38b32013-03-15 17:07:05 -05004279 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4280 new_settings(hdev, cmd->sk);
4281 }
4282
4283 mgmt_pending_remove(cmd);
4284
4285unlock:
4286 hci_dev_unlock(hdev);
4287}
4288
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004289static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004290 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004291{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004292 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004293 struct pending_cmd *cmd;
4294 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004295 int err;
4296
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004297 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004298
Johan Hedberg56f87902013-10-02 13:43:13 +03004299 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4300 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004301 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4302 MGMT_STATUS_NOT_SUPPORTED);
4303
Johan Hedberga7e80f22013-01-09 16:05:19 +02004304 if (cp->val != 0x00 && cp->val != 0x01)
4305 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4306 MGMT_STATUS_INVALID_PARAMS);
4307
Johan Hedberg5400c042012-02-21 16:40:33 +02004308 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004309 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004310 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004311
4312 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004313 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004314 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004315
4316 hci_dev_lock(hdev);
4317
Johan Hedberg05cbf292013-03-15 17:07:07 -05004318 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4319 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4320 MGMT_STATUS_BUSY);
4321 goto unlock;
4322 }
4323
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004324 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4325 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4326 hdev);
4327 goto unlock;
4328 }
4329
Johan Hedberg33e38b32013-03-15 17:07:05 -05004330 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4331 data, len);
4332 if (!cmd) {
4333 err = -ENOMEM;
4334 goto unlock;
4335 }
4336
4337 hci_req_init(&req, hdev);
4338
Johan Hedberg406d7802013-03-15 17:07:09 -05004339 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004340
4341 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004342 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004343 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004344 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004345 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004346 }
4347
Johan Hedberg33e38b32013-03-15 17:07:05 -05004348unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004349 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004350
Antti Julkuf6422ec2011-06-22 13:11:56 +03004351 return err;
4352}
4353
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004354static void set_bredr_scan(struct hci_request *req)
4355{
4356 struct hci_dev *hdev = req->hdev;
4357 u8 scan = 0;
4358
4359 /* Ensure that fast connectable is disabled. This function will
4360 * not do anything if the page scan parameters are already what
4361 * they should be.
4362 */
4363 write_fast_connectable(req, false);
4364
Johan Hedberg6cebb9e72014-07-09 12:59:18 +03004365 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
4366 !list_empty(&hdev->whitelist))
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004367 scan |= SCAN_PAGE;
4368 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4369 scan |= SCAN_INQUIRY;
4370
4371 if (scan)
4372 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4373}
4374
Johan Hedberg0663ca22013-10-02 13:43:14 +03004375static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4376{
4377 struct pending_cmd *cmd;
4378
4379 BT_DBG("status 0x%02x", status);
4380
4381 hci_dev_lock(hdev);
4382
4383 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4384 if (!cmd)
4385 goto unlock;
4386
4387 if (status) {
4388 u8 mgmt_err = mgmt_status(status);
4389
4390 /* We need to restore the flag if related HCI commands
4391 * failed.
4392 */
4393 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4394
4395 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4396 } else {
4397 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4398 new_settings(hdev, cmd->sk);
4399 }
4400
4401 mgmt_pending_remove(cmd);
4402
4403unlock:
4404 hci_dev_unlock(hdev);
4405}
4406
4407static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4408{
4409 struct mgmt_mode *cp = data;
4410 struct pending_cmd *cmd;
4411 struct hci_request req;
4412 int err;
4413
4414 BT_DBG("request for %s", hdev->name);
4415
4416 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4417 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4418 MGMT_STATUS_NOT_SUPPORTED);
4419
4420 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4421 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4422 MGMT_STATUS_REJECTED);
4423
4424 if (cp->val != 0x00 && cp->val != 0x01)
4425 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4426 MGMT_STATUS_INVALID_PARAMS);
4427
4428 hci_dev_lock(hdev);
4429
4430 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4431 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4432 goto unlock;
4433 }
4434
4435 if (!hdev_is_powered(hdev)) {
4436 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004437 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4438 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4439 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4440 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4441 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4442 }
4443
4444 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4445
4446 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4447 if (err < 0)
4448 goto unlock;
4449
4450 err = new_settings(hdev, sk);
4451 goto unlock;
4452 }
4453
4454 /* Reject disabling when powered on */
4455 if (!cp->val) {
4456 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4457 MGMT_STATUS_REJECTED);
4458 goto unlock;
4459 }
4460
4461 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4462 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4463 MGMT_STATUS_BUSY);
4464 goto unlock;
4465 }
4466
4467 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4468 if (!cmd) {
4469 err = -ENOMEM;
4470 goto unlock;
4471 }
4472
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004473 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004474 * generates the correct flags.
4475 */
4476 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4477
4478 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004479
Johan Hedberg6cebb9e72014-07-09 12:59:18 +03004480 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
4481 !list_empty(&hdev->whitelist))
Johan Hedbergaa8af462013-10-14 21:15:26 +03004482 set_bredr_scan(&req);
4483
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004484 /* Since only the advertising data flags will change, there
4485 * is no need to update the scan response data.
4486 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004487 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004488
Johan Hedberg0663ca22013-10-02 13:43:14 +03004489 err = hci_req_run(&req, set_bredr_complete);
4490 if (err < 0)
4491 mgmt_pending_remove(cmd);
4492
4493unlock:
4494 hci_dev_unlock(hdev);
4495 return err;
4496}
4497
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004498static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4499 void *data, u16 len)
4500{
4501 struct mgmt_mode *cp = data;
4502 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004503 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004504 int err;
4505
4506 BT_DBG("request for %s", hdev->name);
4507
4508 status = mgmt_bredr_support(hdev);
4509 if (status)
4510 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4511 status);
4512
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004513 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004514 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004515 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4516 MGMT_STATUS_NOT_SUPPORTED);
4517
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004518 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004519 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4520 MGMT_STATUS_INVALID_PARAMS);
4521
4522 hci_dev_lock(hdev);
4523
4524 if (!hdev_is_powered(hdev)) {
4525 bool changed;
4526
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004527 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004528 changed = !test_and_set_bit(HCI_SC_ENABLED,
4529 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004530 if (cp->val == 0x02)
4531 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4532 else
4533 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4534 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004535 changed = test_and_clear_bit(HCI_SC_ENABLED,
4536 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004537 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4538 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004539
4540 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4541 if (err < 0)
4542 goto failed;
4543
4544 if (changed)
4545 err = new_settings(hdev, sk);
4546
4547 goto failed;
4548 }
4549
4550 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4551 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4552 MGMT_STATUS_BUSY);
4553 goto failed;
4554 }
4555
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004556 val = !!cp->val;
4557
4558 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4559 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004560 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4561 goto failed;
4562 }
4563
4564 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4565 if (!cmd) {
4566 err = -ENOMEM;
4567 goto failed;
4568 }
4569
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004570 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004571 if (err < 0) {
4572 mgmt_pending_remove(cmd);
4573 goto failed;
4574 }
4575
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004576 if (cp->val == 0x02)
4577 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4578 else
4579 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4580
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004581failed:
4582 hci_dev_unlock(hdev);
4583 return err;
4584}
4585
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004586static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4587 void *data, u16 len)
4588{
4589 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004590 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004591 int err;
4592
4593 BT_DBG("request for %s", hdev->name);
4594
Johan Hedbergb97109792014-06-24 14:00:28 +03004595 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004596 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4597 MGMT_STATUS_INVALID_PARAMS);
4598
4599 hci_dev_lock(hdev);
4600
4601 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004602 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4603 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004604 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004605 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4606 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004607
Johan Hedbergb97109792014-06-24 14:00:28 +03004608 if (cp->val == 0x02)
4609 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4610 &hdev->dev_flags);
4611 else
4612 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4613 &hdev->dev_flags);
4614
4615 if (hdev_is_powered(hdev) && use_changed &&
4616 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4617 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4618 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4619 sizeof(mode), &mode);
4620 }
4621
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004622 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4623 if (err < 0)
4624 goto unlock;
4625
4626 if (changed)
4627 err = new_settings(hdev, sk);
4628
4629unlock:
4630 hci_dev_unlock(hdev);
4631 return err;
4632}
4633
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004634static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4635 u16 len)
4636{
4637 struct mgmt_cp_set_privacy *cp = cp_data;
4638 bool changed;
4639 int err;
4640
4641 BT_DBG("request for %s", hdev->name);
4642
4643 if (!lmp_le_capable(hdev))
4644 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4645 MGMT_STATUS_NOT_SUPPORTED);
4646
4647 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4648 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4649 MGMT_STATUS_INVALID_PARAMS);
4650
4651 if (hdev_is_powered(hdev))
4652 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4653 MGMT_STATUS_REJECTED);
4654
4655 hci_dev_lock(hdev);
4656
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004657 /* If user space supports this command it is also expected to
4658 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4659 */
4660 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4661
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004662 if (cp->privacy) {
4663 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4664 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4665 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4666 } else {
4667 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4668 memset(hdev->irk, 0, sizeof(hdev->irk));
4669 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4670 }
4671
4672 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4673 if (err < 0)
4674 goto unlock;
4675
4676 if (changed)
4677 err = new_settings(hdev, sk);
4678
4679unlock:
4680 hci_dev_unlock(hdev);
4681 return err;
4682}
4683
Johan Hedberg41edf162014-02-18 10:19:35 +02004684static bool irk_is_valid(struct mgmt_irk_info *irk)
4685{
4686 switch (irk->addr.type) {
4687 case BDADDR_LE_PUBLIC:
4688 return true;
4689
4690 case BDADDR_LE_RANDOM:
4691 /* Two most significant bits shall be set */
4692 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4693 return false;
4694 return true;
4695 }
4696
4697 return false;
4698}
4699
4700static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4701 u16 len)
4702{
4703 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004704 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4705 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004706 u16 irk_count, expected_len;
4707 int i, err;
4708
4709 BT_DBG("request for %s", hdev->name);
4710
4711 if (!lmp_le_capable(hdev))
4712 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4713 MGMT_STATUS_NOT_SUPPORTED);
4714
4715 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004716 if (irk_count > max_irk_count) {
4717 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4718 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4719 MGMT_STATUS_INVALID_PARAMS);
4720 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004721
4722 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4723 if (expected_len != len) {
4724 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004725 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004726 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4727 MGMT_STATUS_INVALID_PARAMS);
4728 }
4729
4730 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4731
4732 for (i = 0; i < irk_count; i++) {
4733 struct mgmt_irk_info *key = &cp->irks[i];
4734
4735 if (!irk_is_valid(key))
4736 return cmd_status(sk, hdev->id,
4737 MGMT_OP_LOAD_IRKS,
4738 MGMT_STATUS_INVALID_PARAMS);
4739 }
4740
4741 hci_dev_lock(hdev);
4742
4743 hci_smp_irks_clear(hdev);
4744
4745 for (i = 0; i < irk_count; i++) {
4746 struct mgmt_irk_info *irk = &cp->irks[i];
4747 u8 addr_type;
4748
4749 if (irk->addr.type == BDADDR_LE_PUBLIC)
4750 addr_type = ADDR_LE_DEV_PUBLIC;
4751 else
4752 addr_type = ADDR_LE_DEV_RANDOM;
4753
4754 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4755 BDADDR_ANY);
4756 }
4757
4758 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4759
4760 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4761
4762 hci_dev_unlock(hdev);
4763
4764 return err;
4765}
4766
Johan Hedberg3f706b72013-01-20 14:27:16 +02004767static bool ltk_is_valid(struct mgmt_ltk_info *key)
4768{
4769 if (key->master != 0x00 && key->master != 0x01)
4770 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004771
4772 switch (key->addr.type) {
4773 case BDADDR_LE_PUBLIC:
4774 return true;
4775
4776 case BDADDR_LE_RANDOM:
4777 /* Two most significant bits shall be set */
4778 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4779 return false;
4780 return true;
4781 }
4782
4783 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004784}
4785
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004786static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004787 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004788{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004789 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004790 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4791 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004792 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004793 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004794
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004795 BT_DBG("request for %s", hdev->name);
4796
4797 if (!lmp_le_capable(hdev))
4798 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4799 MGMT_STATUS_NOT_SUPPORTED);
4800
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004801 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004802 if (key_count > max_key_count) {
4803 BT_ERR("load_ltks: too big key_count value %u", key_count);
4804 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4805 MGMT_STATUS_INVALID_PARAMS);
4806 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004807
4808 expected_len = sizeof(*cp) + key_count *
4809 sizeof(struct mgmt_ltk_info);
4810 if (expected_len != len) {
4811 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004812 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004813 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004814 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004815 }
4816
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004817 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004818
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004819 for (i = 0; i < key_count; i++) {
4820 struct mgmt_ltk_info *key = &cp->keys[i];
4821
Johan Hedberg3f706b72013-01-20 14:27:16 +02004822 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004823 return cmd_status(sk, hdev->id,
4824 MGMT_OP_LOAD_LONG_TERM_KEYS,
4825 MGMT_STATUS_INVALID_PARAMS);
4826 }
4827
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004828 hci_dev_lock(hdev);
4829
4830 hci_smp_ltks_clear(hdev);
4831
4832 for (i = 0; i < key_count; i++) {
4833 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004834 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004835
4836 if (key->addr.type == BDADDR_LE_PUBLIC)
4837 addr_type = ADDR_LE_DEV_PUBLIC;
4838 else
4839 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004840
4841 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004842 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004843 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004844 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004845
Johan Hedberg61b43352014-05-29 19:36:53 +03004846 switch (key->type) {
4847 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004848 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004849 break;
4850 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004851 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004852 break;
4853 default:
4854 continue;
4855 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004856
Johan Hedberg35d70272014-02-19 14:57:47 +02004857 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004858 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004859 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004860 }
4861
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004862 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4863 NULL, 0);
4864
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004865 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004866
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004867 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004868}
4869
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004870struct cmd_conn_lookup {
4871 struct hci_conn *conn;
4872 bool valid_tx_power;
4873 u8 mgmt_status;
4874};
4875
4876static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4877{
4878 struct cmd_conn_lookup *match = data;
4879 struct mgmt_cp_get_conn_info *cp;
4880 struct mgmt_rp_get_conn_info rp;
4881 struct hci_conn *conn = cmd->user_data;
4882
4883 if (conn != match->conn)
4884 return;
4885
4886 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4887
4888 memset(&rp, 0, sizeof(rp));
4889 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4890 rp.addr.type = cp->addr.type;
4891
4892 if (!match->mgmt_status) {
4893 rp.rssi = conn->rssi;
4894
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004895 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004896 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004897 rp.max_tx_power = conn->max_tx_power;
4898 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004899 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004900 rp.max_tx_power = HCI_TX_POWER_INVALID;
4901 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004902 }
4903
4904 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4905 match->mgmt_status, &rp, sizeof(rp));
4906
4907 hci_conn_drop(conn);
4908
4909 mgmt_pending_remove(cmd);
4910}
4911
4912static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4913{
4914 struct hci_cp_read_rssi *cp;
4915 struct hci_conn *conn;
4916 struct cmd_conn_lookup match;
4917 u16 handle;
4918
4919 BT_DBG("status 0x%02x", status);
4920
4921 hci_dev_lock(hdev);
4922
4923 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004924 * otherwise we assume it's not valid. At the moment we assume that
4925 * either both or none of current and max values are valid to keep code
4926 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004927 */
4928 match.valid_tx_power = !status;
4929
4930 /* Commands sent in request are either Read RSSI or Read Transmit Power
4931 * Level so we check which one was last sent to retrieve connection
4932 * handle. Both commands have handle as first parameter so it's safe to
4933 * cast data on the same command struct.
4934 *
4935 * First command sent is always Read RSSI and we fail only if it fails.
4936 * In other case we simply override error to indicate success as we
4937 * already remembered if TX power value is actually valid.
4938 */
4939 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4940 if (!cp) {
4941 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4942 status = 0;
4943 }
4944
4945 if (!cp) {
4946 BT_ERR("invalid sent_cmd in response");
4947 goto unlock;
4948 }
4949
4950 handle = __le16_to_cpu(cp->handle);
4951 conn = hci_conn_hash_lookup_handle(hdev, handle);
4952 if (!conn) {
4953 BT_ERR("unknown handle (%d) in response", handle);
4954 goto unlock;
4955 }
4956
4957 match.conn = conn;
4958 match.mgmt_status = mgmt_status(status);
4959
4960 /* Cache refresh is complete, now reply for mgmt request for given
4961 * connection only.
4962 */
4963 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4964 get_conn_info_complete, &match);
4965
4966unlock:
4967 hci_dev_unlock(hdev);
4968}
4969
4970static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4971 u16 len)
4972{
4973 struct mgmt_cp_get_conn_info *cp = data;
4974 struct mgmt_rp_get_conn_info rp;
4975 struct hci_conn *conn;
4976 unsigned long conn_info_age;
4977 int err = 0;
4978
4979 BT_DBG("%s", hdev->name);
4980
4981 memset(&rp, 0, sizeof(rp));
4982 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4983 rp.addr.type = cp->addr.type;
4984
4985 if (!bdaddr_type_is_valid(cp->addr.type))
4986 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4987 MGMT_STATUS_INVALID_PARAMS,
4988 &rp, sizeof(rp));
4989
4990 hci_dev_lock(hdev);
4991
4992 if (!hdev_is_powered(hdev)) {
4993 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4994 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4995 goto unlock;
4996 }
4997
4998 if (cp->addr.type == BDADDR_BREDR)
4999 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5000 &cp->addr.bdaddr);
5001 else
5002 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5003
5004 if (!conn || conn->state != BT_CONNECTED) {
5005 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5006 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5007 goto unlock;
5008 }
5009
5010 /* To avoid client trying to guess when to poll again for information we
5011 * calculate conn info age as random value between min/max set in hdev.
5012 */
5013 conn_info_age = hdev->conn_info_min_age +
5014 prandom_u32_max(hdev->conn_info_max_age -
5015 hdev->conn_info_min_age);
5016
5017 /* Query controller to refresh cached values if they are too old or were
5018 * never read.
5019 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005020 if (time_after(jiffies, conn->conn_info_timestamp +
5021 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005022 !conn->conn_info_timestamp) {
5023 struct hci_request req;
5024 struct hci_cp_read_tx_power req_txp_cp;
5025 struct hci_cp_read_rssi req_rssi_cp;
5026 struct pending_cmd *cmd;
5027
5028 hci_req_init(&req, hdev);
5029 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5030 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5031 &req_rssi_cp);
5032
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005033 /* For LE links TX power does not change thus we don't need to
5034 * query for it once value is known.
5035 */
5036 if (!bdaddr_type_is_le(cp->addr.type) ||
5037 conn->tx_power == HCI_TX_POWER_INVALID) {
5038 req_txp_cp.handle = cpu_to_le16(conn->handle);
5039 req_txp_cp.type = 0x00;
5040 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5041 sizeof(req_txp_cp), &req_txp_cp);
5042 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005043
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005044 /* Max TX power needs to be read only once per connection */
5045 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5046 req_txp_cp.handle = cpu_to_le16(conn->handle);
5047 req_txp_cp.type = 0x01;
5048 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5049 sizeof(req_txp_cp), &req_txp_cp);
5050 }
5051
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005052 err = hci_req_run(&req, conn_info_refresh_complete);
5053 if (err < 0)
5054 goto unlock;
5055
5056 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5057 data, len);
5058 if (!cmd) {
5059 err = -ENOMEM;
5060 goto unlock;
5061 }
5062
5063 hci_conn_hold(conn);
5064 cmd->user_data = conn;
5065
5066 conn->conn_info_timestamp = jiffies;
5067 } else {
5068 /* Cache is valid, just reply with values cached in hci_conn */
5069 rp.rssi = conn->rssi;
5070 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005071 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005072
5073 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5074 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5075 }
5076
5077unlock:
5078 hci_dev_unlock(hdev);
5079 return err;
5080}
5081
Johan Hedberg95868422014-06-28 17:54:07 +03005082static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5083{
5084 struct mgmt_cp_get_clock_info *cp;
5085 struct mgmt_rp_get_clock_info rp;
5086 struct hci_cp_read_clock *hci_cp;
5087 struct pending_cmd *cmd;
5088 struct hci_conn *conn;
5089
5090 BT_DBG("%s status %u", hdev->name, status);
5091
5092 hci_dev_lock(hdev);
5093
5094 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5095 if (!hci_cp)
5096 goto unlock;
5097
5098 if (hci_cp->which) {
5099 u16 handle = __le16_to_cpu(hci_cp->handle);
5100 conn = hci_conn_hash_lookup_handle(hdev, handle);
5101 } else {
5102 conn = NULL;
5103 }
5104
5105 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5106 if (!cmd)
5107 goto unlock;
5108
5109 cp = cmd->param;
5110
5111 memset(&rp, 0, sizeof(rp));
5112 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5113
5114 if (status)
5115 goto send_rsp;
5116
5117 rp.local_clock = cpu_to_le32(hdev->clock);
5118
5119 if (conn) {
5120 rp.piconet_clock = cpu_to_le32(conn->clock);
5121 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5122 }
5123
5124send_rsp:
5125 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5126 &rp, sizeof(rp));
5127 mgmt_pending_remove(cmd);
5128 if (conn)
5129 hci_conn_drop(conn);
5130
5131unlock:
5132 hci_dev_unlock(hdev);
5133}
5134
5135static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5136 u16 len)
5137{
5138 struct mgmt_cp_get_clock_info *cp = data;
5139 struct mgmt_rp_get_clock_info rp;
5140 struct hci_cp_read_clock hci_cp;
5141 struct pending_cmd *cmd;
5142 struct hci_request req;
5143 struct hci_conn *conn;
5144 int err;
5145
5146 BT_DBG("%s", hdev->name);
5147
5148 memset(&rp, 0, sizeof(rp));
5149 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5150 rp.addr.type = cp->addr.type;
5151
5152 if (cp->addr.type != BDADDR_BREDR)
5153 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5154 MGMT_STATUS_INVALID_PARAMS,
5155 &rp, sizeof(rp));
5156
5157 hci_dev_lock(hdev);
5158
5159 if (!hdev_is_powered(hdev)) {
5160 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5161 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5162 goto unlock;
5163 }
5164
5165 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5166 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5167 &cp->addr.bdaddr);
5168 if (!conn || conn->state != BT_CONNECTED) {
5169 err = cmd_complete(sk, hdev->id,
5170 MGMT_OP_GET_CLOCK_INFO,
5171 MGMT_STATUS_NOT_CONNECTED,
5172 &rp, sizeof(rp));
5173 goto unlock;
5174 }
5175 } else {
5176 conn = NULL;
5177 }
5178
5179 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5180 if (!cmd) {
5181 err = -ENOMEM;
5182 goto unlock;
5183 }
5184
5185 hci_req_init(&req, hdev);
5186
5187 memset(&hci_cp, 0, sizeof(hci_cp));
5188 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5189
5190 if (conn) {
5191 hci_conn_hold(conn);
5192 cmd->user_data = conn;
5193
5194 hci_cp.handle = cpu_to_le16(conn->handle);
5195 hci_cp.which = 0x01; /* Piconet clock */
5196 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5197 }
5198
5199 err = hci_req_run(&req, get_clock_info_complete);
5200 if (err < 0)
5201 mgmt_pending_remove(cmd);
5202
5203unlock:
5204 hci_dev_unlock(hdev);
5205 return err;
5206}
5207
Johan Hedberga3974072014-07-09 12:59:15 +03005208/* Helper for Add/Remove Device commands */
5209static void update_page_scan(struct hci_dev *hdev, u8 scan)
5210{
5211 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5212 return;
5213
5214 if (!hdev_is_powered(hdev))
5215 return;
5216
5217 /* If HCI_CONNECTABLE is set then Add/Remove Device should not
5218 * make any changes to page scanning.
5219 */
5220 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
5221 return;
5222
5223 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
5224 scan |= SCAN_INQUIRY;
5225
5226 hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
5227}
5228
Marcel Holtmann8afef092014-06-29 22:28:34 +02005229static void device_added(struct sock *sk, struct hci_dev *hdev,
5230 bdaddr_t *bdaddr, u8 type, u8 action)
5231{
5232 struct mgmt_ev_device_added ev;
5233
5234 bacpy(&ev.addr.bdaddr, bdaddr);
5235 ev.addr.type = type;
5236 ev.action = action;
5237
5238 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5239}
5240
Marcel Holtmann2faade52014-06-29 19:44:03 +02005241static int add_device(struct sock *sk, struct hci_dev *hdev,
5242 void *data, u16 len)
5243{
5244 struct mgmt_cp_add_device *cp = data;
5245 u8 auto_conn, addr_type;
5246 int err;
5247
5248 BT_DBG("%s", hdev->name);
5249
Johan Hedberg66593582014-07-09 12:59:14 +03005250 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005251 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5252 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5253 MGMT_STATUS_INVALID_PARAMS,
5254 &cp->addr, sizeof(cp->addr));
5255
5256 if (cp->action != 0x00 && cp->action != 0x01)
5257 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5258 MGMT_STATUS_INVALID_PARAMS,
5259 &cp->addr, sizeof(cp->addr));
5260
5261 hci_dev_lock(hdev);
5262
Johan Hedberg66593582014-07-09 12:59:14 +03005263 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberga3974072014-07-09 12:59:15 +03005264 bool update_scan;
5265
Johan Hedberg66593582014-07-09 12:59:14 +03005266 /* Only "connect" action supported for now */
5267 if (cp->action != 0x01) {
5268 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5269 MGMT_STATUS_INVALID_PARAMS,
5270 &cp->addr, sizeof(cp->addr));
5271 goto unlock;
5272 }
5273
Johan Hedberga3974072014-07-09 12:59:15 +03005274 update_scan = list_empty(&hdev->whitelist);
5275
Johan Hedberg66593582014-07-09 12:59:14 +03005276 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5277 cp->addr.type);
5278 if (err)
5279 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005280
5281 if (update_scan)
5282 update_page_scan(hdev, SCAN_PAGE);
5283
Johan Hedberg66593582014-07-09 12:59:14 +03005284 goto added;
5285 }
5286
Marcel Holtmann2faade52014-06-29 19:44:03 +02005287 if (cp->addr.type == BDADDR_LE_PUBLIC)
5288 addr_type = ADDR_LE_DEV_PUBLIC;
5289 else
5290 addr_type = ADDR_LE_DEV_RANDOM;
5291
5292 if (cp->action)
5293 auto_conn = HCI_AUTO_CONN_ALWAYS;
5294 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005295 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005296
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005297 /* If the connection parameters don't exist for this device,
5298 * they will be created and configured with defaults.
5299 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005300 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5301 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005302 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5303 MGMT_STATUS_FAILED,
5304 &cp->addr, sizeof(cp->addr));
5305 goto unlock;
5306 }
5307
Johan Hedberg66593582014-07-09 12:59:14 +03005308added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005309 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5310
Marcel Holtmann2faade52014-06-29 19:44:03 +02005311 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5312 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5313
5314unlock:
5315 hci_dev_unlock(hdev);
5316 return err;
5317}
5318
Marcel Holtmann8afef092014-06-29 22:28:34 +02005319static void device_removed(struct sock *sk, struct hci_dev *hdev,
5320 bdaddr_t *bdaddr, u8 type)
5321{
5322 struct mgmt_ev_device_removed ev;
5323
5324 bacpy(&ev.addr.bdaddr, bdaddr);
5325 ev.addr.type = type;
5326
5327 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5328}
5329
Marcel Holtmann2faade52014-06-29 19:44:03 +02005330static int remove_device(struct sock *sk, struct hci_dev *hdev,
5331 void *data, u16 len)
5332{
5333 struct mgmt_cp_remove_device *cp = data;
5334 int err;
5335
5336 BT_DBG("%s", hdev->name);
5337
5338 hci_dev_lock(hdev);
5339
5340 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005341 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005342 u8 addr_type;
5343
Johan Hedberg66593582014-07-09 12:59:14 +03005344 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005345 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5346 MGMT_STATUS_INVALID_PARAMS,
5347 &cp->addr, sizeof(cp->addr));
5348 goto unlock;
5349 }
5350
Johan Hedberg66593582014-07-09 12:59:14 +03005351 if (cp->addr.type == BDADDR_BREDR) {
5352 err = hci_bdaddr_list_del(&hdev->whitelist,
5353 &cp->addr.bdaddr,
5354 cp->addr.type);
5355 if (err) {
5356 err = cmd_complete(sk, hdev->id,
5357 MGMT_OP_REMOVE_DEVICE,
5358 MGMT_STATUS_INVALID_PARAMS,
5359 &cp->addr, sizeof(cp->addr));
5360 goto unlock;
5361 }
5362
Johan Hedberga3974072014-07-09 12:59:15 +03005363 if (list_empty(&hdev->whitelist))
5364 update_page_scan(hdev, SCAN_DISABLED);
5365
Johan Hedberg66593582014-07-09 12:59:14 +03005366 device_removed(sk, hdev, &cp->addr.bdaddr,
5367 cp->addr.type);
5368 goto complete;
5369 }
5370
Marcel Holtmann2faade52014-06-29 19:44:03 +02005371 if (cp->addr.type == BDADDR_LE_PUBLIC)
5372 addr_type = ADDR_LE_DEV_PUBLIC;
5373 else
5374 addr_type = ADDR_LE_DEV_RANDOM;
5375
Johan Hedbergc71593d2014-07-02 17:37:28 +03005376 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5377 addr_type);
5378 if (!params) {
5379 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5380 MGMT_STATUS_INVALID_PARAMS,
5381 &cp->addr, sizeof(cp->addr));
5382 goto unlock;
5383 }
5384
5385 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5386 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5387 MGMT_STATUS_INVALID_PARAMS,
5388 &cp->addr, sizeof(cp->addr));
5389 goto unlock;
5390 }
5391
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005392 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005393 list_del(&params->list);
5394 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005395 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005396
5397 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005398 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005399 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005400 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005401
Marcel Holtmann2faade52014-06-29 19:44:03 +02005402 if (cp->addr.type) {
5403 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5404 MGMT_STATUS_INVALID_PARAMS,
5405 &cp->addr, sizeof(cp->addr));
5406 goto unlock;
5407 }
5408
Johan Hedberg66593582014-07-09 12:59:14 +03005409 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5410 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5411 list_del(&b->list);
5412 kfree(b);
5413 }
5414
Johan Hedberga3974072014-07-09 12:59:15 +03005415 update_page_scan(hdev, SCAN_DISABLED);
5416
Johan Hedberg19de0822014-07-06 13:06:51 +03005417 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5418 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5419 continue;
5420 device_removed(sk, hdev, &p->addr, p->addr_type);
5421 list_del(&p->action);
5422 list_del(&p->list);
5423 kfree(p);
5424 }
5425
5426 BT_DBG("All LE connection parameters were removed");
5427
5428 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005429 }
5430
Johan Hedberg66593582014-07-09 12:59:14 +03005431complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005432 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5433 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5434
5435unlock:
5436 hci_dev_unlock(hdev);
5437 return err;
5438}
5439
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005440static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5441 u16 len)
5442{
5443 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005444 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5445 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005446 u16 param_count, expected_len;
5447 int i;
5448
5449 if (!lmp_le_capable(hdev))
5450 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5451 MGMT_STATUS_NOT_SUPPORTED);
5452
5453 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005454 if (param_count > max_param_count) {
5455 BT_ERR("load_conn_param: too big param_count value %u",
5456 param_count);
5457 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5458 MGMT_STATUS_INVALID_PARAMS);
5459 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005460
5461 expected_len = sizeof(*cp) + param_count *
5462 sizeof(struct mgmt_conn_param);
5463 if (expected_len != len) {
5464 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5465 expected_len, len);
5466 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5467 MGMT_STATUS_INVALID_PARAMS);
5468 }
5469
5470 BT_DBG("%s param_count %u", hdev->name, param_count);
5471
5472 hci_dev_lock(hdev);
5473
5474 hci_conn_params_clear_disabled(hdev);
5475
5476 for (i = 0; i < param_count; i++) {
5477 struct mgmt_conn_param *param = &cp->params[i];
5478 struct hci_conn_params *hci_param;
5479 u16 min, max, latency, timeout;
5480 u8 addr_type;
5481
5482 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5483 param->addr.type);
5484
5485 if (param->addr.type == BDADDR_LE_PUBLIC) {
5486 addr_type = ADDR_LE_DEV_PUBLIC;
5487 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5488 addr_type = ADDR_LE_DEV_RANDOM;
5489 } else {
5490 BT_ERR("Ignoring invalid connection parameters");
5491 continue;
5492 }
5493
5494 min = le16_to_cpu(param->min_interval);
5495 max = le16_to_cpu(param->max_interval);
5496 latency = le16_to_cpu(param->latency);
5497 timeout = le16_to_cpu(param->timeout);
5498
5499 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5500 min, max, latency, timeout);
5501
5502 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5503 BT_ERR("Ignoring invalid connection parameters");
5504 continue;
5505 }
5506
5507 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5508 addr_type);
5509 if (!hci_param) {
5510 BT_ERR("Failed to add connection parameters");
5511 continue;
5512 }
5513
5514 hci_param->conn_min_interval = min;
5515 hci_param->conn_max_interval = max;
5516 hci_param->conn_latency = latency;
5517 hci_param->supervision_timeout = timeout;
5518 }
5519
5520 hci_dev_unlock(hdev);
5521
5522 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5523}
5524
Marcel Holtmanndbece372014-07-04 18:11:55 +02005525static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5526 void *data, u16 len)
5527{
5528 struct mgmt_cp_set_external_config *cp = data;
5529 bool changed;
5530 int err;
5531
5532 BT_DBG("%s", hdev->name);
5533
5534 if (hdev_is_powered(hdev))
5535 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5536 MGMT_STATUS_REJECTED);
5537
5538 if (cp->config != 0x00 && cp->config != 0x01)
5539 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5540 MGMT_STATUS_INVALID_PARAMS);
5541
5542 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5543 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5544 MGMT_STATUS_NOT_SUPPORTED);
5545
5546 hci_dev_lock(hdev);
5547
5548 if (cp->config)
5549 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5550 &hdev->dev_flags);
5551 else
5552 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5553 &hdev->dev_flags);
5554
5555 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5556 if (err < 0)
5557 goto unlock;
5558
5559 if (!changed)
5560 goto unlock;
5561
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005562 err = new_options(hdev, sk);
5563
Marcel Holtmanndbece372014-07-04 18:11:55 +02005564 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5565 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005566
5567 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5568 set_bit(HCI_CONFIG, &hdev->dev_flags);
5569 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5570
5571 queue_work(hdev->req_workqueue, &hdev->power_on);
5572 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005573 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005574 mgmt_index_added(hdev);
5575 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005576 }
5577
5578unlock:
5579 hci_dev_unlock(hdev);
5580 return err;
5581}
5582
Marcel Holtmann9713c172014-07-06 12:11:15 +02005583static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5584 void *data, u16 len)
5585{
5586 struct mgmt_cp_set_public_address *cp = data;
5587 bool changed;
5588 int err;
5589
5590 BT_DBG("%s", hdev->name);
5591
5592 if (hdev_is_powered(hdev))
5593 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5594 MGMT_STATUS_REJECTED);
5595
5596 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5597 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5598 MGMT_STATUS_INVALID_PARAMS);
5599
5600 if (!hdev->set_bdaddr)
5601 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5602 MGMT_STATUS_NOT_SUPPORTED);
5603
5604 hci_dev_lock(hdev);
5605
5606 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5607 bacpy(&hdev->public_addr, &cp->bdaddr);
5608
5609 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5610 if (err < 0)
5611 goto unlock;
5612
5613 if (!changed)
5614 goto unlock;
5615
5616 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5617 err = new_options(hdev, sk);
5618
5619 if (is_configured(hdev)) {
5620 mgmt_index_removed(hdev);
5621
5622 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5623
5624 set_bit(HCI_CONFIG, &hdev->dev_flags);
5625 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5626
5627 queue_work(hdev->req_workqueue, &hdev->power_on);
5628 }
5629
5630unlock:
5631 hci_dev_unlock(hdev);
5632 return err;
5633}
5634
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005635static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005636 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5637 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005638 bool var_len;
5639 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005640} mgmt_handlers[] = {
5641 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005642 { read_version, false, MGMT_READ_VERSION_SIZE },
5643 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5644 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5645 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5646 { set_powered, false, MGMT_SETTING_SIZE },
5647 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5648 { set_connectable, false, MGMT_SETTING_SIZE },
5649 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5650 { set_pairable, false, MGMT_SETTING_SIZE },
5651 { set_link_security, false, MGMT_SETTING_SIZE },
5652 { set_ssp, false, MGMT_SETTING_SIZE },
5653 { set_hs, false, MGMT_SETTING_SIZE },
5654 { set_le, false, MGMT_SETTING_SIZE },
5655 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5656 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5657 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5658 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5659 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5660 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5661 { disconnect, false, MGMT_DISCONNECT_SIZE },
5662 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5663 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5664 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5665 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5666 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5667 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5668 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5669 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5670 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5671 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5672 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5673 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005674 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005675 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5676 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5677 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5678 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5679 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5680 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005681 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005682 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005683 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005684 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005685 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005686 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005687 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005688 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005689 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005690 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005691 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005692 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5693 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005694 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5695 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005696 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005697 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005698 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005699};
5700
Johan Hedberg03811012010-12-08 00:21:06 +02005701int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5702{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005703 void *buf;
5704 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005705 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005706 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005707 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005708 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005709 int err;
5710
5711 BT_DBG("got %zu bytes", msglen);
5712
5713 if (msglen < sizeof(*hdr))
5714 return -EINVAL;
5715
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005716 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005717 if (!buf)
5718 return -ENOMEM;
5719
5720 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5721 err = -EFAULT;
5722 goto done;
5723 }
5724
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005725 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005726 opcode = __le16_to_cpu(hdr->opcode);
5727 index = __le16_to_cpu(hdr->index);
5728 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005729
5730 if (len != msglen - sizeof(*hdr)) {
5731 err = -EINVAL;
5732 goto done;
5733 }
5734
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005735 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005736 hdev = hci_dev_get(index);
5737 if (!hdev) {
5738 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005739 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005740 goto done;
5741 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005742
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005743 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005744 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005745 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005746 err = cmd_status(sk, index, opcode,
5747 MGMT_STATUS_INVALID_INDEX);
5748 goto done;
5749 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005750
5751 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005752 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005753 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5754 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005755 err = cmd_status(sk, index, opcode,
5756 MGMT_STATUS_INVALID_INDEX);
5757 goto done;
5758 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005759 }
5760
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005761 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005762 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005763 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005764 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005765 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005766 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005767 }
5768
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005769 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5770 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5771 err = cmd_status(sk, index, opcode,
5772 MGMT_STATUS_INVALID_INDEX);
5773 goto done;
5774 }
5775
5776 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5777 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005778 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005779 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005780 goto done;
5781 }
5782
Johan Hedbergbe22b542012-03-01 22:24:41 +02005783 handler = &mgmt_handlers[opcode];
5784
5785 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005786 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005787 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005788 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005789 goto done;
5790 }
5791
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005792 if (hdev)
5793 mgmt_init_hdev(sk, hdev);
5794
5795 cp = buf + sizeof(*hdr);
5796
Johan Hedbergbe22b542012-03-01 22:24:41 +02005797 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005798 if (err < 0)
5799 goto done;
5800
Johan Hedberg03811012010-12-08 00:21:06 +02005801 err = msglen;
5802
5803done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005804 if (hdev)
5805 hci_dev_put(hdev);
5806
Johan Hedberg03811012010-12-08 00:21:06 +02005807 kfree(buf);
5808 return err;
5809}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005810
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005811void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005812{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005813 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005814 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005815
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005816 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5817 return;
5818
5819 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5820 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5821 else
5822 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005823}
5824
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005825void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005826{
Johan Hedberg5f159032012-03-02 03:13:19 +02005827 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005828
Marcel Holtmann1514b892013-10-06 08:25:01 -07005829 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005830 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005831
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005832 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5833 return;
5834
Johan Hedberg744cf192011-11-08 20:40:14 +02005835 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005836
Marcel Holtmannedd38962014-07-02 21:30:55 +02005837 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5838 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5839 else
5840 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005841}
5842
Andre Guedes6046dc32014-02-26 20:21:51 -03005843/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005844static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005845{
5846 struct hci_conn_params *p;
5847
5848 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005849 /* Needed for AUTO_OFF case where might not "really"
5850 * have been powered off.
5851 */
5852 list_del_init(&p->action);
5853
5854 switch (p->auto_connect) {
5855 case HCI_AUTO_CONN_ALWAYS:
5856 list_add(&p->action, &hdev->pend_le_conns);
5857 break;
5858 case HCI_AUTO_CONN_REPORT:
5859 list_add(&p->action, &hdev->pend_le_reports);
5860 break;
5861 default:
5862 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005863 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005864 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005865
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005866 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005867}
5868
Johan Hedberg229ab392013-03-15 17:06:53 -05005869static void powered_complete(struct hci_dev *hdev, u8 status)
5870{
5871 struct cmd_lookup match = { NULL, hdev };
5872
5873 BT_DBG("status 0x%02x", status);
5874
5875 hci_dev_lock(hdev);
5876
Johan Hedbergd7347f32014-07-04 12:37:23 +03005877 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005878
Johan Hedberg229ab392013-03-15 17:06:53 -05005879 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5880
5881 new_settings(hdev, match.sk);
5882
5883 hci_dev_unlock(hdev);
5884
5885 if (match.sk)
5886 sock_put(match.sk);
5887}
5888
Johan Hedberg70da6242013-03-15 17:06:51 -05005889static int powered_update_hci(struct hci_dev *hdev)
5890{
Johan Hedberg890ea892013-03-15 17:06:52 -05005891 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005892 u8 link_sec;
5893
Johan Hedberg890ea892013-03-15 17:06:52 -05005894 hci_req_init(&req, hdev);
5895
Johan Hedberg70da6242013-03-15 17:06:51 -05005896 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5897 !lmp_host_ssp_capable(hdev)) {
5898 u8 ssp = 1;
5899
Johan Hedberg890ea892013-03-15 17:06:52 -05005900 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005901 }
5902
Johan Hedbergc73eee92013-04-19 18:35:21 +03005903 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5904 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005905 struct hci_cp_write_le_host_supported cp;
5906
5907 cp.le = 1;
5908 cp.simul = lmp_le_br_capable(hdev);
5909
5910 /* Check first if we already have the right
5911 * host state (host features set)
5912 */
5913 if (cp.le != lmp_host_le_capable(hdev) ||
5914 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005915 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5916 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005917 }
5918
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005919 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005920 /* Make sure the controller has a good default for
5921 * advertising data. This also applies to the case
5922 * where BR/EDR was toggled during the AUTO_OFF phase.
5923 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005924 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005925 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005926 update_scan_rsp_data(&req);
5927 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005928
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005929 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5930 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005931 }
5932
Johan Hedberg70da6242013-03-15 17:06:51 -05005933 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5934 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005935 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5936 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005937
5938 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005939 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5940 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005941 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005942 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005943 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005944 }
5945
Johan Hedberg229ab392013-03-15 17:06:53 -05005946 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005947}
5948
Johan Hedberg744cf192011-11-08 20:40:14 +02005949int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005950{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005951 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005952 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5953 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005954 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005955
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005956 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5957 return 0;
5958
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005959 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005960 if (powered_update_hci(hdev) == 0)
5961 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005962
Johan Hedberg229ab392013-03-15 17:06:53 -05005963 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5964 &match);
5965 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005966 }
5967
Johan Hedberg229ab392013-03-15 17:06:53 -05005968 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5969 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5970
5971 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5972 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5973 zero_cod, sizeof(zero_cod), NULL);
5974
5975new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005976 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005977
5978 if (match.sk)
5979 sock_put(match.sk);
5980
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005981 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005982}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005983
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005984void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005985{
5986 struct pending_cmd *cmd;
5987 u8 status;
5988
5989 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5990 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005991 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005992
5993 if (err == -ERFKILL)
5994 status = MGMT_STATUS_RFKILLED;
5995 else
5996 status = MGMT_STATUS_FAILED;
5997
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005998 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005999
6000 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006001}
6002
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006003void mgmt_discoverable_timeout(struct hci_dev *hdev)
6004{
6005 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006006
6007 hci_dev_lock(hdev);
6008
6009 /* When discoverable timeout triggers, then just make sure
6010 * the limited discoverable flag is cleared. Even in the case
6011 * of a timeout triggered from general discoverable, it is
6012 * safe to unconditionally clear the flag.
6013 */
6014 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006015 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006016
6017 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006018 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6019 u8 scan = SCAN_PAGE;
6020 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6021 sizeof(scan), &scan);
6022 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006023 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006024 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006025 hci_req_run(&req, NULL);
6026
6027 hdev->discov_timeout = 0;
6028
Johan Hedberg9a43e252013-10-20 19:00:07 +03006029 new_settings(hdev, NULL);
6030
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006031 hci_dev_unlock(hdev);
6032}
6033
Marcel Holtmann86a75642013-10-15 06:33:54 -07006034void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02006035{
Marcel Holtmann86a75642013-10-15 06:33:54 -07006036 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02006037
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03006038 /* Nothing needed here if there's a pending command since that
6039 * commands request completion callback takes care of everything
6040 * necessary.
6041 */
6042 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07006043 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03006044
Johan Hedbergbd107992014-02-24 14:52:19 +02006045 /* Powering off may clear the scan mode - don't let that interfere */
6046 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
6047 return;
6048
Johan Hedberg9a43e252013-10-20 19:00:07 +03006049 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07006050 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006051 } else {
6052 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07006053 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006054 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02006055
Johan Hedberg9a43e252013-10-20 19:00:07 +03006056 if (changed) {
6057 struct hci_request req;
6058
6059 /* In case this change in discoverable was triggered by
6060 * a disabling of connectable there could be a need to
6061 * update the advertising flags.
6062 */
6063 hci_req_init(&req, hdev);
6064 update_adv_data(&req);
6065 hci_req_run(&req, NULL);
6066
Marcel Holtmann86a75642013-10-15 06:33:54 -07006067 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006068 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02006069}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006070
Marcel Holtmanna3309162013-10-15 06:33:55 -07006071void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006072{
Marcel Holtmanna3309162013-10-15 06:33:55 -07006073 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006074
Johan Hedbergd7b856f2013-10-14 16:20:04 +03006075 /* Nothing needed here if there's a pending command since that
6076 * commands request completion callback takes care of everything
6077 * necessary.
6078 */
6079 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07006080 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03006081
Johan Hedbergce3f24c2014-02-24 14:52:20 +02006082 /* Powering off may clear the scan mode - don't let that interfere */
6083 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
6084 return;
6085
Johan Hedbergdee58c12014-07-09 12:59:16 +03006086 /* If something else than mgmt changed the page scan state we
6087 * can't differentiate this from a change triggered by adding
6088 * the first element to the whitelist. Therefore, avoid
6089 * incorrectly setting HCI_CONNECTABLE.
6090 */
6091 if (connectable && !list_empty(&hdev->whitelist))
6092 return;
6093
Marcel Holtmanna3309162013-10-15 06:33:55 -07006094 if (connectable)
6095 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
6096 else
6097 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006098
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006099 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07006100 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006101}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006102
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07006103void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006104{
Johan Hedbergca69b792011-11-11 18:10:00 +02006105 u8 mgmt_err = mgmt_status(status);
6106
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006107 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02006108 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006109 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006110
6111 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02006112 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006113 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006114}
6115
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006116void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6117 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006118{
Johan Hedberg86742e12011-11-07 23:13:38 +02006119 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006120
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006121 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006122
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006123 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006124 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006125 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006126 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006127 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006128 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006129
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006130 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006131}
Johan Hedbergf7520542011-01-20 12:34:39 +02006132
Johan Hedbergd7b25452014-05-23 13:19:53 +03006133static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6134{
6135 if (ltk->authenticated)
6136 return MGMT_LTK_AUTHENTICATED;
6137
6138 return MGMT_LTK_UNAUTHENTICATED;
6139}
6140
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006141void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006142{
6143 struct mgmt_ev_new_long_term_key ev;
6144
6145 memset(&ev, 0, sizeof(ev));
6146
Marcel Holtmann5192d302014-02-19 17:11:58 -08006147 /* Devices using resolvable or non-resolvable random addresses
6148 * without providing an indentity resolving key don't require
6149 * to store long term keys. Their addresses will change the
6150 * next time around.
6151 *
6152 * Only when a remote device provides an identity address
6153 * make sure the long term key is stored. If the remote
6154 * identity is known, the long term keys are internally
6155 * mapped to the identity address. So allow static random
6156 * and public addresses here.
6157 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006158 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6159 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6160 ev.store_hint = 0x00;
6161 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006162 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006163
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006164 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006165 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006166 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006167 ev.key.enc_size = key->enc_size;
6168 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006169 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006170
Johan Hedberg2ceba532014-06-16 19:25:16 +03006171 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006172 ev.key.master = 1;
6173
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006174 memcpy(ev.key.val, key->val, sizeof(key->val));
6175
Marcel Holtmann083368f2013-10-15 14:26:29 -07006176 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006177}
6178
Johan Hedberg95fbac82014-02-19 15:18:31 +02006179void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6180{
6181 struct mgmt_ev_new_irk ev;
6182
6183 memset(&ev, 0, sizeof(ev));
6184
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006185 /* For identity resolving keys from devices that are already
6186 * using a public address or static random address, do not
6187 * ask for storing this key. The identity resolving key really
6188 * is only mandatory for devices using resovlable random
6189 * addresses.
6190 *
6191 * Storing all identity resolving keys has the downside that
6192 * they will be also loaded on next boot of they system. More
6193 * identity resolving keys, means more time during scanning is
6194 * needed to actually resolve these addresses.
6195 */
6196 if (bacmp(&irk->rpa, BDADDR_ANY))
6197 ev.store_hint = 0x01;
6198 else
6199 ev.store_hint = 0x00;
6200
Johan Hedberg95fbac82014-02-19 15:18:31 +02006201 bacpy(&ev.rpa, &irk->rpa);
6202 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6203 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6204 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6205
6206 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6207}
6208
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006209void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6210 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006211{
6212 struct mgmt_ev_new_csrk ev;
6213
6214 memset(&ev, 0, sizeof(ev));
6215
6216 /* Devices using resolvable or non-resolvable random addresses
6217 * without providing an indentity resolving key don't require
6218 * to store signature resolving keys. Their addresses will change
6219 * the next time around.
6220 *
6221 * Only when a remote device provides an identity address
6222 * make sure the signature resolving key is stored. So allow
6223 * static random and public addresses here.
6224 */
6225 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6226 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6227 ev.store_hint = 0x00;
6228 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006229 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006230
6231 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6232 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6233 ev.key.master = csrk->master;
6234 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6235
6236 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6237}
6238
Andre Guedesffb5a8272014-07-01 18:10:11 -03006239void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006240 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6241 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006242{
6243 struct mgmt_ev_new_conn_param ev;
6244
Johan Hedbergc103aea2014-07-02 17:37:34 +03006245 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6246 return;
6247
Andre Guedesffb5a8272014-07-01 18:10:11 -03006248 memset(&ev, 0, sizeof(ev));
6249 bacpy(&ev.addr.bdaddr, bdaddr);
6250 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006251 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006252 ev.min_interval = cpu_to_le16(min_interval);
6253 ev.max_interval = cpu_to_le16(max_interval);
6254 ev.latency = cpu_to_le16(latency);
6255 ev.timeout = cpu_to_le16(timeout);
6256
6257 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6258}
6259
Marcel Holtmann94933992013-10-15 10:26:39 -07006260static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6261 u8 data_len)
6262{
6263 eir[eir_len++] = sizeof(type) + data_len;
6264 eir[eir_len++] = type;
6265 memcpy(&eir[eir_len], data, data_len);
6266 eir_len += data_len;
6267
6268 return eir_len;
6269}
6270
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006271void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6272 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6273 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006274{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006275 char buf[512];
6276 struct mgmt_ev_device_connected *ev = (void *) buf;
6277 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006278
Johan Hedbergb644ba32012-01-17 21:48:47 +02006279 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006280 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006281
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006282 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006283
Johan Hedbergb644ba32012-01-17 21:48:47 +02006284 if (name_len > 0)
6285 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006286 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006287
6288 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006289 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006290 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006291
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006292 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006293
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006294 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6295 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006296}
6297
Johan Hedberg8962ee72011-01-20 12:40:27 +02006298static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6299{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006300 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006301 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006302 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006303
Johan Hedberg88c3df12012-02-09 14:27:38 +02006304 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6305 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006306
Johan Hedbergaee9b212012-02-18 15:07:59 +02006307 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006308 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006309
6310 *sk = cmd->sk;
6311 sock_hold(*sk);
6312
Johan Hedberga664b5b2011-02-19 12:06:02 -03006313 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006314}
6315
Johan Hedberg124f6e32012-02-09 13:50:12 +02006316static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006317{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006318 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006319 struct mgmt_cp_unpair_device *cp = cmd->param;
6320 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006321
6322 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006323 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6324 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006325
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006326 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6327
Johan Hedbergaee9b212012-02-18 15:07:59 +02006328 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006329
6330 mgmt_pending_remove(cmd);
6331}
6332
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006333void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006334 u8 link_type, u8 addr_type, u8 reason,
6335 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006336{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006337 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006338 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006339 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006340
Johan Hedberg8b064a32014-02-24 14:52:22 +02006341 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6342 if (power_off) {
6343 struct mgmt_mode *cp = power_off->param;
6344
6345 /* The connection is still in hci_conn_hash so test for 1
6346 * instead of 0 to know if this is the last one.
6347 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006348 if (!cp->val && hci_conn_count(hdev) == 1) {
6349 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006350 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006351 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006352 }
6353
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006354 if (!mgmt_connected)
6355 return;
6356
Andre Guedes57eb7762013-10-30 19:01:41 -03006357 if (link_type != ACL_LINK && link_type != LE_LINK)
6358 return;
6359
Johan Hedberg744cf192011-11-08 20:40:14 +02006360 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006361
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006362 bacpy(&ev.addr.bdaddr, bdaddr);
6363 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6364 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006365
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006366 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006367
6368 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006369 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006370
Johan Hedberg124f6e32012-02-09 13:50:12 +02006371 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006372 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006373}
6374
Marcel Holtmann78929242013-10-06 23:55:47 -07006375void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6376 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006377{
Andre Guedes3655bba2013-10-30 19:01:40 -03006378 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6379 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006380 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006381 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006382
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006383 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6384 hdev);
6385
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006386 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006387 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006388 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006389
Andre Guedes3655bba2013-10-30 19:01:40 -03006390 cp = cmd->param;
6391
6392 if (bacmp(bdaddr, &cp->addr.bdaddr))
6393 return;
6394
6395 if (cp->addr.type != bdaddr_type)
6396 return;
6397
Johan Hedberg88c3df12012-02-09 14:27:38 +02006398 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006399 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006400
Marcel Holtmann78929242013-10-06 23:55:47 -07006401 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6402 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006403
Johan Hedberga664b5b2011-02-19 12:06:02 -03006404 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006405}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006406
Marcel Holtmann445608d2013-10-06 23:55:48 -07006407void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6408 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006409{
6410 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006411 struct pending_cmd *power_off;
6412
6413 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6414 if (power_off) {
6415 struct mgmt_mode *cp = power_off->param;
6416
6417 /* The connection is still in hci_conn_hash so test for 1
6418 * instead of 0 to know if this is the last one.
6419 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006420 if (!cp->val && hci_conn_count(hdev) == 1) {
6421 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006422 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006423 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006424 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006425
Johan Hedberg4c659c32011-11-07 23:13:39 +02006426 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006427 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006428 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006429
Marcel Holtmann445608d2013-10-06 23:55:48 -07006430 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006431}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006432
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006433void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006434{
6435 struct mgmt_ev_pin_code_request ev;
6436
Johan Hedbergd8457692012-02-17 14:24:57 +02006437 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006438 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006439 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006440
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006441 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006442}
6443
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006444void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6445 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006446{
6447 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006448 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006449
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006450 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006451 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006452 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006453
Johan Hedbergd8457692012-02-17 14:24:57 +02006454 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006455 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006456
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006457 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6458 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006459
Johan Hedberga664b5b2011-02-19 12:06:02 -03006460 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006461}
6462
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006463void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6464 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006465{
6466 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006467 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006468
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006469 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006470 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006471 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006472
Johan Hedbergd8457692012-02-17 14:24:57 +02006473 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006474 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006475
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006476 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6477 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006478
Johan Hedberga664b5b2011-02-19 12:06:02 -03006479 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006480}
Johan Hedberga5c29682011-02-19 12:05:57 -03006481
Johan Hedberg744cf192011-11-08 20:40:14 +02006482int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006483 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006484 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006485{
6486 struct mgmt_ev_user_confirm_request ev;
6487
Johan Hedberg744cf192011-11-08 20:40:14 +02006488 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006489
Johan Hedberg272d90d2012-02-09 15:26:12 +02006490 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006491 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006492 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006493 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006494
Johan Hedberg744cf192011-11-08 20:40:14 +02006495 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006496 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006497}
6498
Johan Hedberg272d90d2012-02-09 15:26:12 +02006499int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006500 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006501{
6502 struct mgmt_ev_user_passkey_request ev;
6503
6504 BT_DBG("%s", hdev->name);
6505
Johan Hedberg272d90d2012-02-09 15:26:12 +02006506 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006507 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006508
6509 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006510 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006511}
6512
Brian Gix0df4c182011-11-16 13:53:13 -08006513static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006514 u8 link_type, u8 addr_type, u8 status,
6515 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006516{
6517 struct pending_cmd *cmd;
6518 struct mgmt_rp_user_confirm_reply rp;
6519 int err;
6520
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006521 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006522 if (!cmd)
6523 return -ENOENT;
6524
Johan Hedberg272d90d2012-02-09 15:26:12 +02006525 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006526 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006527 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006528 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006529
Johan Hedberga664b5b2011-02-19 12:06:02 -03006530 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006531
6532 return err;
6533}
6534
Johan Hedberg744cf192011-11-08 20:40:14 +02006535int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006536 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006537{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006538 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006539 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006540}
6541
Johan Hedberg272d90d2012-02-09 15:26:12 +02006542int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006543 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006544{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006545 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006546 status,
6547 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006548}
Johan Hedberg2a611692011-02-19 12:06:00 -03006549
Brian Gix604086b2011-11-23 08:28:33 -08006550int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006551 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006552{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006553 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006554 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006555}
6556
Johan Hedberg272d90d2012-02-09 15:26:12 +02006557int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006558 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006559{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006560 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006561 status,
6562 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006563}
6564
Johan Hedberg92a25252012-09-06 18:39:26 +03006565int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6566 u8 link_type, u8 addr_type, u32 passkey,
6567 u8 entered)
6568{
6569 struct mgmt_ev_passkey_notify ev;
6570
6571 BT_DBG("%s", hdev->name);
6572
6573 bacpy(&ev.addr.bdaddr, bdaddr);
6574 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6575 ev.passkey = __cpu_to_le32(passkey);
6576 ev.entered = entered;
6577
6578 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6579}
6580
Marcel Holtmanne5460992013-10-15 14:26:23 -07006581void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6582 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006583{
6584 struct mgmt_ev_auth_failed ev;
6585
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006586 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006587 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006588 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006589
Marcel Holtmanne5460992013-10-15 14:26:23 -07006590 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006591}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006592
Marcel Holtmann464996a2013-10-15 14:26:24 -07006593void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006594{
6595 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006596 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006597
6598 if (status) {
6599 u8 mgmt_err = mgmt_status(status);
6600 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006601 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006602 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006603 }
6604
Marcel Holtmann464996a2013-10-15 14:26:24 -07006605 if (test_bit(HCI_AUTH, &hdev->flags))
6606 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6607 &hdev->dev_flags);
6608 else
6609 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6610 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006611
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006612 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006613 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006614
Johan Hedberg47990ea2012-02-22 11:58:37 +02006615 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006616 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006617
6618 if (match.sk)
6619 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006620}
6621
Johan Hedberg890ea892013-03-15 17:06:52 -05006622static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006623{
Johan Hedberg890ea892013-03-15 17:06:52 -05006624 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006625 struct hci_cp_write_eir cp;
6626
Johan Hedberg976eb202012-10-24 21:12:01 +03006627 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006628 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006629
Johan Hedbergc80da272012-02-22 15:38:48 +02006630 memset(hdev->eir, 0, sizeof(hdev->eir));
6631
Johan Hedbergcacaf522012-02-21 00:52:42 +02006632 memset(&cp, 0, sizeof(cp));
6633
Johan Hedberg890ea892013-03-15 17:06:52 -05006634 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006635}
6636
Marcel Holtmann3e248562013-10-15 14:26:25 -07006637void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006638{
6639 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006640 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006641 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006642
6643 if (status) {
6644 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006645
6646 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006647 &hdev->dev_flags)) {
6648 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006649 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006650 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006651
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006652 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6653 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006654 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006655 }
6656
6657 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006658 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006659 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006660 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6661 if (!changed)
6662 changed = test_and_clear_bit(HCI_HS_ENABLED,
6663 &hdev->dev_flags);
6664 else
6665 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006666 }
6667
6668 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6669
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006670 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006671 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006672
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006673 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006674 sock_put(match.sk);
6675
Johan Hedberg890ea892013-03-15 17:06:52 -05006676 hci_req_init(&req, hdev);
6677
Johan Hedberg37699722014-06-24 14:00:27 +03006678 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6679 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6680 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6681 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006682 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006683 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006684 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006685 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006686
6687 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006688}
6689
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006690void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6691{
6692 struct cmd_lookup match = { NULL, hdev };
6693 bool changed = false;
6694
6695 if (status) {
6696 u8 mgmt_err = mgmt_status(status);
6697
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006698 if (enable) {
6699 if (test_and_clear_bit(HCI_SC_ENABLED,
6700 &hdev->dev_flags))
6701 new_settings(hdev, NULL);
6702 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6703 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006704
6705 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6706 cmd_status_rsp, &mgmt_err);
6707 return;
6708 }
6709
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006710 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006711 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006712 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006713 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006714 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6715 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006716
6717 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6718 settings_rsp, &match);
6719
6720 if (changed)
6721 new_settings(hdev, match.sk);
6722
6723 if (match.sk)
6724 sock_put(match.sk);
6725}
6726
Johan Hedberg92da6092013-03-15 17:06:55 -05006727static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006728{
6729 struct cmd_lookup *match = data;
6730
Johan Hedberg90e70452012-02-23 23:09:40 +02006731 if (match->sk == NULL) {
6732 match->sk = cmd->sk;
6733 sock_hold(match->sk);
6734 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006735}
6736
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006737void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6738 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006739{
Johan Hedberg90e70452012-02-23 23:09:40 +02006740 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006741
Johan Hedberg92da6092013-03-15 17:06:55 -05006742 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6743 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6744 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006745
6746 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006747 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6748 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006749
6750 if (match.sk)
6751 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006752}
6753
Marcel Holtmann7667da32013-10-15 14:26:27 -07006754void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006755{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006756 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006757 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006758
Johan Hedberg13928972013-03-15 17:07:00 -05006759 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006760 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006761
6762 memset(&ev, 0, sizeof(ev));
6763 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006764 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006765
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006766 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006767 if (!cmd) {
6768 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006769
Johan Hedberg13928972013-03-15 17:07:00 -05006770 /* If this is a HCI command related to powering on the
6771 * HCI dev don't send any mgmt signals.
6772 */
6773 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006774 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006775 }
6776
Marcel Holtmann7667da32013-10-15 14:26:27 -07006777 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6778 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006779}
Szymon Jancc35938b2011-03-22 13:12:21 +01006780
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006781void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6782 u8 *randomizer192, u8 *hash256,
6783 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006784{
6785 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006786
Johan Hedberg744cf192011-11-08 20:40:14 +02006787 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006788
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006789 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006790 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006791 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006792
6793 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006794 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6795 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006796 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006797 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6798 hash256 && randomizer256) {
6799 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006800
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006801 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6802 memcpy(rp.randomizer192, randomizer192,
6803 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006804
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006805 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6806 memcpy(rp.randomizer256, randomizer256,
6807 sizeof(rp.randomizer256));
6808
6809 cmd_complete(cmd->sk, hdev->id,
6810 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6811 &rp, sizeof(rp));
6812 } else {
6813 struct mgmt_rp_read_local_oob_data rp;
6814
6815 memcpy(rp.hash, hash192, sizeof(rp.hash));
6816 memcpy(rp.randomizer, randomizer192,
6817 sizeof(rp.randomizer));
6818
6819 cmd_complete(cmd->sk, hdev->id,
6820 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6821 &rp, sizeof(rp));
6822 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006823 }
6824
6825 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006826}
Johan Hedberge17acd42011-03-30 23:57:16 +03006827
Marcel Holtmann901801b2013-10-06 23:55:51 -07006828void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006829 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6830 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006831{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006832 char buf[512];
6833 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006834 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006835
Johan Hedberg75ce2082014-07-02 22:42:01 +03006836 /* Don't send events for a non-kernel initiated discovery. With
6837 * LE one exception is if we have pend_le_reports > 0 in which
6838 * case we're doing passive scanning and want these events.
6839 */
6840 if (!hci_discovery_active(hdev)) {
6841 if (link_type == ACL_LINK)
6842 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006843 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006844 return;
6845 }
Andre Guedes12602d02013-04-30 15:29:40 -03006846
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006847 /* Make sure that the buffer is big enough. The 5 extra bytes
6848 * are for the potential CoD field.
6849 */
6850 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006851 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006852
Johan Hedberg1dc06092012-01-15 21:01:23 +02006853 memset(buf, 0, sizeof(buf));
6854
Johan Hedberg841c5642014-07-07 12:45:54 +03006855 bacpy(&ev->addr.bdaddr, bdaddr);
6856 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006857 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006858 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006859
Johan Hedberg1dc06092012-01-15 21:01:23 +02006860 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006861 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006862
Johan Hedberg1dc06092012-01-15 21:01:23 +02006863 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6864 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006865 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006866
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006867 if (scan_rsp_len > 0)
6868 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6869
6870 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6871 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006872
Marcel Holtmann901801b2013-10-06 23:55:51 -07006873 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006874}
Johan Hedberga88a9652011-03-30 13:18:12 +03006875
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006876void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6877 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006878{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006879 struct mgmt_ev_device_found *ev;
6880 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6881 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006882
Johan Hedbergb644ba32012-01-17 21:48:47 +02006883 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006884
Johan Hedbergb644ba32012-01-17 21:48:47 +02006885 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006886
Johan Hedbergb644ba32012-01-17 21:48:47 +02006887 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006888 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006889 ev->rssi = rssi;
6890
6891 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006892 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006893
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006894 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006895
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006896 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006897}
Johan Hedberg314b2382011-04-27 10:29:57 -04006898
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006899void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006900{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006901 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006902 struct pending_cmd *cmd;
6903
Andre Guedes343fb142011-11-22 17:14:19 -03006904 BT_DBG("%s discovering %u", hdev->name, discovering);
6905
Johan Hedberg164a6e72011-11-01 17:06:44 +02006906 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006907 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006908 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006909 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006910
6911 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006912 u8 type = hdev->discovery.type;
6913
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006914 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6915 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006916 mgmt_pending_remove(cmd);
6917 }
6918
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006919 memset(&ev, 0, sizeof(ev));
6920 ev.type = hdev->discovery.type;
6921 ev.discovering = discovering;
6922
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006923 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006924}
Antti Julku5e762442011-08-25 16:48:02 +03006925
Marcel Holtmann5976e602013-10-06 04:08:14 -07006926static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6927{
6928 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006929}
6930
6931void mgmt_reenable_advertising(struct hci_dev *hdev)
6932{
6933 struct hci_request req;
6934
Marcel Holtmann5976e602013-10-06 04:08:14 -07006935 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6936 return;
6937
6938 hci_req_init(&req, hdev);
6939 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006940 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006941}