blob: eb25a1259271968b03282a0f91deb3b507ed68f7 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200132#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
133 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
134
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135struct pending_cmd {
136 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200137 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100139 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200580 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200582
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200583 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
584 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585 settings |= MGMT_SETTING_CONFIGURATION;
586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587 return settings;
588}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200589
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200590static u32 get_current_settings(struct hci_dev *hdev)
591{
592 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200593
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200594 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100595 settings |= MGMT_SETTING_POWERED;
596
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200597 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200598 settings |= MGMT_SETTING_CONNECTABLE;
599
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500600 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
601 settings |= MGMT_SETTING_FAST_CONNECTABLE;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_DISCOVERABLE;
605
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200606 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_PAIRABLE;
608
Johan Hedberg56f87902013-10-02 13:43:13 +0300609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_BREDR;
611
Johan Hedberg06199cf2012-02-22 16:37:11 +0200612 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200614
Johan Hedberg47990ea2012-02-22 11:58:37 +0200615 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200617
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200618 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200620
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200621 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
622 settings |= MGMT_SETTING_HS;
623
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200624 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300625 settings |= MGMT_SETTING_ADVERTISING;
626
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_SECURE_CONN;
629
Johan Hedberg0663b292014-06-24 13:15:50 +0300630 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800631 settings |= MGMT_SETTING_DEBUG_KEYS;
632
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200633 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
634 settings |= MGMT_SETTING_PRIVACY;
635
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200636 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200637}
638
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300639#define PNP_INFO_SVCLASS_ID 0x1200
640
Johan Hedberg213202e2013-01-27 00:31:33 +0200641static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
642{
643 u8 *ptr = data, *uuids_start = NULL;
644 struct bt_uuid *uuid;
645
646 if (len < 4)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 u16 uuid16;
651
652 if (uuid->size != 16)
653 continue;
654
655 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
656 if (uuid16 < 0x1100)
657 continue;
658
659 if (uuid16 == PNP_INFO_SVCLASS_ID)
660 continue;
661
662 if (!uuids_start) {
663 uuids_start = ptr;
664 uuids_start[0] = 1;
665 uuids_start[1] = EIR_UUID16_ALL;
666 ptr += 2;
667 }
668
669 /* Stop if not enough space to put next UUID */
670 if ((ptr - data) + sizeof(u16) > len) {
671 uuids_start[1] = EIR_UUID16_SOME;
672 break;
673 }
674
675 *ptr++ = (uuid16 & 0x00ff);
676 *ptr++ = (uuid16 & 0xff00) >> 8;
677 uuids_start[0] += sizeof(uuid16);
678 }
679
680 return ptr;
681}
682
Johan Hedbergcdf19632013-01-27 00:31:34 +0200683static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
684{
685 u8 *ptr = data, *uuids_start = NULL;
686 struct bt_uuid *uuid;
687
688 if (len < 6)
689 return ptr;
690
691 list_for_each_entry(uuid, &hdev->uuids, list) {
692 if (uuid->size != 32)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID32_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u32) > len) {
704 uuids_start[1] = EIR_UUID32_SOME;
705 break;
706 }
707
708 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
709 ptr += sizeof(u32);
710 uuids_start[0] += sizeof(u32);
711 }
712
713 return ptr;
714}
715
Johan Hedbergc00d5752013-01-27 00:31:35 +0200716static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 18)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 128)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID128_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + 16 > len) {
737 uuids_start[1] = EIR_UUID128_SOME;
738 break;
739 }
740
741 memcpy(ptr, uuid->uuid, 16);
742 ptr += 16;
743 uuids_start[0] += 16;
744 }
745
746 return ptr;
747}
748
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300749static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
750{
751 struct pending_cmd *cmd;
752
753 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
754 if (cmd->opcode == opcode)
755 return cmd;
756 }
757
758 return NULL;
759}
760
Johan Hedberg95868422014-06-28 17:54:07 +0300761static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
762 struct hci_dev *hdev,
763 const void *data)
764{
765 struct pending_cmd *cmd;
766
767 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
768 if (cmd->user_data != data)
769 continue;
770 if (cmd->opcode == opcode)
771 return cmd;
772 }
773
774 return NULL;
775}
776
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700777static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
778{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700779 u8 ad_len = 0;
780 size_t name_len;
781
782 name_len = strlen(hdev->dev_name);
783 if (name_len > 0) {
784 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
785
786 if (name_len > max_len) {
787 name_len = max_len;
788 ptr[1] = EIR_NAME_SHORT;
789 } else
790 ptr[1] = EIR_NAME_COMPLETE;
791
792 ptr[0] = name_len + 1;
793
794 memcpy(ptr + 2, hdev->dev_name, name_len);
795
796 ad_len += (name_len + 2);
797 ptr += (name_len + 2);
798 }
799
800 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700801}
802
803static void update_scan_rsp_data(struct hci_request *req)
804{
805 struct hci_dev *hdev = req->hdev;
806 struct hci_cp_le_set_scan_rsp_data cp;
807 u8 len;
808
Johan Hedberg7751ef12013-10-19 23:38:15 +0300809 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700810 return;
811
812 memset(&cp, 0, sizeof(cp));
813
814 len = create_scan_rsp_data(hdev, cp.data);
815
Johan Hedbergeb438b52013-10-16 15:31:07 +0300816 if (hdev->scan_rsp_data_len == len &&
817 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700818 return;
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
821 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822
823 cp.length = len;
824
825 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
826}
827
Johan Hedberg9a43e252013-10-20 19:00:07 +0300828static u8 get_adv_discov_flags(struct hci_dev *hdev)
829{
830 struct pending_cmd *cmd;
831
832 /* If there's a pending mgmt command the flags will not yet have
833 * their final values, so check for this first.
834 */
835 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
836 if (cmd) {
837 struct mgmt_mode *cp = cmd->param;
838 if (cp->val == 0x01)
839 return LE_AD_GENERAL;
840 else if (cp->val == 0x02)
841 return LE_AD_LIMITED;
842 } else {
843 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_LIMITED;
845 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_GENERAL;
847 }
848
849 return 0;
850}
851
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700852static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853{
854 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberg9a43e252013-10-20 19:00:07 +0300856 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberge8340042014-01-30 11:16:50 -0800858 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
861 if (flags) {
862 BT_DBG("adv flags 0x%02x", flags);
863
864 ptr[0] = 2;
865 ptr[1] = EIR_FLAGS;
866 ptr[2] = flags;
867
868 ad_len += 3;
869 ptr += 3;
870 }
871
872 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
873 ptr[0] = 2;
874 ptr[1] = EIR_TX_POWER;
875 ptr[2] = (u8) hdev->adv_tx_power;
876
877 ad_len += 3;
878 ptr += 3;
879 }
880
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700881 return ad_len;
882}
883
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700884static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885{
886 struct hci_dev *hdev = req->hdev;
887 struct hci_cp_le_set_adv_data cp;
888 u8 len;
889
Johan Hedberg10994ce2013-10-19 23:38:16 +0300890 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891 return;
892
893 memset(&cp, 0, sizeof(cp));
894
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700895 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896
897 if (hdev->adv_data_len == len &&
898 memcmp(cp.data, hdev->adv_data, len) == 0)
899 return;
900
901 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
902 hdev->adv_data_len = len;
903
904 cp.length = len;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
907}
908
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300909int mgmt_update_adv_data(struct hci_dev *hdev)
910{
911 struct hci_request req;
912
913 hci_req_init(&req, hdev);
914 update_adv_data(&req);
915
916 return hci_req_run(&req, NULL);
917}
918
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300919static void create_eir(struct hci_dev *hdev, u8 *data)
920{
921 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300922 size_t name_len;
923
924 name_len = strlen(hdev->dev_name);
925
926 if (name_len > 0) {
927 /* EIR Data type */
928 if (name_len > 48) {
929 name_len = 48;
930 ptr[1] = EIR_NAME_SHORT;
931 } else
932 ptr[1] = EIR_NAME_COMPLETE;
933
934 /* EIR Data length */
935 ptr[0] = name_len + 1;
936
937 memcpy(ptr + 2, hdev->dev_name, name_len);
938
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300939 ptr += (name_len + 2);
940 }
941
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100942 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700943 ptr[0] = 2;
944 ptr[1] = EIR_TX_POWER;
945 ptr[2] = (u8) hdev->inq_tx_power;
946
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700947 ptr += 3;
948 }
949
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700950 if (hdev->devid_source > 0) {
951 ptr[0] = 9;
952 ptr[1] = EIR_DEVICE_ID;
953
954 put_unaligned_le16(hdev->devid_source, ptr + 2);
955 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
956 put_unaligned_le16(hdev->devid_product, ptr + 6);
957 put_unaligned_le16(hdev->devid_version, ptr + 8);
958
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700959 ptr += 10;
960 }
961
Johan Hedberg213202e2013-01-27 00:31:33 +0200962 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200963 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200964 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300965}
966
Johan Hedberg890ea892013-03-15 17:06:52 -0500967static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300968{
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970 struct hci_cp_write_eir cp;
971
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200972 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500973 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200974
Johan Hedberg976eb202012-10-24 21:12:01 +0300975 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500976 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300977
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200978 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200981 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500982 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300983
984 memset(&cp, 0, sizeof(cp));
985
986 create_eir(hdev, cp.data);
987
988 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500989 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300990
991 memcpy(hdev->eir, cp.data, sizeof(cp.data));
992
Johan Hedberg890ea892013-03-15 17:06:52 -0500993 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300994}
995
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200996static u8 get_service_classes(struct hci_dev *hdev)
997{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300998 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200999 u8 val = 0;
1000
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001001 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001002 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003
1004 return val;
1005}
1006
Johan Hedberg890ea892013-03-15 17:06:52 -05001007static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001008{
Johan Hedberg890ea892013-03-15 17:06:52 -05001009 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001010 u8 cod[3];
1011
1012 BT_DBG("%s", hdev->name);
1013
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001014 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001015 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001016
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001017 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1018 return;
1019
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001020 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
1023 cod[0] = hdev->minor_class;
1024 cod[1] = hdev->major_class;
1025 cod[2] = get_service_classes(hdev);
1026
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001027 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1028 cod[1] |= 0x20;
1029
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001031 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001032
Johan Hedberg890ea892013-03-15 17:06:52 -05001033 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001034}
1035
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037{
1038 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001039
1040 /* If there's a pending mgmt command the flag will not yet have
1041 * it's final value, so check for this first.
1042 */
1043 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1044 if (cmd) {
1045 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001046 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001047 }
1048
Johan Hedberga4858cb2014-02-25 19:56:31 +02001049 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001050}
1051
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001052static void disable_advertising(struct hci_request *req)
1053{
1054 u8 enable = 0x00;
1055
1056 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1057}
1058
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001059static void enable_advertising(struct hci_request *req)
1060{
1061 struct hci_dev *hdev = req->hdev;
1062 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001063 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001064 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001065
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001066 if (hci_conn_num(hdev, LE_LINK) > 0)
1067 return;
1068
1069 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1070 disable_advertising(req);
1071
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001072 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001073 * hci_update_random_address knows that it's safe to go ahead
1074 * and write a new random address. The flag will be set back on
1075 * as soon as the SET_ADV_ENABLE HCI command completes.
1076 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001077 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001078
Johan Hedberga4858cb2014-02-25 19:56:31 +02001079 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001080
Johan Hedberga4858cb2014-02-25 19:56:31 +02001081 /* Set require_privacy to true only when non-connectable
1082 * advertising is used. In that case it is fine to use a
1083 * non-resolvable private address.
1084 */
1085 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001086 return;
1087
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001088 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001089 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1090 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001091 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001092 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001093 cp.channel_map = hdev->le_adv_channel_map;
1094
1095 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1096
1097 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1098}
1099
Johan Hedberg7d785252011-12-15 00:47:39 +02001100static void service_cache_off(struct work_struct *work)
1101{
1102 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001103 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001104 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001105
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001106 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001107 return;
1108
Johan Hedberg890ea892013-03-15 17:06:52 -05001109 hci_req_init(&req, hdev);
1110
Johan Hedberg7d785252011-12-15 00:47:39 +02001111 hci_dev_lock(hdev);
1112
Johan Hedberg890ea892013-03-15 17:06:52 -05001113 update_eir(&req);
1114 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001115
1116 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001117
1118 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001119}
1120
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001121static void rpa_expired(struct work_struct *work)
1122{
1123 struct hci_dev *hdev = container_of(work, struct hci_dev,
1124 rpa_expired.work);
1125 struct hci_request req;
1126
1127 BT_DBG("");
1128
1129 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1130
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001131 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001132 return;
1133
1134 /* The generation of a new RPA and programming it into the
1135 * controller happens in the enable_advertising() function.
1136 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 hci_req_run(&req, NULL);
1140}
1141
Johan Hedberg6a919082012-02-28 06:17:26 +02001142static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001143{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001144 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001145 return;
1146
Johan Hedberg4f87da82012-03-02 19:55:56 +02001147 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001148 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001149
Johan Hedberg4f87da82012-03-02 19:55:56 +02001150 /* Non-mgmt controlled devices get this bit set
1151 * implicitly so that pairing works for them, however
1152 * for mgmt we require user-space to explicitly enable
1153 * it
1154 */
1155 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001156}
1157
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001158static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001159 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001160{
1161 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001162
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001163 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001164
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001165 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001166
Johan Hedberg03811012010-12-08 00:21:06 +02001167 memset(&rp, 0, sizeof(rp));
1168
Johan Hedberg03811012010-12-08 00:21:06 +02001169 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001170
1171 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001172 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001173
1174 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1175 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1176
1177 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001178
1179 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001180 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001181
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001182 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001183
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001184 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001185 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001186}
1187
1188static void mgmt_pending_free(struct pending_cmd *cmd)
1189{
1190 sock_put(cmd->sk);
1191 kfree(cmd->param);
1192 kfree(cmd);
1193}
1194
1195static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001196 struct hci_dev *hdev, void *data,
1197 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001198{
1199 struct pending_cmd *cmd;
1200
Johan Hedbergfca20012014-06-28 17:54:05 +03001201 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001202 if (!cmd)
1203 return NULL;
1204
1205 cmd->opcode = opcode;
1206 cmd->index = hdev->id;
1207
Andre Guedes12b94562012-06-07 19:05:45 -03001208 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001209 if (!cmd->param) {
1210 kfree(cmd);
1211 return NULL;
1212 }
1213
1214 if (data)
1215 memcpy(cmd->param, data, len);
1216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberge6fe7982013-10-02 15:45:22 +03001475static u8 mgmt_bredr_support(struct hci_dev *hdev)
1476{
1477 if (!lmp_bredr_capable(hdev))
1478 return MGMT_STATUS_NOT_SUPPORTED;
1479 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1480 return MGMT_STATUS_REJECTED;
1481 else
1482 return MGMT_STATUS_SUCCESS;
1483}
1484
1485static u8 mgmt_le_support(struct hci_dev *hdev)
1486{
1487 if (!lmp_le_capable(hdev))
1488 return MGMT_STATUS_NOT_SUPPORTED;
1489 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1490 return MGMT_STATUS_REJECTED;
1491 else
1492 return MGMT_STATUS_SUCCESS;
1493}
1494
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001495static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1496{
1497 struct pending_cmd *cmd;
1498 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001499 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001500 bool changed;
1501
1502 BT_DBG("status 0x%02x", status);
1503
1504 hci_dev_lock(hdev);
1505
1506 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1507 if (!cmd)
1508 goto unlock;
1509
1510 if (status) {
1511 u8 mgmt_err = mgmt_status(status);
1512 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001513 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001514 goto remove_cmd;
1515 }
1516
1517 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001518 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001519 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1520 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001521
1522 if (hdev->discov_timeout > 0) {
1523 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1524 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1525 to);
1526 }
1527 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001528 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1529 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001530 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001531
1532 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1533
1534 if (changed)
1535 new_settings(hdev, cmd->sk);
1536
Marcel Holtmann970ba522013-10-15 06:33:57 -07001537 /* When the discoverable mode gets changed, make sure
1538 * that class of device has the limited discoverable
1539 * bit correctly set.
1540 */
1541 hci_req_init(&req, hdev);
1542 update_class(&req);
1543 hci_req_run(&req, NULL);
1544
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545remove_cmd:
1546 mgmt_pending_remove(cmd);
1547
1548unlock:
1549 hci_dev_unlock(hdev);
1550}
1551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001552static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001553 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001554{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001555 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001556 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001558 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001559 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001560 int err;
1561
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001562 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001563
Johan Hedberg9a43e252013-10-20 19:00:07 +03001564 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1565 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001566 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001567 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001568
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001569 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1571 MGMT_STATUS_INVALID_PARAMS);
1572
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001573 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001574
1575 /* Disabling discoverable requires that no timeout is set,
1576 * and enabling limited discoverable requires a timeout.
1577 */
1578 if ((cp->val == 0x00 && timeout > 0) ||
1579 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001582
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001583 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001584
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001585 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001586 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001587 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001588 goto failed;
1589 }
1590
1591 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001592 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001593 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001594 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001595 goto failed;
1596 }
1597
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001598 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001599 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001600 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001601 goto failed;
1602 }
1603
1604 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001605 bool changed = false;
1606
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001607 /* Setting limited discoverable when powered off is
1608 * not a valid operation since it requires a timeout
1609 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1610 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001611 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1612 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1613 changed = true;
1614 }
1615
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001616 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001617 if (err < 0)
1618 goto failed;
1619
1620 if (changed)
1621 err = new_settings(hdev, sk);
1622
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001623 goto failed;
1624 }
1625
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001626 /* If the current mode is the same, then just update the timeout
1627 * value with the new value. And if only the timeout gets updated,
1628 * then no need for any HCI transactions.
1629 */
1630 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1631 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1632 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001633 cancel_delayed_work(&hdev->discov_off);
1634 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001635
Marcel Holtmann36261542013-10-15 08:28:51 -07001636 if (cp->val && hdev->discov_timeout > 0) {
1637 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001638 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001639 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001640 }
1641
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001642 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001643 goto failed;
1644 }
1645
1646 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1647 if (!cmd) {
1648 err = -ENOMEM;
1649 goto failed;
1650 }
1651
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001652 /* Cancel any potential discoverable timeout that might be
1653 * still active and store new timeout value. The arming of
1654 * the timeout happens in the complete handler.
1655 */
1656 cancel_delayed_work(&hdev->discov_off);
1657 hdev->discov_timeout = timeout;
1658
Johan Hedbergb456f872013-10-19 23:38:22 +03001659 /* Limited discoverable mode */
1660 if (cp->val == 0x02)
1661 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1662 else
1663 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1664
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001665 hci_req_init(&req, hdev);
1666
Johan Hedberg9a43e252013-10-20 19:00:07 +03001667 /* The procedure for LE-only controllers is much simpler - just
1668 * update the advertising data.
1669 */
1670 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1671 goto update_ad;
1672
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001673 scan = SCAN_PAGE;
1674
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001675 if (cp->val) {
1676 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001677
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001678 if (cp->val == 0x02) {
1679 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001680 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001681 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1682 hci_cp.iac_lap[1] = 0x8b;
1683 hci_cp.iac_lap[2] = 0x9e;
1684 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1685 hci_cp.iac_lap[4] = 0x8b;
1686 hci_cp.iac_lap[5] = 0x9e;
1687 } else {
1688 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001689 hci_cp.num_iac = 1;
1690 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1691 hci_cp.iac_lap[1] = 0x8b;
1692 hci_cp.iac_lap[2] = 0x9e;
1693 }
1694
1695 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1696 (hci_cp.num_iac * 3) + 1, &hci_cp);
1697
1698 scan |= SCAN_INQUIRY;
1699 } else {
1700 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1701 }
1702
1703 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001704
Johan Hedberg9a43e252013-10-20 19:00:07 +03001705update_ad:
1706 update_adv_data(&req);
1707
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001708 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001709 if (err < 0)
1710 mgmt_pending_remove(cmd);
1711
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001712failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001713 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001714 return err;
1715}
1716
Johan Hedberg406d7802013-03-15 17:07:09 -05001717static void write_fast_connectable(struct hci_request *req, bool enable)
1718{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001719 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001720 struct hci_cp_write_page_scan_activity acp;
1721 u8 type;
1722
Johan Hedberg547003b2013-10-21 16:51:53 +03001723 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1724 return;
1725
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001726 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1727 return;
1728
Johan Hedberg406d7802013-03-15 17:07:09 -05001729 if (enable) {
1730 type = PAGE_SCAN_TYPE_INTERLACED;
1731
1732 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001733 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001734 } else {
1735 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1736
1737 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001738 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001739 }
1740
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001741 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001742
Johan Hedbergbd98b992013-03-15 17:07:13 -05001743 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1744 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1745 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1746 sizeof(acp), &acp);
1747
1748 if (hdev->page_scan_type != type)
1749 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001750}
1751
Johan Hedberg2b76f452013-03-15 17:07:04 -05001752static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1753{
1754 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001755 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001756 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001757
1758 BT_DBG("status 0x%02x", status);
1759
1760 hci_dev_lock(hdev);
1761
1762 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1763 if (!cmd)
1764 goto unlock;
1765
Johan Hedberg37438c12013-10-14 16:20:05 +03001766 if (status) {
1767 u8 mgmt_err = mgmt_status(status);
1768 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1769 goto remove_cmd;
1770 }
1771
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001772 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001773 if (cp->val) {
1774 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1775 &hdev->dev_flags);
1776 discov_changed = false;
1777 } else {
1778 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1779 &hdev->dev_flags);
1780 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1781 &hdev->dev_flags);
1782 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783
Johan Hedberg2b76f452013-03-15 17:07:04 -05001784 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1785
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001786 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001787 new_settings(hdev, cmd->sk);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001788 if (discov_changed)
1789 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001790 hci_update_background_scan(hdev);
1791 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001792
Johan Hedberg37438c12013-10-14 16:20:05 +03001793remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001794 mgmt_pending_remove(cmd);
1795
1796unlock:
1797 hci_dev_unlock(hdev);
1798}
1799
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001800static int set_connectable_update_settings(struct hci_dev *hdev,
1801 struct sock *sk, u8 val)
1802{
1803 bool changed = false;
1804 int err;
1805
1806 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1807 changed = true;
1808
1809 if (val) {
1810 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1811 } else {
1812 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1813 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1814 }
1815
1816 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1817 if (err < 0)
1818 return err;
1819
Johan Hedberg562064e2014-07-08 16:35:34 +03001820 if (changed) {
1821 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001822 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001823 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001824
1825 return 0;
1826}
1827
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001828static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001829 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001830{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001831 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001832 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001833 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001834 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001835 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001836
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001837 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001838
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001839 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1840 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001841 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001842 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001843
Johan Hedberga7e80f22013-01-09 16:05:19 +02001844 if (cp->val != 0x00 && cp->val != 0x01)
1845 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1846 MGMT_STATUS_INVALID_PARAMS);
1847
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001848 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001849
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001850 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001851 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001852 goto failed;
1853 }
1854
1855 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001856 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001857 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001858 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001859 goto failed;
1860 }
1861
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001862 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1863 if (!cmd) {
1864 err = -ENOMEM;
1865 goto failed;
1866 }
1867
Johan Hedberg2b76f452013-03-15 17:07:04 -05001868 hci_req_init(&req, hdev);
1869
Johan Hedberg9a43e252013-10-20 19:00:07 +03001870 /* If BR/EDR is not enabled and we disable advertising as a
1871 * by-product of disabling connectable, we need to update the
1872 * advertising flags.
1873 */
1874 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1875 if (!cp->val) {
1876 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1877 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1878 }
1879 update_adv_data(&req);
1880 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001881 if (cp->val) {
1882 scan = SCAN_PAGE;
1883 } else {
1884 scan = 0;
1885
1886 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001887 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001888 cancel_delayed_work(&hdev->discov_off);
1889 }
1890
1891 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1892 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001893
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001894 /* If we're going from non-connectable to connectable or
1895 * vice-versa when fast connectable is enabled ensure that fast
1896 * connectable gets disabled. write_fast_connectable won't do
1897 * anything if the page scan parameters are already what they
1898 * should be.
1899 */
1900 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001901 write_fast_connectable(&req, false);
1902
Johan Hedberge8b12022014-07-10 10:51:27 +03001903 /* Update the advertising parameters if necessary */
1904 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001905 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001906
Johan Hedberg2b76f452013-03-15 17:07:04 -05001907 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001908 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001909 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001910 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001911 err = set_connectable_update_settings(hdev, sk,
1912 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001913 goto failed;
1914 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001915
1916failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001917 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001918 return err;
1919}
1920
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001921static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001922 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001923{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001924 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001925 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001926 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001927
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001928 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001929
Johan Hedberga7e80f22013-01-09 16:05:19 +02001930 if (cp->val != 0x00 && cp->val != 0x01)
1931 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1932 MGMT_STATUS_INVALID_PARAMS);
1933
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001934 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001935
1936 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001937 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001938 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001939 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001940
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001941 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001942 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001943 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001944
Marcel Holtmann55594352013-10-06 16:11:57 -07001945 if (changed)
1946 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001947
Marcel Holtmann55594352013-10-06 16:11:57 -07001948unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001949 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001950 return err;
1951}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001952
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001953static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1954 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001955{
1956 struct mgmt_mode *cp = data;
1957 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001958 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001959 int err;
1960
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001961 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001962
Johan Hedberge6fe7982013-10-02 15:45:22 +03001963 status = mgmt_bredr_support(hdev);
1964 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001965 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001966 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001967
Johan Hedberga7e80f22013-01-09 16:05:19 +02001968 if (cp->val != 0x00 && cp->val != 0x01)
1969 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1970 MGMT_STATUS_INVALID_PARAMS);
1971
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001972 hci_dev_lock(hdev);
1973
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001974 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001975 bool changed = false;
1976
1977 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001978 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001979 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1980 changed = true;
1981 }
1982
1983 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1984 if (err < 0)
1985 goto failed;
1986
1987 if (changed)
1988 err = new_settings(hdev, sk);
1989
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001990 goto failed;
1991 }
1992
1993 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001994 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001995 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001996 goto failed;
1997 }
1998
1999 val = !!cp->val;
2000
2001 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2002 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2003 goto failed;
2004 }
2005
2006 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2007 if (!cmd) {
2008 err = -ENOMEM;
2009 goto failed;
2010 }
2011
2012 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2013 if (err < 0) {
2014 mgmt_pending_remove(cmd);
2015 goto failed;
2016 }
2017
2018failed:
2019 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002020 return err;
2021}
2022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002023static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002024{
2025 struct mgmt_mode *cp = data;
2026 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002027 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002028 int err;
2029
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002030 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002031
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002032 status = mgmt_bredr_support(hdev);
2033 if (status)
2034 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2035
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002036 if (!lmp_ssp_capable(hdev))
2037 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2038 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002039
Johan Hedberga7e80f22013-01-09 16:05:19 +02002040 if (cp->val != 0x00 && cp->val != 0x01)
2041 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2042 MGMT_STATUS_INVALID_PARAMS);
2043
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002044 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002045
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002046 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002047 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002048
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002049 if (cp->val) {
2050 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2051 &hdev->dev_flags);
2052 } else {
2053 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2054 &hdev->dev_flags);
2055 if (!changed)
2056 changed = test_and_clear_bit(HCI_HS_ENABLED,
2057 &hdev->dev_flags);
2058 else
2059 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002060 }
2061
2062 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2063 if (err < 0)
2064 goto failed;
2065
2066 if (changed)
2067 err = new_settings(hdev, sk);
2068
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002069 goto failed;
2070 }
2071
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002072 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2073 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002074 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2075 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002076 goto failed;
2077 }
2078
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002079 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002080 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2081 goto failed;
2082 }
2083
2084 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2085 if (!cmd) {
2086 err = -ENOMEM;
2087 goto failed;
2088 }
2089
Johan Hedberg37699722014-06-24 14:00:27 +03002090 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2091 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2092 sizeof(cp->val), &cp->val);
2093
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002094 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002095 if (err < 0) {
2096 mgmt_pending_remove(cmd);
2097 goto failed;
2098 }
2099
2100failed:
2101 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002102 return err;
2103}
2104
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002105static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002106{
2107 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002108 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002109 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002110 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002111
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002112 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002113
Johan Hedberge6fe7982013-10-02 15:45:22 +03002114 status = mgmt_bredr_support(hdev);
2115 if (status)
2116 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002117
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002118 if (!lmp_ssp_capable(hdev))
2119 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2120 MGMT_STATUS_NOT_SUPPORTED);
2121
2122 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2123 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2124 MGMT_STATUS_REJECTED);
2125
Johan Hedberga7e80f22013-01-09 16:05:19 +02002126 if (cp->val != 0x00 && cp->val != 0x01)
2127 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2128 MGMT_STATUS_INVALID_PARAMS);
2129
Marcel Holtmannee392692013-10-01 22:59:23 -07002130 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002131
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002132 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002133 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002134 } else {
2135 if (hdev_is_powered(hdev)) {
2136 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2137 MGMT_STATUS_REJECTED);
2138 goto unlock;
2139 }
2140
Marcel Holtmannee392692013-10-01 22:59:23 -07002141 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002142 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002143
2144 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2145 if (err < 0)
2146 goto unlock;
2147
2148 if (changed)
2149 err = new_settings(hdev, sk);
2150
2151unlock:
2152 hci_dev_unlock(hdev);
2153 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002154}
2155
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002156static void le_enable_complete(struct hci_dev *hdev, u8 status)
2157{
2158 struct cmd_lookup match = { NULL, hdev };
2159
2160 if (status) {
2161 u8 mgmt_err = mgmt_status(status);
2162
2163 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2164 &mgmt_err);
2165 return;
2166 }
2167
2168 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2169
2170 new_settings(hdev, match.sk);
2171
2172 if (match.sk)
2173 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002174
2175 /* Make sure the controller has a good default for
2176 * advertising data. Restrict the update to when LE
2177 * has actually been enabled. During power on, the
2178 * update in powered_update_hci will take care of it.
2179 */
2180 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2181 struct hci_request req;
2182
2183 hci_dev_lock(hdev);
2184
2185 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002186 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002187 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002188 hci_req_run(&req, NULL);
2189
Johan Hedberga70f4b52014-07-07 15:19:50 +03002190 hci_update_background_scan(hdev);
2191
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002192 hci_dev_unlock(hdev);
2193 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002194}
2195
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002196static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002197{
2198 struct mgmt_mode *cp = data;
2199 struct hci_cp_write_le_host_supported hci_cp;
2200 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002201 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002202 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002203 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002204
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002205 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002206
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002207 if (!lmp_le_capable(hdev))
2208 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2209 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002210
Johan Hedberga7e80f22013-01-09 16:05:19 +02002211 if (cp->val != 0x00 && cp->val != 0x01)
2212 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2213 MGMT_STATUS_INVALID_PARAMS);
2214
Johan Hedbergc73eee92013-04-19 18:35:21 +03002215 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002216 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002217 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2218 MGMT_STATUS_REJECTED);
2219
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002220 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002221
2222 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002223 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002224
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002225 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002226 bool changed = false;
2227
2228 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2229 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2230 changed = true;
2231 }
2232
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002233 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2234 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002235 changed = true;
2236 }
2237
Johan Hedberg06199cf2012-02-22 16:37:11 +02002238 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2239 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002240 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002241
2242 if (changed)
2243 err = new_settings(hdev, sk);
2244
Johan Hedberg1de028c2012-02-29 19:55:35 -08002245 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246 }
2247
Johan Hedberg4375f102013-09-25 13:26:10 +03002248 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2249 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002250 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002251 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002252 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002253 }
2254
2255 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2256 if (!cmd) {
2257 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002258 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002259 }
2260
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002261 hci_req_init(&req, hdev);
2262
Johan Hedberg06199cf2012-02-22 16:37:11 +02002263 memset(&hci_cp, 0, sizeof(hci_cp));
2264
2265 if (val) {
2266 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002267 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002268 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002269 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002270 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002271 }
2272
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002273 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2274 &hci_cp);
2275
2276 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302277 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002278 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002279
Johan Hedberg1de028c2012-02-29 19:55:35 -08002280unlock:
2281 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002282 return err;
2283}
2284
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002285/* This is a helper function to test for pending mgmt commands that can
2286 * cause CoD or EIR HCI commands. We can only allow one such pending
2287 * mgmt command at a time since otherwise we cannot easily track what
2288 * the current values are, will be, and based on that calculate if a new
2289 * HCI command needs to be sent and if yes with what value.
2290 */
2291static bool pending_eir_or_class(struct hci_dev *hdev)
2292{
2293 struct pending_cmd *cmd;
2294
2295 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2296 switch (cmd->opcode) {
2297 case MGMT_OP_ADD_UUID:
2298 case MGMT_OP_REMOVE_UUID:
2299 case MGMT_OP_SET_DEV_CLASS:
2300 case MGMT_OP_SET_POWERED:
2301 return true;
2302 }
2303 }
2304
2305 return false;
2306}
2307
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002308static const u8 bluetooth_base_uuid[] = {
2309 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2310 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2311};
2312
2313static u8 get_uuid_size(const u8 *uuid)
2314{
2315 u32 val;
2316
2317 if (memcmp(uuid, bluetooth_base_uuid, 12))
2318 return 128;
2319
2320 val = get_unaligned_le32(&uuid[12]);
2321 if (val > 0xffff)
2322 return 32;
2323
2324 return 16;
2325}
2326
Johan Hedberg92da6092013-03-15 17:06:55 -05002327static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2328{
2329 struct pending_cmd *cmd;
2330
2331 hci_dev_lock(hdev);
2332
2333 cmd = mgmt_pending_find(mgmt_op, hdev);
2334 if (!cmd)
2335 goto unlock;
2336
2337 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2338 hdev->dev_class, 3);
2339
2340 mgmt_pending_remove(cmd);
2341
2342unlock:
2343 hci_dev_unlock(hdev);
2344}
2345
2346static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2347{
2348 BT_DBG("status 0x%02x", status);
2349
2350 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2351}
2352
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002353static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002354{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002355 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002356 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002357 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002358 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002359 int err;
2360
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002361 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002362
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002363 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002364
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002365 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002366 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002367 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002368 goto failed;
2369 }
2370
Andre Guedes92c4c202012-06-07 19:05:44 -03002371 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002372 if (!uuid) {
2373 err = -ENOMEM;
2374 goto failed;
2375 }
2376
2377 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002378 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002379 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002380
Johan Hedbergde66aa62013-01-27 00:31:27 +02002381 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002382
Johan Hedberg890ea892013-03-15 17:06:52 -05002383 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002384
Johan Hedberg890ea892013-03-15 17:06:52 -05002385 update_class(&req);
2386 update_eir(&req);
2387
Johan Hedberg92da6092013-03-15 17:06:55 -05002388 err = hci_req_run(&req, add_uuid_complete);
2389 if (err < 0) {
2390 if (err != -ENODATA)
2391 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002392
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002393 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002394 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002395 goto failed;
2396 }
2397
2398 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002399 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002400 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002401 goto failed;
2402 }
2403
2404 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002405
2406failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002407 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002408 return err;
2409}
2410
Johan Hedberg24b78d02012-02-23 23:24:30 +02002411static bool enable_service_cache(struct hci_dev *hdev)
2412{
2413 if (!hdev_is_powered(hdev))
2414 return false;
2415
2416 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002417 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2418 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002419 return true;
2420 }
2421
2422 return false;
2423}
2424
Johan Hedberg92da6092013-03-15 17:06:55 -05002425static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2426{
2427 BT_DBG("status 0x%02x", status);
2428
2429 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2430}
2431
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002432static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002433 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002434{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002435 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002436 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002437 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002438 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 -05002439 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002440 int err, found;
2441
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002442 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002443
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002444 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002445
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002446 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002447 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002448 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002449 goto unlock;
2450 }
2451
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002452 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002453 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002454
Johan Hedberg24b78d02012-02-23 23:24:30 +02002455 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002456 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002457 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002458 goto unlock;
2459 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002460
Johan Hedberg9246a862012-02-23 21:33:16 +02002461 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002462 }
2463
2464 found = 0;
2465
Johan Hedberg056341c2013-01-27 00:31:30 +02002466 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002467 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2468 continue;
2469
2470 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002471 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002472 found++;
2473 }
2474
2475 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002476 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002477 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002478 goto unlock;
2479 }
2480
Johan Hedberg9246a862012-02-23 21:33:16 +02002481update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002482 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002483
Johan Hedberg890ea892013-03-15 17:06:52 -05002484 update_class(&req);
2485 update_eir(&req);
2486
Johan Hedberg92da6092013-03-15 17:06:55 -05002487 err = hci_req_run(&req, remove_uuid_complete);
2488 if (err < 0) {
2489 if (err != -ENODATA)
2490 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002491
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002492 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002493 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002494 goto unlock;
2495 }
2496
2497 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002498 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002499 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002500 goto unlock;
2501 }
2502
2503 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002504
2505unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002506 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002507 return err;
2508}
2509
Johan Hedberg92da6092013-03-15 17:06:55 -05002510static void set_class_complete(struct hci_dev *hdev, u8 status)
2511{
2512 BT_DBG("status 0x%02x", status);
2513
2514 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2515}
2516
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002517static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002518 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002519{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002520 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002521 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002522 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002523 int err;
2524
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002525 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002526
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002527 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002528 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2529 MGMT_STATUS_NOT_SUPPORTED);
2530
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002531 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002532
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002533 if (pending_eir_or_class(hdev)) {
2534 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2535 MGMT_STATUS_BUSY);
2536 goto unlock;
2537 }
2538
2539 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2540 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2541 MGMT_STATUS_INVALID_PARAMS);
2542 goto unlock;
2543 }
2544
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002545 hdev->major_class = cp->major;
2546 hdev->minor_class = cp->minor;
2547
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002548 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002549 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002550 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002551 goto unlock;
2552 }
2553
Johan Hedberg890ea892013-03-15 17:06:52 -05002554 hci_req_init(&req, hdev);
2555
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002556 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002557 hci_dev_unlock(hdev);
2558 cancel_delayed_work_sync(&hdev->service_cache);
2559 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002560 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002561 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002562
Johan Hedberg890ea892013-03-15 17:06:52 -05002563 update_class(&req);
2564
Johan Hedberg92da6092013-03-15 17:06:55 -05002565 err = hci_req_run(&req, set_class_complete);
2566 if (err < 0) {
2567 if (err != -ENODATA)
2568 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002569
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002570 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002571 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002572 goto unlock;
2573 }
2574
2575 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002576 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002577 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002578 goto unlock;
2579 }
2580
2581 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002582
Johan Hedbergb5235a62012-02-21 14:32:24 +02002583unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002584 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002585 return err;
2586}
2587
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002588static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002589 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002590{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002591 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002592 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2593 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002594 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002595 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002596 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002597
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002598 BT_DBG("request for %s", hdev->name);
2599
2600 if (!lmp_bredr_capable(hdev))
2601 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2602 MGMT_STATUS_NOT_SUPPORTED);
2603
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002604 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002605 if (key_count > max_key_count) {
2606 BT_ERR("load_link_keys: too big key_count value %u",
2607 key_count);
2608 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2609 MGMT_STATUS_INVALID_PARAMS);
2610 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002611
Johan Hedberg86742e12011-11-07 23:13:38 +02002612 expected_len = sizeof(*cp) + key_count *
2613 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002614 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002615 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002616 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002617 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002618 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002619 }
2620
Johan Hedberg4ae14302013-01-20 14:27:13 +02002621 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2622 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2623 MGMT_STATUS_INVALID_PARAMS);
2624
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002625 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002626 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002627
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002628 for (i = 0; i < key_count; i++) {
2629 struct mgmt_link_key_info *key = &cp->keys[i];
2630
Marcel Holtmann8e991132014-01-10 02:07:25 -08002631 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002632 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2633 MGMT_STATUS_INVALID_PARAMS);
2634 }
2635
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002636 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002637
2638 hci_link_keys_clear(hdev);
2639
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002640 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002641 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2642 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002643 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002644 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2645 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002646
2647 if (changed)
2648 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002649
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002650 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002651 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002652
Johan Hedberg58e92932014-06-24 14:00:26 +03002653 /* Always ignore debug keys and require a new pairing if
2654 * the user wants to use them.
2655 */
2656 if (key->type == HCI_LK_DEBUG_COMBINATION)
2657 continue;
2658
Johan Hedberg7652ff62014-06-24 13:15:49 +03002659 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2660 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661 }
2662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002663 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002664
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002665 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002666
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002667 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002668}
2669
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002670static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002671 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002672{
2673 struct mgmt_ev_device_unpaired ev;
2674
2675 bacpy(&ev.addr.bdaddr, bdaddr);
2676 ev.addr.type = addr_type;
2677
2678 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002679 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002680}
2681
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002682static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002683 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002684{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002685 struct mgmt_cp_unpair_device *cp = data;
2686 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002687 struct hci_cp_disconnect dc;
2688 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002689 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002690 int err;
2691
Johan Hedberga8a1d192011-11-10 15:54:38 +02002692 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002693 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2694 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002695
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002696 if (!bdaddr_type_is_valid(cp->addr.type))
2697 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2698 MGMT_STATUS_INVALID_PARAMS,
2699 &rp, sizeof(rp));
2700
Johan Hedberg118da702013-01-20 14:27:20 +02002701 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2702 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2703 MGMT_STATUS_INVALID_PARAMS,
2704 &rp, sizeof(rp));
2705
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002706 hci_dev_lock(hdev);
2707
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002708 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002709 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002710 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002711 goto unlock;
2712 }
2713
Johan Hedberge0b2b272014-02-18 17:14:31 +02002714 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002715 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002716 } else {
2717 u8 addr_type;
2718
2719 if (cp->addr.type == BDADDR_LE_PUBLIC)
2720 addr_type = ADDR_LE_DEV_PUBLIC;
2721 else
2722 addr_type = ADDR_LE_DEV_RANDOM;
2723
Johan Hedberga7ec7332014-02-18 17:14:35 +02002724 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2725
Andre Guedesa9b0a042014-02-26 20:21:52 -03002726 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2727
Johan Hedberge0b2b272014-02-18 17:14:31 +02002728 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2729 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002730
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002731 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002732 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002733 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002734 goto unlock;
2735 }
2736
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002737 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002738 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002739 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002740 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002741 else
2742 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002743 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002744 } else {
2745 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002746 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002747
Johan Hedberga8a1d192011-11-10 15:54:38 +02002748 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002749 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002750 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002751 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002752 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002753 }
2754
Johan Hedberg124f6e32012-02-09 13:50:12 +02002755 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002757 if (!cmd) {
2758 err = -ENOMEM;
2759 goto unlock;
2760 }
2761
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002762 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002763 dc.reason = 0x13; /* Remote User Terminated Connection */
2764 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2765 if (err < 0)
2766 mgmt_pending_remove(cmd);
2767
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002768unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002769 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002770 return err;
2771}
2772
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002773static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002774 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002775{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002776 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002777 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002778 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002779 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002780 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002781 int err;
2782
2783 BT_DBG("");
2784
Johan Hedberg06a63b12013-01-20 14:27:21 +02002785 memset(&rp, 0, sizeof(rp));
2786 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2787 rp.addr.type = cp->addr.type;
2788
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002789 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002790 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2791 MGMT_STATUS_INVALID_PARAMS,
2792 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002793
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002794 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002795
2796 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002797 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2798 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002799 goto failed;
2800 }
2801
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002802 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002803 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2804 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002805 goto failed;
2806 }
2807
Andre Guedes591f47f2012-04-24 21:02:49 -03002808 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002809 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2810 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002811 else
2812 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002813
Vishal Agarwalf9607272012-06-13 05:32:43 +05302814 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002815 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2816 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002817 goto failed;
2818 }
2819
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002820 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002821 if (!cmd) {
2822 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002823 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002824 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002825
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002826 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002827 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002828
2829 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2830 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002831 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002832
2833failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002834 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002835 return err;
2836}
2837
Andre Guedes57c14772012-04-24 21:02:50 -03002838static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002839{
2840 switch (link_type) {
2841 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002842 switch (addr_type) {
2843 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002844 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002845
Johan Hedberg48264f02011-11-09 13:58:58 +02002846 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002847 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002848 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002849 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002850
Johan Hedberg4c659c32011-11-07 23:13:39 +02002851 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002852 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002853 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002854 }
2855}
2856
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002857static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2858 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002859{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002860 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002861 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002862 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002863 int err;
2864 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002865
2866 BT_DBG("");
2867
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002868 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002869
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002870 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002871 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002872 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002873 goto unlock;
2874 }
2875
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002876 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002877 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2878 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002879 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002880 }
2881
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002882 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002883 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002884 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002885 err = -ENOMEM;
2886 goto unlock;
2887 }
2888
Johan Hedberg2784eb42011-01-21 13:56:35 +02002889 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002890 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002891 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2892 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002893 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002894 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002895 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002896 continue;
2897 i++;
2898 }
2899
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002900 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002901
Johan Hedberg4c659c32011-11-07 23:13:39 +02002902 /* Recalculate length in case of filtered SCO connections, etc */
2903 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002904
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002905 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002906 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002907
Johan Hedberga38528f2011-01-22 06:46:43 +02002908 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002909
2910unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002911 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002912 return err;
2913}
2914
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002915static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002916 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002917{
2918 struct pending_cmd *cmd;
2919 int err;
2920
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002921 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002922 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002923 if (!cmd)
2924 return -ENOMEM;
2925
Johan Hedbergd8457692012-02-17 14:24:57 +02002926 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002927 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002928 if (err < 0)
2929 mgmt_pending_remove(cmd);
2930
2931 return err;
2932}
2933
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002934static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002935 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002936{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002937 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002938 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002939 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002940 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002941 int err;
2942
2943 BT_DBG("");
2944
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002945 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002946
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002947 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002948 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002949 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002950 goto failed;
2951 }
2952
Johan Hedbergd8457692012-02-17 14:24:57 +02002953 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002954 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002955 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002956 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002957 goto failed;
2958 }
2959
2960 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002961 struct mgmt_cp_pin_code_neg_reply ncp;
2962
2963 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002964
2965 BT_ERR("PIN code is not 16 bytes long");
2966
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002967 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002968 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002969 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002970 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002971
2972 goto failed;
2973 }
2974
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002975 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002976 if (!cmd) {
2977 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002978 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002979 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002980
Johan Hedbergd8457692012-02-17 14:24:57 +02002981 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002982 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002983 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002984
2985 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2986 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002987 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002988
2989failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002990 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002991 return err;
2992}
2993
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002994static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2995 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002996{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002997 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002998
2999 BT_DBG("");
3000
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003001 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3002 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3003 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3004
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003005 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003006
3007 hdev->io_capability = cp->io_capability;
3008
3009 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003010 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003011
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003012 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003013
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003014 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3015 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003016}
3017
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003018static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003019{
3020 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003021 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003022
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003023 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003024 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3025 continue;
3026
Johan Hedberge9a416b2011-02-19 12:05:56 -03003027 if (cmd->user_data != conn)
3028 continue;
3029
3030 return cmd;
3031 }
3032
3033 return NULL;
3034}
3035
3036static void pairing_complete(struct pending_cmd *cmd, u8 status)
3037{
3038 struct mgmt_rp_pair_device rp;
3039 struct hci_conn *conn = cmd->user_data;
3040
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003041 bacpy(&rp.addr.bdaddr, &conn->dst);
3042 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003043
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003044 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003045 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003046
3047 /* So we don't get further callbacks for this connection */
3048 conn->connect_cfm_cb = NULL;
3049 conn->security_cfm_cb = NULL;
3050 conn->disconn_cfm_cb = NULL;
3051
David Herrmann76a68ba2013-04-06 20:28:37 +02003052 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003053
Johan Hedberga664b5b2011-02-19 12:06:02 -03003054 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003055}
3056
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003057void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3058{
3059 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3060 struct pending_cmd *cmd;
3061
3062 cmd = find_pairing(conn);
3063 if (cmd)
3064 pairing_complete(cmd, status);
3065}
3066
Johan Hedberge9a416b2011-02-19 12:05:56 -03003067static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3068{
3069 struct pending_cmd *cmd;
3070
3071 BT_DBG("status %u", status);
3072
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003073 cmd = find_pairing(conn);
3074 if (!cmd)
3075 BT_DBG("Unable to find a pending command");
3076 else
Johan Hedberge2113262012-02-18 15:20:03 +02003077 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003078}
3079
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003080static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303081{
3082 struct pending_cmd *cmd;
3083
3084 BT_DBG("status %u", status);
3085
3086 if (!status)
3087 return;
3088
3089 cmd = find_pairing(conn);
3090 if (!cmd)
3091 BT_DBG("Unable to find a pending command");
3092 else
3093 pairing_complete(cmd, mgmt_status(status));
3094}
3095
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003096static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003097 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003098{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003099 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003100 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003101 struct pending_cmd *cmd;
3102 u8 sec_level, auth_type;
3103 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003104 int err;
3105
3106 BT_DBG("");
3107
Szymon Jancf950a30e2013-01-18 12:48:07 +01003108 memset(&rp, 0, sizeof(rp));
3109 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3110 rp.addr.type = cp->addr.type;
3111
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003112 if (!bdaddr_type_is_valid(cp->addr.type))
3113 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3114 MGMT_STATUS_INVALID_PARAMS,
3115 &rp, sizeof(rp));
3116
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003117 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3118 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3119 MGMT_STATUS_INVALID_PARAMS,
3120 &rp, sizeof(rp));
3121
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003122 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003123
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003124 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003125 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3126 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003127 goto unlock;
3128 }
3129
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003130 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003131 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003132
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003133 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003134 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3135 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003136 } else {
3137 u8 addr_type;
3138
3139 /* Convert from L2CAP channel address type to HCI address type
3140 */
3141 if (cp->addr.type == BDADDR_LE_PUBLIC)
3142 addr_type = ADDR_LE_DEV_PUBLIC;
3143 else
3144 addr_type = ADDR_LE_DEV_RANDOM;
3145
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003146 /* When pairing a new device, it is expected to remember
3147 * this device for future connections. Adding the connection
3148 * parameter information ahead of time allows tracking
3149 * of the slave preferred values and will speed up any
3150 * further connection establishment.
3151 *
3152 * If connection parameters already exist, then they
3153 * will be kept and this function does nothing.
3154 */
3155 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3156
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003157 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003158 sec_level, HCI_LE_CONN_TIMEOUT,
3159 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003160 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003161
Ville Tervo30e76272011-02-22 16:10:53 -03003162 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003163 int status;
3164
3165 if (PTR_ERR(conn) == -EBUSY)
3166 status = MGMT_STATUS_BUSY;
3167 else
3168 status = MGMT_STATUS_CONNECT_FAILED;
3169
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003170 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003171 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003172 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003173 goto unlock;
3174 }
3175
3176 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003177 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003178 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003179 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003180 goto unlock;
3181 }
3182
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003183 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003184 if (!cmd) {
3185 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003186 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003187 goto unlock;
3188 }
3189
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003190 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003191 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003192 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003193 conn->security_cfm_cb = pairing_complete_cb;
3194 conn->disconn_cfm_cb = pairing_complete_cb;
3195 } else {
3196 conn->connect_cfm_cb = le_pairing_complete_cb;
3197 conn->security_cfm_cb = le_pairing_complete_cb;
3198 conn->disconn_cfm_cb = le_pairing_complete_cb;
3199 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003200
Johan Hedberge9a416b2011-02-19 12:05:56 -03003201 conn->io_capability = cp->io_cap;
3202 cmd->user_data = conn;
3203
3204 if (conn->state == BT_CONNECTED &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003205 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003206 pairing_complete(cmd, 0);
3207
3208 err = 0;
3209
3210unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003211 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003212 return err;
3213}
3214
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003215static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3216 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003217{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003218 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003219 struct pending_cmd *cmd;
3220 struct hci_conn *conn;
3221 int err;
3222
3223 BT_DBG("");
3224
Johan Hedberg28424702012-02-02 04:02:29 +02003225 hci_dev_lock(hdev);
3226
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003227 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003228 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003229 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003230 goto unlock;
3231 }
3232
Johan Hedberg28424702012-02-02 04:02:29 +02003233 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3234 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003235 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003236 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003237 goto unlock;
3238 }
3239
3240 conn = cmd->user_data;
3241
3242 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003243 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003244 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003245 goto unlock;
3246 }
3247
3248 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003250 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003251 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003252unlock:
3253 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003254 return err;
3255}
3256
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003257static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003258 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003260{
Johan Hedberga5c29682011-02-19 12:05:57 -03003261 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003262 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003263 int err;
3264
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003265 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003266
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003267 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003268 err = cmd_complete(sk, hdev->id, mgmt_op,
3269 MGMT_STATUS_NOT_POWERED, addr,
3270 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003271 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003272 }
3273
Johan Hedberg1707c602013-03-15 17:07:15 -05003274 if (addr->type == BDADDR_BREDR)
3275 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003276 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003277 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003278
Johan Hedberg272d90d2012-02-09 15:26:12 +02003279 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003280 err = cmd_complete(sk, hdev->id, mgmt_op,
3281 MGMT_STATUS_NOT_CONNECTED, addr,
3282 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003283 goto done;
3284 }
3285
Johan Hedberg1707c602013-03-15 17:07:15 -05003286 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003287 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003288 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003289 err = cmd_complete(sk, hdev->id, mgmt_op,
3290 MGMT_STATUS_SUCCESS, addr,
3291 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003292 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003293 err = cmd_complete(sk, hdev->id, mgmt_op,
3294 MGMT_STATUS_FAILED, addr,
3295 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003296
Brian Gix47c15e22011-11-16 13:53:14 -08003297 goto done;
3298 }
3299
Johan Hedberg1707c602013-03-15 17:07:15 -05003300 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003301 if (!cmd) {
3302 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003303 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003304 }
3305
Brian Gix0df4c182011-11-16 13:53:13 -08003306 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003307 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3308 struct hci_cp_user_passkey_reply cp;
3309
Johan Hedberg1707c602013-03-15 17:07:15 -05003310 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003311 cp.passkey = passkey;
3312 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3313 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003314 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3315 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003316
Johan Hedberga664b5b2011-02-19 12:06:02 -03003317 if (err < 0)
3318 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003319
Brian Gix0df4c182011-11-16 13:53:13 -08003320done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003321 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003322 return err;
3323}
3324
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303325static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3326 void *data, u16 len)
3327{
3328 struct mgmt_cp_pin_code_neg_reply *cp = data;
3329
3330 BT_DBG("");
3331
Johan Hedberg1707c602013-03-15 17:07:15 -05003332 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303333 MGMT_OP_PIN_CODE_NEG_REPLY,
3334 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3335}
3336
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003337static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3338 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003339{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003340 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003341
3342 BT_DBG("");
3343
3344 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003345 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003346 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003347
Johan Hedberg1707c602013-03-15 17:07:15 -05003348 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003349 MGMT_OP_USER_CONFIRM_REPLY,
3350 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003351}
3352
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003353static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003354 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003355{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003356 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003357
3358 BT_DBG("");
3359
Johan Hedberg1707c602013-03-15 17:07:15 -05003360 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003361 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3362 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003363}
3364
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003365static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3366 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003368 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003369
3370 BT_DBG("");
3371
Johan Hedberg1707c602013-03-15 17:07:15 -05003372 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003373 MGMT_OP_USER_PASSKEY_REPLY,
3374 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003375}
3376
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003377static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003378 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003379{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003380 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003381
3382 BT_DBG("");
3383
Johan Hedberg1707c602013-03-15 17:07:15 -05003384 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003385 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3386 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003387}
3388
Johan Hedberg13928972013-03-15 17:07:00 -05003389static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003390{
Johan Hedberg13928972013-03-15 17:07:00 -05003391 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003392 struct hci_cp_write_local_name cp;
3393
Johan Hedberg13928972013-03-15 17:07:00 -05003394 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003395
Johan Hedberg890ea892013-03-15 17:06:52 -05003396 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003397}
3398
Johan Hedberg13928972013-03-15 17:07:00 -05003399static void set_name_complete(struct hci_dev *hdev, u8 status)
3400{
3401 struct mgmt_cp_set_local_name *cp;
3402 struct pending_cmd *cmd;
3403
3404 BT_DBG("status 0x%02x", status);
3405
3406 hci_dev_lock(hdev);
3407
3408 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3409 if (!cmd)
3410 goto unlock;
3411
3412 cp = cmd->param;
3413
3414 if (status)
3415 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3416 mgmt_status(status));
3417 else
3418 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3419 cp, sizeof(*cp));
3420
3421 mgmt_pending_remove(cmd);
3422
3423unlock:
3424 hci_dev_unlock(hdev);
3425}
3426
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003427static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003428 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003429{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003430 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003431 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003432 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003433 int err;
3434
3435 BT_DBG("");
3436
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003437 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003438
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003439 /* If the old values are the same as the new ones just return a
3440 * direct command complete event.
3441 */
3442 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3443 !memcmp(hdev->short_name, cp->short_name,
3444 sizeof(hdev->short_name))) {
3445 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3446 data, len);
3447 goto failed;
3448 }
3449
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003450 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003451
Johan Hedbergb5235a62012-02-21 14:32:24 +02003452 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003453 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003454
3455 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003456 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003457 if (err < 0)
3458 goto failed;
3459
3460 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003461 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003462
Johan Hedbergb5235a62012-02-21 14:32:24 +02003463 goto failed;
3464 }
3465
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003466 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003467 if (!cmd) {
3468 err = -ENOMEM;
3469 goto failed;
3470 }
3471
Johan Hedberg13928972013-03-15 17:07:00 -05003472 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3473
Johan Hedberg890ea892013-03-15 17:06:52 -05003474 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003475
3476 if (lmp_bredr_capable(hdev)) {
3477 update_name(&req);
3478 update_eir(&req);
3479 }
3480
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003481 /* The name is stored in the scan response data and so
3482 * no need to udpate the advertising data here.
3483 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003484 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003485 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003486
Johan Hedberg13928972013-03-15 17:07:00 -05003487 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003488 if (err < 0)
3489 mgmt_pending_remove(cmd);
3490
3491failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003492 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003493 return err;
3494}
3495
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003496static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003497 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003498{
Szymon Jancc35938b2011-03-22 13:12:21 +01003499 struct pending_cmd *cmd;
3500 int err;
3501
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003502 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003503
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003504 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003505
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003506 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003507 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003508 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003509 goto unlock;
3510 }
3511
Andre Guedes9a1a1992012-07-24 15:03:48 -03003512 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003513 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003514 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003515 goto unlock;
3516 }
3517
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003518 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003519 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003520 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003521 goto unlock;
3522 }
3523
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003524 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003525 if (!cmd) {
3526 err = -ENOMEM;
3527 goto unlock;
3528 }
3529
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003530 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3531 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3532 0, NULL);
3533 else
3534 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3535
Szymon Jancc35938b2011-03-22 13:12:21 +01003536 if (err < 0)
3537 mgmt_pending_remove(cmd);
3538
3539unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003540 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003541 return err;
3542}
3543
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003544static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003545 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003546{
Szymon Janc2763eda2011-03-22 13:12:22 +01003547 int err;
3548
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003549 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003550
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003551 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003552
Marcel Holtmannec109112014-01-10 02:07:30 -08003553 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3554 struct mgmt_cp_add_remote_oob_data *cp = data;
3555 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003556
Marcel Holtmannec109112014-01-10 02:07:30 -08003557 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3558 cp->hash, cp->randomizer);
3559 if (err < 0)
3560 status = MGMT_STATUS_FAILED;
3561 else
3562 status = MGMT_STATUS_SUCCESS;
3563
3564 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3565 status, &cp->addr, sizeof(cp->addr));
3566 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3567 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3568 u8 status;
3569
3570 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3571 cp->hash192,
3572 cp->randomizer192,
3573 cp->hash256,
3574 cp->randomizer256);
3575 if (err < 0)
3576 status = MGMT_STATUS_FAILED;
3577 else
3578 status = MGMT_STATUS_SUCCESS;
3579
3580 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3581 status, &cp->addr, sizeof(cp->addr));
3582 } else {
3583 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3584 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3585 MGMT_STATUS_INVALID_PARAMS);
3586 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003587
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003588 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003589 return err;
3590}
3591
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003592static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003593 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003594{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003595 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003596 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003597 int err;
3598
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003599 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003600
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003601 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003602
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003603 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003604 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003605 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003606 else
Szymon Janca6785be2012-12-13 15:11:21 +01003607 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003608
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003609 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003610 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003611
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003612 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003613 return err;
3614}
3615
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003616static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3617{
3618 struct pending_cmd *cmd;
3619 u8 type;
3620 int err;
3621
3622 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3623
3624 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3625 if (!cmd)
3626 return -ENOENT;
3627
3628 type = hdev->discovery.type;
3629
3630 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3631 &type, sizeof(type));
3632 mgmt_pending_remove(cmd);
3633
3634 return err;
3635}
3636
Andre Guedes7c307722013-04-30 15:29:28 -03003637static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3638{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003639 unsigned long timeout = 0;
3640
Andre Guedes7c307722013-04-30 15:29:28 -03003641 BT_DBG("status %d", status);
3642
3643 if (status) {
3644 hci_dev_lock(hdev);
3645 mgmt_start_discovery_failed(hdev, status);
3646 hci_dev_unlock(hdev);
3647 return;
3648 }
3649
3650 hci_dev_lock(hdev);
3651 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3652 hci_dev_unlock(hdev);
3653
3654 switch (hdev->discovery.type) {
3655 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003656 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003657 break;
3658
3659 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003660 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003661 break;
3662
3663 case DISCOV_TYPE_BREDR:
3664 break;
3665
3666 default:
3667 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3668 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003669
3670 if (!timeout)
3671 return;
3672
3673 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003674}
3675
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003676static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003677 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003678{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003679 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003680 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003681 struct hci_cp_le_set_scan_param param_cp;
3682 struct hci_cp_le_set_scan_enable enable_cp;
3683 struct hci_cp_inquiry inq_cp;
3684 struct hci_request req;
3685 /* General inquiry access code (GIAC) */
3686 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003687 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003688 int err;
3689
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003690 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003691
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003692 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003693
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003694 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003695 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003696 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003697 goto failed;
3698 }
3699
Andre Guedes642be6c2012-03-21 00:03:37 -03003700 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3701 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3702 MGMT_STATUS_BUSY);
3703 goto failed;
3704 }
3705
Johan Hedbergff9ef572012-01-04 14:23:45 +02003706 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003707 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003708 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003709 goto failed;
3710 }
3711
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003712 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003713 if (!cmd) {
3714 err = -ENOMEM;
3715 goto failed;
3716 }
3717
Andre Guedes4aab14e2012-02-17 20:39:36 -03003718 hdev->discovery.type = cp->type;
3719
Andre Guedes7c307722013-04-30 15:29:28 -03003720 hci_req_init(&req, hdev);
3721
Andre Guedes4aab14e2012-02-17 20:39:36 -03003722 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003723 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003724 status = mgmt_bredr_support(hdev);
3725 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003726 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003727 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003728 mgmt_pending_remove(cmd);
3729 goto failed;
3730 }
3731
Andre Guedes7c307722013-04-30 15:29:28 -03003732 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3733 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3734 MGMT_STATUS_BUSY);
3735 mgmt_pending_remove(cmd);
3736 goto failed;
3737 }
3738
3739 hci_inquiry_cache_flush(hdev);
3740
3741 memset(&inq_cp, 0, sizeof(inq_cp));
3742 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003743 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003744 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003745 break;
3746
3747 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003748 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003749 status = mgmt_le_support(hdev);
3750 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003751 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003752 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003753 mgmt_pending_remove(cmd);
3754 goto failed;
3755 }
3756
Andre Guedes7c307722013-04-30 15:29:28 -03003757 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003758 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003759 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3760 MGMT_STATUS_NOT_SUPPORTED);
3761 mgmt_pending_remove(cmd);
3762 goto failed;
3763 }
3764
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003765 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3766 /* Don't let discovery abort an outgoing
3767 * connection attempt that's using directed
3768 * advertising.
3769 */
3770 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3771 BT_CONNECT)) {
3772 err = cmd_status(sk, hdev->id,
3773 MGMT_OP_START_DISCOVERY,
3774 MGMT_STATUS_REJECTED);
3775 mgmt_pending_remove(cmd);
3776 goto failed;
3777 }
3778
3779 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003780 }
3781
Andre Guedesc54c3862014-02-26 20:21:50 -03003782 /* If controller is scanning, it means the background scanning
3783 * is running. Thus, we should temporarily stop it in order to
3784 * set the discovery scanning parameters.
3785 */
3786 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3787 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003788
3789 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003790
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003791 /* All active scans will be done with either a resolvable
3792 * private address (when privacy feature has been enabled)
3793 * or unresolvable private address.
3794 */
3795 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003796 if (err < 0) {
3797 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3798 MGMT_STATUS_FAILED);
3799 mgmt_pending_remove(cmd);
3800 goto failed;
3801 }
3802
Andre Guedes7c307722013-04-30 15:29:28 -03003803 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003804 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3805 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003806 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003807 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3808 &param_cp);
3809
3810 memset(&enable_cp, 0, sizeof(enable_cp));
3811 enable_cp.enable = LE_SCAN_ENABLE;
3812 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3813 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3814 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003815 break;
3816
Andre Guedesf39799f2012-02-17 20:39:35 -03003817 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003818 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3819 MGMT_STATUS_INVALID_PARAMS);
3820 mgmt_pending_remove(cmd);
3821 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003822 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003823
Andre Guedes7c307722013-04-30 15:29:28 -03003824 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003825 if (err < 0)
3826 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003827 else
3828 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003829
3830failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003831 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003832 return err;
3833}
3834
Andre Guedes1183fdc2013-04-30 15:29:35 -03003835static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3836{
3837 struct pending_cmd *cmd;
3838 int err;
3839
3840 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3841 if (!cmd)
3842 return -ENOENT;
3843
3844 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3845 &hdev->discovery.type, sizeof(hdev->discovery.type));
3846 mgmt_pending_remove(cmd);
3847
3848 return err;
3849}
3850
Andre Guedes0e05bba2013-04-30 15:29:33 -03003851static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3852{
3853 BT_DBG("status %d", status);
3854
3855 hci_dev_lock(hdev);
3856
3857 if (status) {
3858 mgmt_stop_discovery_failed(hdev, status);
3859 goto unlock;
3860 }
3861
3862 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3863
3864unlock:
3865 hci_dev_unlock(hdev);
3866}
3867
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003868static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003869 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003870{
Johan Hedbergd9306502012-02-20 23:25:18 +02003871 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003872 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003873 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003874 int err;
3875
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003876 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003877
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003878 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003879
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003880 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003881 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003882 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3883 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003884 goto unlock;
3885 }
3886
3887 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003888 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003889 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3890 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003891 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003892 }
3893
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003894 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003895 if (!cmd) {
3896 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003897 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003898 }
3899
Andre Guedes0e05bba2013-04-30 15:29:33 -03003900 hci_req_init(&req, hdev);
3901
Johan Hedberg21a60d32014-06-10 14:05:58 +03003902 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003903
Johan Hedberg21a60d32014-06-10 14:05:58 +03003904 err = hci_req_run(&req, stop_discovery_complete);
3905 if (!err) {
3906 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003907 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003908 }
3909
Johan Hedberg21a60d32014-06-10 14:05:58 +03003910 mgmt_pending_remove(cmd);
3911
3912 /* If no HCI commands were sent we're done */
3913 if (err == -ENODATA) {
3914 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3915 &mgmt_cp->type, sizeof(mgmt_cp->type));
3916 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3917 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003918
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003919unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003920 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003921 return err;
3922}
3923
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003924static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003925 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003926{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003927 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003928 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003929 int err;
3930
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003931 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003932
Johan Hedberg561aafb2012-01-04 13:31:59 +02003933 hci_dev_lock(hdev);
3934
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003935 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003936 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3937 MGMT_STATUS_FAILED, &cp->addr,
3938 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003939 goto failed;
3940 }
3941
Johan Hedberga198e7b2012-02-17 14:27:06 +02003942 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003943 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003944 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3945 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3946 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003947 goto failed;
3948 }
3949
3950 if (cp->name_known) {
3951 e->name_state = NAME_KNOWN;
3952 list_del(&e->list);
3953 } else {
3954 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003955 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003956 }
3957
Johan Hedberge3846622013-01-09 15:29:33 +02003958 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3959 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003960
3961failed:
3962 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003963 return err;
3964}
3965
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003966static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003967 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003968{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003969 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003970 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003971 int err;
3972
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003973 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003974
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003975 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003976 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3977 MGMT_STATUS_INVALID_PARAMS,
3978 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003979
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003980 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003981
Johan Hedbergdcc36c12014-07-09 12:59:13 +03003982 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
3983 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003984 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003985 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003986 goto done;
3987 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003988
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003989 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3990 sk);
3991 status = MGMT_STATUS_SUCCESS;
3992
3993done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003994 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003995 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003996
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003997 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003998
3999 return err;
4000}
4001
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004002static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004003 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004004{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004005 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004006 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004007 int err;
4008
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004009 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004010
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004011 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004012 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4013 MGMT_STATUS_INVALID_PARAMS,
4014 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004015
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004016 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004017
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004018 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4019 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004020 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004021 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004022 goto done;
4023 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004024
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004025 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4026 sk);
4027 status = MGMT_STATUS_SUCCESS;
4028
4029done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004030 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004031 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004032
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004033 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004034
4035 return err;
4036}
4037
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004038static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4039 u16 len)
4040{
4041 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004042 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004043 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004044 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004045
4046 BT_DBG("%s", hdev->name);
4047
Szymon Jancc72d4b82012-03-16 16:02:57 +01004048 source = __le16_to_cpu(cp->source);
4049
4050 if (source > 0x0002)
4051 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4052 MGMT_STATUS_INVALID_PARAMS);
4053
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004054 hci_dev_lock(hdev);
4055
Szymon Jancc72d4b82012-03-16 16:02:57 +01004056 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004057 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4058 hdev->devid_product = __le16_to_cpu(cp->product);
4059 hdev->devid_version = __le16_to_cpu(cp->version);
4060
4061 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4062
Johan Hedberg890ea892013-03-15 17:06:52 -05004063 hci_req_init(&req, hdev);
4064 update_eir(&req);
4065 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004066
4067 hci_dev_unlock(hdev);
4068
4069 return err;
4070}
4071
Johan Hedberg4375f102013-09-25 13:26:10 +03004072static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4073{
4074 struct cmd_lookup match = { NULL, hdev };
4075
4076 if (status) {
4077 u8 mgmt_err = mgmt_status(status);
4078
4079 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4080 cmd_status_rsp, &mgmt_err);
4081 return;
4082 }
4083
Johan Hedbergc93bd152014-07-08 15:07:48 +03004084 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4085 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4086 else
4087 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4088
Johan Hedberg4375f102013-09-25 13:26:10 +03004089 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4090 &match);
4091
4092 new_settings(hdev, match.sk);
4093
4094 if (match.sk)
4095 sock_put(match.sk);
4096}
4097
Marcel Holtmann21b51872013-10-10 09:47:53 -07004098static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4099 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004100{
4101 struct mgmt_mode *cp = data;
4102 struct pending_cmd *cmd;
4103 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004104 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004105 int err;
4106
4107 BT_DBG("request for %s", hdev->name);
4108
Johan Hedberge6fe7982013-10-02 15:45:22 +03004109 status = mgmt_le_support(hdev);
4110 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004111 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004112 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004113
4114 if (cp->val != 0x00 && cp->val != 0x01)
4115 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4116 MGMT_STATUS_INVALID_PARAMS);
4117
4118 hci_dev_lock(hdev);
4119
4120 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004121 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004122
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004123 /* The following conditions are ones which mean that we should
4124 * not do any HCI communication but directly send a mgmt
4125 * response to user space (after toggling the flag if
4126 * necessary).
4127 */
4128 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004129 hci_conn_num(hdev, LE_LINK) > 0 ||
4130 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4131 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004132 bool changed = false;
4133
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004134 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4135 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004136 changed = true;
4137 }
4138
4139 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4140 if (err < 0)
4141 goto unlock;
4142
4143 if (changed)
4144 err = new_settings(hdev, sk);
4145
4146 goto unlock;
4147 }
4148
4149 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4150 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4151 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4152 MGMT_STATUS_BUSY);
4153 goto unlock;
4154 }
4155
4156 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4157 if (!cmd) {
4158 err = -ENOMEM;
4159 goto unlock;
4160 }
4161
4162 hci_req_init(&req, hdev);
4163
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004164 if (val)
4165 enable_advertising(&req);
4166 else
4167 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004168
4169 err = hci_req_run(&req, set_advertising_complete);
4170 if (err < 0)
4171 mgmt_pending_remove(cmd);
4172
4173unlock:
4174 hci_dev_unlock(hdev);
4175 return err;
4176}
4177
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004178static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4179 void *data, u16 len)
4180{
4181 struct mgmt_cp_set_static_address *cp = data;
4182 int err;
4183
4184 BT_DBG("%s", hdev->name);
4185
Marcel Holtmann62af4442013-10-02 22:10:32 -07004186 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004187 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004188 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004189
4190 if (hdev_is_powered(hdev))
4191 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4192 MGMT_STATUS_REJECTED);
4193
4194 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4195 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4196 return cmd_status(sk, hdev->id,
4197 MGMT_OP_SET_STATIC_ADDRESS,
4198 MGMT_STATUS_INVALID_PARAMS);
4199
4200 /* Two most significant bits shall be set */
4201 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4202 return cmd_status(sk, hdev->id,
4203 MGMT_OP_SET_STATIC_ADDRESS,
4204 MGMT_STATUS_INVALID_PARAMS);
4205 }
4206
4207 hci_dev_lock(hdev);
4208
4209 bacpy(&hdev->static_addr, &cp->bdaddr);
4210
4211 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4212
4213 hci_dev_unlock(hdev);
4214
4215 return err;
4216}
4217
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004218static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4219 void *data, u16 len)
4220{
4221 struct mgmt_cp_set_scan_params *cp = data;
4222 __u16 interval, window;
4223 int err;
4224
4225 BT_DBG("%s", hdev->name);
4226
4227 if (!lmp_le_capable(hdev))
4228 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4229 MGMT_STATUS_NOT_SUPPORTED);
4230
4231 interval = __le16_to_cpu(cp->interval);
4232
4233 if (interval < 0x0004 || interval > 0x4000)
4234 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4235 MGMT_STATUS_INVALID_PARAMS);
4236
4237 window = __le16_to_cpu(cp->window);
4238
4239 if (window < 0x0004 || window > 0x4000)
4240 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4241 MGMT_STATUS_INVALID_PARAMS);
4242
Marcel Holtmann899e1072013-10-14 09:55:32 -07004243 if (window > interval)
4244 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4245 MGMT_STATUS_INVALID_PARAMS);
4246
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004247 hci_dev_lock(hdev);
4248
4249 hdev->le_scan_interval = interval;
4250 hdev->le_scan_window = window;
4251
4252 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4253
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004254 /* If background scan is running, restart it so new parameters are
4255 * loaded.
4256 */
4257 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4258 hdev->discovery.state == DISCOVERY_STOPPED) {
4259 struct hci_request req;
4260
4261 hci_req_init(&req, hdev);
4262
4263 hci_req_add_le_scan_disable(&req);
4264 hci_req_add_le_passive_scan(&req);
4265
4266 hci_req_run(&req, NULL);
4267 }
4268
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004269 hci_dev_unlock(hdev);
4270
4271 return err;
4272}
4273
Johan Hedberg33e38b32013-03-15 17:07:05 -05004274static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4275{
4276 struct pending_cmd *cmd;
4277
4278 BT_DBG("status 0x%02x", status);
4279
4280 hci_dev_lock(hdev);
4281
4282 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4283 if (!cmd)
4284 goto unlock;
4285
4286 if (status) {
4287 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4288 mgmt_status(status));
4289 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004290 struct mgmt_mode *cp = cmd->param;
4291
4292 if (cp->val)
4293 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4294 else
4295 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4296
Johan Hedberg33e38b32013-03-15 17:07:05 -05004297 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4298 new_settings(hdev, cmd->sk);
4299 }
4300
4301 mgmt_pending_remove(cmd);
4302
4303unlock:
4304 hci_dev_unlock(hdev);
4305}
4306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004307static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004308 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004309{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004310 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004311 struct pending_cmd *cmd;
4312 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004313 int err;
4314
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004315 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004316
Johan Hedberg56f87902013-10-02 13:43:13 +03004317 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4318 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004319 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4320 MGMT_STATUS_NOT_SUPPORTED);
4321
Johan Hedberga7e80f22013-01-09 16:05:19 +02004322 if (cp->val != 0x00 && cp->val != 0x01)
4323 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4324 MGMT_STATUS_INVALID_PARAMS);
4325
Johan Hedberg5400c042012-02-21 16:40:33 +02004326 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004327 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004328 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004329
4330 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004331 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004332 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004333
4334 hci_dev_lock(hdev);
4335
Johan Hedberg05cbf292013-03-15 17:07:07 -05004336 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4337 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4338 MGMT_STATUS_BUSY);
4339 goto unlock;
4340 }
4341
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004342 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4343 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4344 hdev);
4345 goto unlock;
4346 }
4347
Johan Hedberg33e38b32013-03-15 17:07:05 -05004348 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4349 data, len);
4350 if (!cmd) {
4351 err = -ENOMEM;
4352 goto unlock;
4353 }
4354
4355 hci_req_init(&req, hdev);
4356
Johan Hedberg406d7802013-03-15 17:07:09 -05004357 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004358
4359 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004360 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004361 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004362 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004363 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004364 }
4365
Johan Hedberg33e38b32013-03-15 17:07:05 -05004366unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004367 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004368
Antti Julkuf6422ec2011-06-22 13:11:56 +03004369 return err;
4370}
4371
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004372static void set_bredr_scan(struct hci_request *req)
4373{
4374 struct hci_dev *hdev = req->hdev;
4375 u8 scan = 0;
4376
4377 /* Ensure that fast connectable is disabled. This function will
4378 * not do anything if the page scan parameters are already what
4379 * they should be.
4380 */
4381 write_fast_connectable(req, false);
4382
Johan Hedberg6cebb9e72014-07-09 12:59:18 +03004383 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
4384 !list_empty(&hdev->whitelist))
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004385 scan |= SCAN_PAGE;
4386 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4387 scan |= SCAN_INQUIRY;
4388
4389 if (scan)
4390 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4391}
4392
Johan Hedberg0663ca22013-10-02 13:43:14 +03004393static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4394{
4395 struct pending_cmd *cmd;
4396
4397 BT_DBG("status 0x%02x", status);
4398
4399 hci_dev_lock(hdev);
4400
4401 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4402 if (!cmd)
4403 goto unlock;
4404
4405 if (status) {
4406 u8 mgmt_err = mgmt_status(status);
4407
4408 /* We need to restore the flag if related HCI commands
4409 * failed.
4410 */
4411 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4412
4413 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4414 } else {
4415 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4416 new_settings(hdev, cmd->sk);
4417 }
4418
4419 mgmt_pending_remove(cmd);
4420
4421unlock:
4422 hci_dev_unlock(hdev);
4423}
4424
4425static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4426{
4427 struct mgmt_mode *cp = data;
4428 struct pending_cmd *cmd;
4429 struct hci_request req;
4430 int err;
4431
4432 BT_DBG("request for %s", hdev->name);
4433
4434 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4435 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4436 MGMT_STATUS_NOT_SUPPORTED);
4437
4438 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4439 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4440 MGMT_STATUS_REJECTED);
4441
4442 if (cp->val != 0x00 && cp->val != 0x01)
4443 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4444 MGMT_STATUS_INVALID_PARAMS);
4445
4446 hci_dev_lock(hdev);
4447
4448 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4449 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4450 goto unlock;
4451 }
4452
4453 if (!hdev_is_powered(hdev)) {
4454 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004455 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4456 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4457 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4458 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4459 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4460 }
4461
4462 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4463
4464 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4465 if (err < 0)
4466 goto unlock;
4467
4468 err = new_settings(hdev, sk);
4469 goto unlock;
4470 }
4471
4472 /* Reject disabling when powered on */
4473 if (!cp->val) {
4474 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4475 MGMT_STATUS_REJECTED);
4476 goto unlock;
4477 }
4478
4479 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4480 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4481 MGMT_STATUS_BUSY);
4482 goto unlock;
4483 }
4484
4485 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4486 if (!cmd) {
4487 err = -ENOMEM;
4488 goto unlock;
4489 }
4490
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004491 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004492 * generates the correct flags.
4493 */
4494 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4495
4496 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004497
Johan Hedberg6cebb9e72014-07-09 12:59:18 +03004498 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
4499 !list_empty(&hdev->whitelist))
Johan Hedbergaa8af462013-10-14 21:15:26 +03004500 set_bredr_scan(&req);
4501
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004502 /* Since only the advertising data flags will change, there
4503 * is no need to update the scan response data.
4504 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004505 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004506
Johan Hedberg0663ca22013-10-02 13:43:14 +03004507 err = hci_req_run(&req, set_bredr_complete);
4508 if (err < 0)
4509 mgmt_pending_remove(cmd);
4510
4511unlock:
4512 hci_dev_unlock(hdev);
4513 return err;
4514}
4515
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004516static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4517 void *data, u16 len)
4518{
4519 struct mgmt_mode *cp = data;
4520 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004521 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004522 int err;
4523
4524 BT_DBG("request for %s", hdev->name);
4525
4526 status = mgmt_bredr_support(hdev);
4527 if (status)
4528 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4529 status);
4530
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004531 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004532 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004533 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4534 MGMT_STATUS_NOT_SUPPORTED);
4535
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004536 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004537 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4538 MGMT_STATUS_INVALID_PARAMS);
4539
4540 hci_dev_lock(hdev);
4541
4542 if (!hdev_is_powered(hdev)) {
4543 bool changed;
4544
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004545 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004546 changed = !test_and_set_bit(HCI_SC_ENABLED,
4547 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004548 if (cp->val == 0x02)
4549 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4550 else
4551 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4552 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004553 changed = test_and_clear_bit(HCI_SC_ENABLED,
4554 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004555 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4556 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004557
4558 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4559 if (err < 0)
4560 goto failed;
4561
4562 if (changed)
4563 err = new_settings(hdev, sk);
4564
4565 goto failed;
4566 }
4567
4568 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4569 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4570 MGMT_STATUS_BUSY);
4571 goto failed;
4572 }
4573
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004574 val = !!cp->val;
4575
4576 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4577 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004578 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4579 goto failed;
4580 }
4581
4582 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4583 if (!cmd) {
4584 err = -ENOMEM;
4585 goto failed;
4586 }
4587
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004588 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004589 if (err < 0) {
4590 mgmt_pending_remove(cmd);
4591 goto failed;
4592 }
4593
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004594 if (cp->val == 0x02)
4595 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4596 else
4597 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4598
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004599failed:
4600 hci_dev_unlock(hdev);
4601 return err;
4602}
4603
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004604static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4605 void *data, u16 len)
4606{
4607 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004608 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004609 int err;
4610
4611 BT_DBG("request for %s", hdev->name);
4612
Johan Hedbergb97109792014-06-24 14:00:28 +03004613 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004614 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4615 MGMT_STATUS_INVALID_PARAMS);
4616
4617 hci_dev_lock(hdev);
4618
4619 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004620 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4621 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004622 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004623 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4624 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004625
Johan Hedbergb97109792014-06-24 14:00:28 +03004626 if (cp->val == 0x02)
4627 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4628 &hdev->dev_flags);
4629 else
4630 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4631 &hdev->dev_flags);
4632
4633 if (hdev_is_powered(hdev) && use_changed &&
4634 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4635 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4636 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4637 sizeof(mode), &mode);
4638 }
4639
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004640 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4641 if (err < 0)
4642 goto unlock;
4643
4644 if (changed)
4645 err = new_settings(hdev, sk);
4646
4647unlock:
4648 hci_dev_unlock(hdev);
4649 return err;
4650}
4651
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004652static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4653 u16 len)
4654{
4655 struct mgmt_cp_set_privacy *cp = cp_data;
4656 bool changed;
4657 int err;
4658
4659 BT_DBG("request for %s", hdev->name);
4660
4661 if (!lmp_le_capable(hdev))
4662 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4663 MGMT_STATUS_NOT_SUPPORTED);
4664
4665 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4666 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4667 MGMT_STATUS_INVALID_PARAMS);
4668
4669 if (hdev_is_powered(hdev))
4670 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4671 MGMT_STATUS_REJECTED);
4672
4673 hci_dev_lock(hdev);
4674
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004675 /* If user space supports this command it is also expected to
4676 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4677 */
4678 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4679
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004680 if (cp->privacy) {
4681 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4682 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4683 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4684 } else {
4685 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4686 memset(hdev->irk, 0, sizeof(hdev->irk));
4687 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4688 }
4689
4690 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4691 if (err < 0)
4692 goto unlock;
4693
4694 if (changed)
4695 err = new_settings(hdev, sk);
4696
4697unlock:
4698 hci_dev_unlock(hdev);
4699 return err;
4700}
4701
Johan Hedberg41edf162014-02-18 10:19:35 +02004702static bool irk_is_valid(struct mgmt_irk_info *irk)
4703{
4704 switch (irk->addr.type) {
4705 case BDADDR_LE_PUBLIC:
4706 return true;
4707
4708 case BDADDR_LE_RANDOM:
4709 /* Two most significant bits shall be set */
4710 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4711 return false;
4712 return true;
4713 }
4714
4715 return false;
4716}
4717
4718static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4719 u16 len)
4720{
4721 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004722 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4723 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004724 u16 irk_count, expected_len;
4725 int i, err;
4726
4727 BT_DBG("request for %s", hdev->name);
4728
4729 if (!lmp_le_capable(hdev))
4730 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4731 MGMT_STATUS_NOT_SUPPORTED);
4732
4733 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004734 if (irk_count > max_irk_count) {
4735 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4736 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4737 MGMT_STATUS_INVALID_PARAMS);
4738 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004739
4740 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4741 if (expected_len != len) {
4742 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004743 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004744 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4745 MGMT_STATUS_INVALID_PARAMS);
4746 }
4747
4748 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4749
4750 for (i = 0; i < irk_count; i++) {
4751 struct mgmt_irk_info *key = &cp->irks[i];
4752
4753 if (!irk_is_valid(key))
4754 return cmd_status(sk, hdev->id,
4755 MGMT_OP_LOAD_IRKS,
4756 MGMT_STATUS_INVALID_PARAMS);
4757 }
4758
4759 hci_dev_lock(hdev);
4760
4761 hci_smp_irks_clear(hdev);
4762
4763 for (i = 0; i < irk_count; i++) {
4764 struct mgmt_irk_info *irk = &cp->irks[i];
4765 u8 addr_type;
4766
4767 if (irk->addr.type == BDADDR_LE_PUBLIC)
4768 addr_type = ADDR_LE_DEV_PUBLIC;
4769 else
4770 addr_type = ADDR_LE_DEV_RANDOM;
4771
4772 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4773 BDADDR_ANY);
4774 }
4775
4776 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4777
4778 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4779
4780 hci_dev_unlock(hdev);
4781
4782 return err;
4783}
4784
Johan Hedberg3f706b72013-01-20 14:27:16 +02004785static bool ltk_is_valid(struct mgmt_ltk_info *key)
4786{
4787 if (key->master != 0x00 && key->master != 0x01)
4788 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004789
4790 switch (key->addr.type) {
4791 case BDADDR_LE_PUBLIC:
4792 return true;
4793
4794 case BDADDR_LE_RANDOM:
4795 /* Two most significant bits shall be set */
4796 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4797 return false;
4798 return true;
4799 }
4800
4801 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004802}
4803
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004804static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004805 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004806{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004807 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004808 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4809 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004810 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004811 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004812
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004813 BT_DBG("request for %s", hdev->name);
4814
4815 if (!lmp_le_capable(hdev))
4816 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4817 MGMT_STATUS_NOT_SUPPORTED);
4818
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004819 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004820 if (key_count > max_key_count) {
4821 BT_ERR("load_ltks: too big key_count value %u", key_count);
4822 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4823 MGMT_STATUS_INVALID_PARAMS);
4824 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004825
4826 expected_len = sizeof(*cp) + key_count *
4827 sizeof(struct mgmt_ltk_info);
4828 if (expected_len != len) {
4829 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004830 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004831 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004832 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004833 }
4834
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004835 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004836
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004837 for (i = 0; i < key_count; i++) {
4838 struct mgmt_ltk_info *key = &cp->keys[i];
4839
Johan Hedberg3f706b72013-01-20 14:27:16 +02004840 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004841 return cmd_status(sk, hdev->id,
4842 MGMT_OP_LOAD_LONG_TERM_KEYS,
4843 MGMT_STATUS_INVALID_PARAMS);
4844 }
4845
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004846 hci_dev_lock(hdev);
4847
4848 hci_smp_ltks_clear(hdev);
4849
4850 for (i = 0; i < key_count; i++) {
4851 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004852 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004853
4854 if (key->addr.type == BDADDR_LE_PUBLIC)
4855 addr_type = ADDR_LE_DEV_PUBLIC;
4856 else
4857 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004858
4859 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004860 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004861 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004862 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004863
Johan Hedberg61b43352014-05-29 19:36:53 +03004864 switch (key->type) {
4865 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004866 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004867 break;
4868 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004869 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004870 break;
4871 default:
4872 continue;
4873 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004874
Johan Hedberg35d70272014-02-19 14:57:47 +02004875 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004876 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004877 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004878 }
4879
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004880 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4881 NULL, 0);
4882
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004883 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004884
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004885 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004886}
4887
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004888struct cmd_conn_lookup {
4889 struct hci_conn *conn;
4890 bool valid_tx_power;
4891 u8 mgmt_status;
4892};
4893
4894static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4895{
4896 struct cmd_conn_lookup *match = data;
4897 struct mgmt_cp_get_conn_info *cp;
4898 struct mgmt_rp_get_conn_info rp;
4899 struct hci_conn *conn = cmd->user_data;
4900
4901 if (conn != match->conn)
4902 return;
4903
4904 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4905
4906 memset(&rp, 0, sizeof(rp));
4907 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4908 rp.addr.type = cp->addr.type;
4909
4910 if (!match->mgmt_status) {
4911 rp.rssi = conn->rssi;
4912
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004913 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004914 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004915 rp.max_tx_power = conn->max_tx_power;
4916 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004917 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004918 rp.max_tx_power = HCI_TX_POWER_INVALID;
4919 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004920 }
4921
4922 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4923 match->mgmt_status, &rp, sizeof(rp));
4924
4925 hci_conn_drop(conn);
4926
4927 mgmt_pending_remove(cmd);
4928}
4929
4930static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4931{
4932 struct hci_cp_read_rssi *cp;
4933 struct hci_conn *conn;
4934 struct cmd_conn_lookup match;
4935 u16 handle;
4936
4937 BT_DBG("status 0x%02x", status);
4938
4939 hci_dev_lock(hdev);
4940
4941 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004942 * otherwise we assume it's not valid. At the moment we assume that
4943 * either both or none of current and max values are valid to keep code
4944 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004945 */
4946 match.valid_tx_power = !status;
4947
4948 /* Commands sent in request are either Read RSSI or Read Transmit Power
4949 * Level so we check which one was last sent to retrieve connection
4950 * handle. Both commands have handle as first parameter so it's safe to
4951 * cast data on the same command struct.
4952 *
4953 * First command sent is always Read RSSI and we fail only if it fails.
4954 * In other case we simply override error to indicate success as we
4955 * already remembered if TX power value is actually valid.
4956 */
4957 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4958 if (!cp) {
4959 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4960 status = 0;
4961 }
4962
4963 if (!cp) {
4964 BT_ERR("invalid sent_cmd in response");
4965 goto unlock;
4966 }
4967
4968 handle = __le16_to_cpu(cp->handle);
4969 conn = hci_conn_hash_lookup_handle(hdev, handle);
4970 if (!conn) {
4971 BT_ERR("unknown handle (%d) in response", handle);
4972 goto unlock;
4973 }
4974
4975 match.conn = conn;
4976 match.mgmt_status = mgmt_status(status);
4977
4978 /* Cache refresh is complete, now reply for mgmt request for given
4979 * connection only.
4980 */
4981 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4982 get_conn_info_complete, &match);
4983
4984unlock:
4985 hci_dev_unlock(hdev);
4986}
4987
4988static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4989 u16 len)
4990{
4991 struct mgmt_cp_get_conn_info *cp = data;
4992 struct mgmt_rp_get_conn_info rp;
4993 struct hci_conn *conn;
4994 unsigned long conn_info_age;
4995 int err = 0;
4996
4997 BT_DBG("%s", hdev->name);
4998
4999 memset(&rp, 0, sizeof(rp));
5000 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5001 rp.addr.type = cp->addr.type;
5002
5003 if (!bdaddr_type_is_valid(cp->addr.type))
5004 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5005 MGMT_STATUS_INVALID_PARAMS,
5006 &rp, sizeof(rp));
5007
5008 hci_dev_lock(hdev);
5009
5010 if (!hdev_is_powered(hdev)) {
5011 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5012 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5013 goto unlock;
5014 }
5015
5016 if (cp->addr.type == BDADDR_BREDR)
5017 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5018 &cp->addr.bdaddr);
5019 else
5020 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5021
5022 if (!conn || conn->state != BT_CONNECTED) {
5023 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5024 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5025 goto unlock;
5026 }
5027
5028 /* To avoid client trying to guess when to poll again for information we
5029 * calculate conn info age as random value between min/max set in hdev.
5030 */
5031 conn_info_age = hdev->conn_info_min_age +
5032 prandom_u32_max(hdev->conn_info_max_age -
5033 hdev->conn_info_min_age);
5034
5035 /* Query controller to refresh cached values if they are too old or were
5036 * never read.
5037 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005038 if (time_after(jiffies, conn->conn_info_timestamp +
5039 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005040 !conn->conn_info_timestamp) {
5041 struct hci_request req;
5042 struct hci_cp_read_tx_power req_txp_cp;
5043 struct hci_cp_read_rssi req_rssi_cp;
5044 struct pending_cmd *cmd;
5045
5046 hci_req_init(&req, hdev);
5047 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5048 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5049 &req_rssi_cp);
5050
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005051 /* For LE links TX power does not change thus we don't need to
5052 * query for it once value is known.
5053 */
5054 if (!bdaddr_type_is_le(cp->addr.type) ||
5055 conn->tx_power == HCI_TX_POWER_INVALID) {
5056 req_txp_cp.handle = cpu_to_le16(conn->handle);
5057 req_txp_cp.type = 0x00;
5058 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5059 sizeof(req_txp_cp), &req_txp_cp);
5060 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005061
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005062 /* Max TX power needs to be read only once per connection */
5063 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5064 req_txp_cp.handle = cpu_to_le16(conn->handle);
5065 req_txp_cp.type = 0x01;
5066 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5067 sizeof(req_txp_cp), &req_txp_cp);
5068 }
5069
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005070 err = hci_req_run(&req, conn_info_refresh_complete);
5071 if (err < 0)
5072 goto unlock;
5073
5074 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5075 data, len);
5076 if (!cmd) {
5077 err = -ENOMEM;
5078 goto unlock;
5079 }
5080
5081 hci_conn_hold(conn);
5082 cmd->user_data = conn;
5083
5084 conn->conn_info_timestamp = jiffies;
5085 } else {
5086 /* Cache is valid, just reply with values cached in hci_conn */
5087 rp.rssi = conn->rssi;
5088 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005089 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005090
5091 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5092 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5093 }
5094
5095unlock:
5096 hci_dev_unlock(hdev);
5097 return err;
5098}
5099
Johan Hedberg95868422014-06-28 17:54:07 +03005100static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5101{
5102 struct mgmt_cp_get_clock_info *cp;
5103 struct mgmt_rp_get_clock_info rp;
5104 struct hci_cp_read_clock *hci_cp;
5105 struct pending_cmd *cmd;
5106 struct hci_conn *conn;
5107
5108 BT_DBG("%s status %u", hdev->name, status);
5109
5110 hci_dev_lock(hdev);
5111
5112 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5113 if (!hci_cp)
5114 goto unlock;
5115
5116 if (hci_cp->which) {
5117 u16 handle = __le16_to_cpu(hci_cp->handle);
5118 conn = hci_conn_hash_lookup_handle(hdev, handle);
5119 } else {
5120 conn = NULL;
5121 }
5122
5123 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5124 if (!cmd)
5125 goto unlock;
5126
5127 cp = cmd->param;
5128
5129 memset(&rp, 0, sizeof(rp));
5130 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5131
5132 if (status)
5133 goto send_rsp;
5134
5135 rp.local_clock = cpu_to_le32(hdev->clock);
5136
5137 if (conn) {
5138 rp.piconet_clock = cpu_to_le32(conn->clock);
5139 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5140 }
5141
5142send_rsp:
5143 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5144 &rp, sizeof(rp));
5145 mgmt_pending_remove(cmd);
5146 if (conn)
5147 hci_conn_drop(conn);
5148
5149unlock:
5150 hci_dev_unlock(hdev);
5151}
5152
5153static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5154 u16 len)
5155{
5156 struct mgmt_cp_get_clock_info *cp = data;
5157 struct mgmt_rp_get_clock_info rp;
5158 struct hci_cp_read_clock hci_cp;
5159 struct pending_cmd *cmd;
5160 struct hci_request req;
5161 struct hci_conn *conn;
5162 int err;
5163
5164 BT_DBG("%s", hdev->name);
5165
5166 memset(&rp, 0, sizeof(rp));
5167 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5168 rp.addr.type = cp->addr.type;
5169
5170 if (cp->addr.type != BDADDR_BREDR)
5171 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5172 MGMT_STATUS_INVALID_PARAMS,
5173 &rp, sizeof(rp));
5174
5175 hci_dev_lock(hdev);
5176
5177 if (!hdev_is_powered(hdev)) {
5178 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5179 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5180 goto unlock;
5181 }
5182
5183 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5184 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5185 &cp->addr.bdaddr);
5186 if (!conn || conn->state != BT_CONNECTED) {
5187 err = cmd_complete(sk, hdev->id,
5188 MGMT_OP_GET_CLOCK_INFO,
5189 MGMT_STATUS_NOT_CONNECTED,
5190 &rp, sizeof(rp));
5191 goto unlock;
5192 }
5193 } else {
5194 conn = NULL;
5195 }
5196
5197 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5198 if (!cmd) {
5199 err = -ENOMEM;
5200 goto unlock;
5201 }
5202
5203 hci_req_init(&req, hdev);
5204
5205 memset(&hci_cp, 0, sizeof(hci_cp));
5206 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5207
5208 if (conn) {
5209 hci_conn_hold(conn);
5210 cmd->user_data = conn;
5211
5212 hci_cp.handle = cpu_to_le16(conn->handle);
5213 hci_cp.which = 0x01; /* Piconet clock */
5214 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5215 }
5216
5217 err = hci_req_run(&req, get_clock_info_complete);
5218 if (err < 0)
5219 mgmt_pending_remove(cmd);
5220
5221unlock:
5222 hci_dev_unlock(hdev);
5223 return err;
5224}
5225
Johan Hedberga3974072014-07-09 12:59:15 +03005226/* Helper for Add/Remove Device commands */
5227static void update_page_scan(struct hci_dev *hdev, u8 scan)
5228{
5229 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5230 return;
5231
5232 if (!hdev_is_powered(hdev))
5233 return;
5234
5235 /* If HCI_CONNECTABLE is set then Add/Remove Device should not
5236 * make any changes to page scanning.
5237 */
5238 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
5239 return;
5240
5241 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
5242 scan |= SCAN_INQUIRY;
5243
5244 hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
5245}
5246
Marcel Holtmann8afef092014-06-29 22:28:34 +02005247static void device_added(struct sock *sk, struct hci_dev *hdev,
5248 bdaddr_t *bdaddr, u8 type, u8 action)
5249{
5250 struct mgmt_ev_device_added ev;
5251
5252 bacpy(&ev.addr.bdaddr, bdaddr);
5253 ev.addr.type = type;
5254 ev.action = action;
5255
5256 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5257}
5258
Marcel Holtmann2faade52014-06-29 19:44:03 +02005259static int add_device(struct sock *sk, struct hci_dev *hdev,
5260 void *data, u16 len)
5261{
5262 struct mgmt_cp_add_device *cp = data;
5263 u8 auto_conn, addr_type;
5264 int err;
5265
5266 BT_DBG("%s", hdev->name);
5267
Johan Hedberg66593582014-07-09 12:59:14 +03005268 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005269 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5270 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5271 MGMT_STATUS_INVALID_PARAMS,
5272 &cp->addr, sizeof(cp->addr));
5273
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005274 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005275 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5276 MGMT_STATUS_INVALID_PARAMS,
5277 &cp->addr, sizeof(cp->addr));
5278
5279 hci_dev_lock(hdev);
5280
Johan Hedberg66593582014-07-09 12:59:14 +03005281 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberga3974072014-07-09 12:59:15 +03005282 bool update_scan;
5283
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005284 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005285 if (cp->action != 0x01) {
5286 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5287 MGMT_STATUS_INVALID_PARAMS,
5288 &cp->addr, sizeof(cp->addr));
5289 goto unlock;
5290 }
5291
Johan Hedberga3974072014-07-09 12:59:15 +03005292 update_scan = list_empty(&hdev->whitelist);
5293
Johan Hedberg66593582014-07-09 12:59:14 +03005294 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5295 cp->addr.type);
5296 if (err)
5297 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005298
5299 if (update_scan)
5300 update_page_scan(hdev, SCAN_PAGE);
5301
Johan Hedberg66593582014-07-09 12:59:14 +03005302 goto added;
5303 }
5304
Marcel Holtmann2faade52014-06-29 19:44:03 +02005305 if (cp->addr.type == BDADDR_LE_PUBLIC)
5306 addr_type = ADDR_LE_DEV_PUBLIC;
5307 else
5308 addr_type = ADDR_LE_DEV_RANDOM;
5309
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005310 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005311 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005312 else if (cp->action == 0x01)
5313 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005314 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005315 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005316
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005317 /* If the connection parameters don't exist for this device,
5318 * they will be created and configured with defaults.
5319 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005320 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5321 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005322 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5323 MGMT_STATUS_FAILED,
5324 &cp->addr, sizeof(cp->addr));
5325 goto unlock;
5326 }
5327
Johan Hedberg66593582014-07-09 12:59:14 +03005328added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005329 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5330
Marcel Holtmann2faade52014-06-29 19:44:03 +02005331 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5332 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5333
5334unlock:
5335 hci_dev_unlock(hdev);
5336 return err;
5337}
5338
Marcel Holtmann8afef092014-06-29 22:28:34 +02005339static void device_removed(struct sock *sk, struct hci_dev *hdev,
5340 bdaddr_t *bdaddr, u8 type)
5341{
5342 struct mgmt_ev_device_removed ev;
5343
5344 bacpy(&ev.addr.bdaddr, bdaddr);
5345 ev.addr.type = type;
5346
5347 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5348}
5349
Marcel Holtmann2faade52014-06-29 19:44:03 +02005350static int remove_device(struct sock *sk, struct hci_dev *hdev,
5351 void *data, u16 len)
5352{
5353 struct mgmt_cp_remove_device *cp = data;
5354 int err;
5355
5356 BT_DBG("%s", hdev->name);
5357
5358 hci_dev_lock(hdev);
5359
5360 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005361 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005362 u8 addr_type;
5363
Johan Hedberg66593582014-07-09 12:59:14 +03005364 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005365 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5366 MGMT_STATUS_INVALID_PARAMS,
5367 &cp->addr, sizeof(cp->addr));
5368 goto unlock;
5369 }
5370
Johan Hedberg66593582014-07-09 12:59:14 +03005371 if (cp->addr.type == BDADDR_BREDR) {
5372 err = hci_bdaddr_list_del(&hdev->whitelist,
5373 &cp->addr.bdaddr,
5374 cp->addr.type);
5375 if (err) {
5376 err = cmd_complete(sk, hdev->id,
5377 MGMT_OP_REMOVE_DEVICE,
5378 MGMT_STATUS_INVALID_PARAMS,
5379 &cp->addr, sizeof(cp->addr));
5380 goto unlock;
5381 }
5382
Johan Hedberga3974072014-07-09 12:59:15 +03005383 if (list_empty(&hdev->whitelist))
5384 update_page_scan(hdev, SCAN_DISABLED);
5385
Johan Hedberg66593582014-07-09 12:59:14 +03005386 device_removed(sk, hdev, &cp->addr.bdaddr,
5387 cp->addr.type);
5388 goto complete;
5389 }
5390
Marcel Holtmann2faade52014-06-29 19:44:03 +02005391 if (cp->addr.type == BDADDR_LE_PUBLIC)
5392 addr_type = ADDR_LE_DEV_PUBLIC;
5393 else
5394 addr_type = ADDR_LE_DEV_RANDOM;
5395
Johan Hedbergc71593d2014-07-02 17:37:28 +03005396 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5397 addr_type);
5398 if (!params) {
5399 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5400 MGMT_STATUS_INVALID_PARAMS,
5401 &cp->addr, sizeof(cp->addr));
5402 goto unlock;
5403 }
5404
5405 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5406 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5407 MGMT_STATUS_INVALID_PARAMS,
5408 &cp->addr, sizeof(cp->addr));
5409 goto unlock;
5410 }
5411
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005412 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005413 list_del(&params->list);
5414 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005415 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005416
5417 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005418 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005419 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005420 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005421
Marcel Holtmann2faade52014-06-29 19:44:03 +02005422 if (cp->addr.type) {
5423 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5424 MGMT_STATUS_INVALID_PARAMS,
5425 &cp->addr, sizeof(cp->addr));
5426 goto unlock;
5427 }
5428
Johan Hedberg66593582014-07-09 12:59:14 +03005429 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5430 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5431 list_del(&b->list);
5432 kfree(b);
5433 }
5434
Johan Hedberga3974072014-07-09 12:59:15 +03005435 update_page_scan(hdev, SCAN_DISABLED);
5436
Johan Hedberg19de0822014-07-06 13:06:51 +03005437 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5438 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5439 continue;
5440 device_removed(sk, hdev, &p->addr, p->addr_type);
5441 list_del(&p->action);
5442 list_del(&p->list);
5443 kfree(p);
5444 }
5445
5446 BT_DBG("All LE connection parameters were removed");
5447
5448 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005449 }
5450
Johan Hedberg66593582014-07-09 12:59:14 +03005451complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005452 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5453 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5454
5455unlock:
5456 hci_dev_unlock(hdev);
5457 return err;
5458}
5459
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005460static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5461 u16 len)
5462{
5463 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005464 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5465 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005466 u16 param_count, expected_len;
5467 int i;
5468
5469 if (!lmp_le_capable(hdev))
5470 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5471 MGMT_STATUS_NOT_SUPPORTED);
5472
5473 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005474 if (param_count > max_param_count) {
5475 BT_ERR("load_conn_param: too big param_count value %u",
5476 param_count);
5477 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5478 MGMT_STATUS_INVALID_PARAMS);
5479 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005480
5481 expected_len = sizeof(*cp) + param_count *
5482 sizeof(struct mgmt_conn_param);
5483 if (expected_len != len) {
5484 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5485 expected_len, len);
5486 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5487 MGMT_STATUS_INVALID_PARAMS);
5488 }
5489
5490 BT_DBG("%s param_count %u", hdev->name, param_count);
5491
5492 hci_dev_lock(hdev);
5493
5494 hci_conn_params_clear_disabled(hdev);
5495
5496 for (i = 0; i < param_count; i++) {
5497 struct mgmt_conn_param *param = &cp->params[i];
5498 struct hci_conn_params *hci_param;
5499 u16 min, max, latency, timeout;
5500 u8 addr_type;
5501
5502 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5503 param->addr.type);
5504
5505 if (param->addr.type == BDADDR_LE_PUBLIC) {
5506 addr_type = ADDR_LE_DEV_PUBLIC;
5507 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5508 addr_type = ADDR_LE_DEV_RANDOM;
5509 } else {
5510 BT_ERR("Ignoring invalid connection parameters");
5511 continue;
5512 }
5513
5514 min = le16_to_cpu(param->min_interval);
5515 max = le16_to_cpu(param->max_interval);
5516 latency = le16_to_cpu(param->latency);
5517 timeout = le16_to_cpu(param->timeout);
5518
5519 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5520 min, max, latency, timeout);
5521
5522 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5523 BT_ERR("Ignoring invalid connection parameters");
5524 continue;
5525 }
5526
5527 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5528 addr_type);
5529 if (!hci_param) {
5530 BT_ERR("Failed to add connection parameters");
5531 continue;
5532 }
5533
5534 hci_param->conn_min_interval = min;
5535 hci_param->conn_max_interval = max;
5536 hci_param->conn_latency = latency;
5537 hci_param->supervision_timeout = timeout;
5538 }
5539
5540 hci_dev_unlock(hdev);
5541
5542 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5543}
5544
Marcel Holtmanndbece372014-07-04 18:11:55 +02005545static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5546 void *data, u16 len)
5547{
5548 struct mgmt_cp_set_external_config *cp = data;
5549 bool changed;
5550 int err;
5551
5552 BT_DBG("%s", hdev->name);
5553
5554 if (hdev_is_powered(hdev))
5555 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5556 MGMT_STATUS_REJECTED);
5557
5558 if (cp->config != 0x00 && cp->config != 0x01)
5559 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5560 MGMT_STATUS_INVALID_PARAMS);
5561
5562 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5563 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5564 MGMT_STATUS_NOT_SUPPORTED);
5565
5566 hci_dev_lock(hdev);
5567
5568 if (cp->config)
5569 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5570 &hdev->dev_flags);
5571 else
5572 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5573 &hdev->dev_flags);
5574
5575 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5576 if (err < 0)
5577 goto unlock;
5578
5579 if (!changed)
5580 goto unlock;
5581
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005582 err = new_options(hdev, sk);
5583
Marcel Holtmanndbece372014-07-04 18:11:55 +02005584 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5585 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005586
5587 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5588 set_bit(HCI_CONFIG, &hdev->dev_flags);
5589 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5590
5591 queue_work(hdev->req_workqueue, &hdev->power_on);
5592 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005593 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005594 mgmt_index_added(hdev);
5595 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005596 }
5597
5598unlock:
5599 hci_dev_unlock(hdev);
5600 return err;
5601}
5602
Marcel Holtmann9713c172014-07-06 12:11:15 +02005603static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5604 void *data, u16 len)
5605{
5606 struct mgmt_cp_set_public_address *cp = data;
5607 bool changed;
5608 int err;
5609
5610 BT_DBG("%s", hdev->name);
5611
5612 if (hdev_is_powered(hdev))
5613 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5614 MGMT_STATUS_REJECTED);
5615
5616 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5617 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5618 MGMT_STATUS_INVALID_PARAMS);
5619
5620 if (!hdev->set_bdaddr)
5621 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5622 MGMT_STATUS_NOT_SUPPORTED);
5623
5624 hci_dev_lock(hdev);
5625
5626 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5627 bacpy(&hdev->public_addr, &cp->bdaddr);
5628
5629 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5630 if (err < 0)
5631 goto unlock;
5632
5633 if (!changed)
5634 goto unlock;
5635
5636 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5637 err = new_options(hdev, sk);
5638
5639 if (is_configured(hdev)) {
5640 mgmt_index_removed(hdev);
5641
5642 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5643
5644 set_bit(HCI_CONFIG, &hdev->dev_flags);
5645 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5646
5647 queue_work(hdev->req_workqueue, &hdev->power_on);
5648 }
5649
5650unlock:
5651 hci_dev_unlock(hdev);
5652 return err;
5653}
5654
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005655static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005656 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5657 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005658 bool var_len;
5659 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005660} mgmt_handlers[] = {
5661 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005662 { read_version, false, MGMT_READ_VERSION_SIZE },
5663 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5664 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5665 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5666 { set_powered, false, MGMT_SETTING_SIZE },
5667 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5668 { set_connectable, false, MGMT_SETTING_SIZE },
5669 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5670 { set_pairable, false, MGMT_SETTING_SIZE },
5671 { set_link_security, false, MGMT_SETTING_SIZE },
5672 { set_ssp, false, MGMT_SETTING_SIZE },
5673 { set_hs, false, MGMT_SETTING_SIZE },
5674 { set_le, false, MGMT_SETTING_SIZE },
5675 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5676 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5677 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5678 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5679 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5680 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5681 { disconnect, false, MGMT_DISCONNECT_SIZE },
5682 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5683 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5684 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5685 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5686 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5687 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5688 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5689 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5690 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5691 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5692 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5693 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005694 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005695 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5696 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5697 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5698 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5699 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5700 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005701 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005702 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005703 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005704 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005705 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005706 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005707 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005708 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005709 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005710 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005711 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005712 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5713 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005714 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5715 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005716 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005717 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005718 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005719};
5720
Johan Hedberg03811012010-12-08 00:21:06 +02005721int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5722{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005723 void *buf;
5724 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005725 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005726 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005727 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005728 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005729 int err;
5730
5731 BT_DBG("got %zu bytes", msglen);
5732
5733 if (msglen < sizeof(*hdr))
5734 return -EINVAL;
5735
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005736 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005737 if (!buf)
5738 return -ENOMEM;
5739
5740 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5741 err = -EFAULT;
5742 goto done;
5743 }
5744
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005745 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005746 opcode = __le16_to_cpu(hdr->opcode);
5747 index = __le16_to_cpu(hdr->index);
5748 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005749
5750 if (len != msglen - sizeof(*hdr)) {
5751 err = -EINVAL;
5752 goto done;
5753 }
5754
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005755 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005756 hdev = hci_dev_get(index);
5757 if (!hdev) {
5758 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005759 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005760 goto done;
5761 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005762
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005763 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005764 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005765 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005766 err = cmd_status(sk, index, opcode,
5767 MGMT_STATUS_INVALID_INDEX);
5768 goto done;
5769 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005770
5771 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005772 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005773 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5774 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005775 err = cmd_status(sk, index, opcode,
5776 MGMT_STATUS_INVALID_INDEX);
5777 goto done;
5778 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005779 }
5780
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005781 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005782 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005783 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005784 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005785 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005786 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005787 }
5788
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005789 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5790 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5791 err = cmd_status(sk, index, opcode,
5792 MGMT_STATUS_INVALID_INDEX);
5793 goto done;
5794 }
5795
5796 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5797 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005798 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005799 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005800 goto done;
5801 }
5802
Johan Hedbergbe22b542012-03-01 22:24:41 +02005803 handler = &mgmt_handlers[opcode];
5804
5805 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005806 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005807 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005808 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005809 goto done;
5810 }
5811
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005812 if (hdev)
5813 mgmt_init_hdev(sk, hdev);
5814
5815 cp = buf + sizeof(*hdr);
5816
Johan Hedbergbe22b542012-03-01 22:24:41 +02005817 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005818 if (err < 0)
5819 goto done;
5820
Johan Hedberg03811012010-12-08 00:21:06 +02005821 err = msglen;
5822
5823done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005824 if (hdev)
5825 hci_dev_put(hdev);
5826
Johan Hedberg03811012010-12-08 00:21:06 +02005827 kfree(buf);
5828 return err;
5829}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005830
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005831void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005832{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005833 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005834 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005835
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005836 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5837 return;
5838
5839 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5840 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5841 else
5842 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005843}
5844
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005845void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005846{
Johan Hedberg5f159032012-03-02 03:13:19 +02005847 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005848
Marcel Holtmann1514b892013-10-06 08:25:01 -07005849 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005850 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005851
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005852 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5853 return;
5854
Johan Hedberg744cf192011-11-08 20:40:14 +02005855 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005856
Marcel Holtmannedd38962014-07-02 21:30:55 +02005857 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5858 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5859 else
5860 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005861}
5862
Andre Guedes6046dc32014-02-26 20:21:51 -03005863/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005864static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005865{
5866 struct hci_conn_params *p;
5867
5868 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005869 /* Needed for AUTO_OFF case where might not "really"
5870 * have been powered off.
5871 */
5872 list_del_init(&p->action);
5873
5874 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005875 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03005876 case HCI_AUTO_CONN_ALWAYS:
5877 list_add(&p->action, &hdev->pend_le_conns);
5878 break;
5879 case HCI_AUTO_CONN_REPORT:
5880 list_add(&p->action, &hdev->pend_le_reports);
5881 break;
5882 default:
5883 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005884 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005885 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005886
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005887 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005888}
5889
Johan Hedberg229ab392013-03-15 17:06:53 -05005890static void powered_complete(struct hci_dev *hdev, u8 status)
5891{
5892 struct cmd_lookup match = { NULL, hdev };
5893
5894 BT_DBG("status 0x%02x", status);
5895
5896 hci_dev_lock(hdev);
5897
Johan Hedbergd7347f32014-07-04 12:37:23 +03005898 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005899
Johan Hedberg229ab392013-03-15 17:06:53 -05005900 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5901
5902 new_settings(hdev, match.sk);
5903
5904 hci_dev_unlock(hdev);
5905
5906 if (match.sk)
5907 sock_put(match.sk);
5908}
5909
Johan Hedberg70da6242013-03-15 17:06:51 -05005910static int powered_update_hci(struct hci_dev *hdev)
5911{
Johan Hedberg890ea892013-03-15 17:06:52 -05005912 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005913 u8 link_sec;
5914
Johan Hedberg890ea892013-03-15 17:06:52 -05005915 hci_req_init(&req, hdev);
5916
Johan Hedberg70da6242013-03-15 17:06:51 -05005917 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5918 !lmp_host_ssp_capable(hdev)) {
5919 u8 ssp = 1;
5920
Johan Hedberg890ea892013-03-15 17:06:52 -05005921 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005922 }
5923
Johan Hedbergc73eee92013-04-19 18:35:21 +03005924 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5925 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005926 struct hci_cp_write_le_host_supported cp;
5927
Marcel Holtmann32226e42014-07-24 20:04:16 +02005928 cp.le = 0x01;
5929 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05005930
5931 /* Check first if we already have the right
5932 * host state (host features set)
5933 */
5934 if (cp.le != lmp_host_le_capable(hdev) ||
5935 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005936 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5937 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005938 }
5939
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005940 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005941 /* Make sure the controller has a good default for
5942 * advertising data. This also applies to the case
5943 * where BR/EDR was toggled during the AUTO_OFF phase.
5944 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005945 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005946 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005947 update_scan_rsp_data(&req);
5948 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005949
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005950 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5951 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005952 }
5953
Johan Hedberg70da6242013-03-15 17:06:51 -05005954 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5955 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005956 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5957 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005958
5959 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005960 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5961 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005962 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005963 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005964 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005965 }
5966
Johan Hedberg229ab392013-03-15 17:06:53 -05005967 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005968}
5969
Johan Hedberg744cf192011-11-08 20:40:14 +02005970int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005971{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005972 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005973 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5974 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005975 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005976
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005977 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5978 return 0;
5979
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005980 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005981 if (powered_update_hci(hdev) == 0)
5982 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005983
Johan Hedberg229ab392013-03-15 17:06:53 -05005984 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5985 &match);
5986 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005987 }
5988
Johan Hedberg229ab392013-03-15 17:06:53 -05005989 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5990 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5991
5992 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5993 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5994 zero_cod, sizeof(zero_cod), NULL);
5995
5996new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005997 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005998
5999 if (match.sk)
6000 sock_put(match.sk);
6001
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006002 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006003}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006004
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006005void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006006{
6007 struct pending_cmd *cmd;
6008 u8 status;
6009
6010 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6011 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006012 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006013
6014 if (err == -ERFKILL)
6015 status = MGMT_STATUS_RFKILLED;
6016 else
6017 status = MGMT_STATUS_FAILED;
6018
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006019 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006020
6021 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006022}
6023
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006024void mgmt_discoverable_timeout(struct hci_dev *hdev)
6025{
6026 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006027
6028 hci_dev_lock(hdev);
6029
6030 /* When discoverable timeout triggers, then just make sure
6031 * the limited discoverable flag is cleared. Even in the case
6032 * of a timeout triggered from general discoverable, it is
6033 * safe to unconditionally clear the flag.
6034 */
6035 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006036 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006037
6038 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006039 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6040 u8 scan = SCAN_PAGE;
6041 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6042 sizeof(scan), &scan);
6043 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006044 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006045 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006046 hci_req_run(&req, NULL);
6047
6048 hdev->discov_timeout = 0;
6049
Johan Hedberg9a43e252013-10-20 19:00:07 +03006050 new_settings(hdev, NULL);
6051
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006052 hci_dev_unlock(hdev);
6053}
6054
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006055void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6056 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006057{
Johan Hedberg86742e12011-11-07 23:13:38 +02006058 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006059
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006060 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006061
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006062 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006063 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006064 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006065 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006066 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006067 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006068
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006069 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006070}
Johan Hedbergf7520542011-01-20 12:34:39 +02006071
Johan Hedbergd7b25452014-05-23 13:19:53 +03006072static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6073{
6074 if (ltk->authenticated)
6075 return MGMT_LTK_AUTHENTICATED;
6076
6077 return MGMT_LTK_UNAUTHENTICATED;
6078}
6079
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006080void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006081{
6082 struct mgmt_ev_new_long_term_key ev;
6083
6084 memset(&ev, 0, sizeof(ev));
6085
Marcel Holtmann5192d302014-02-19 17:11:58 -08006086 /* Devices using resolvable or non-resolvable random addresses
6087 * without providing an indentity resolving key don't require
6088 * to store long term keys. Their addresses will change the
6089 * next time around.
6090 *
6091 * Only when a remote device provides an identity address
6092 * make sure the long term key is stored. If the remote
6093 * identity is known, the long term keys are internally
6094 * mapped to the identity address. So allow static random
6095 * and public addresses here.
6096 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006097 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6098 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6099 ev.store_hint = 0x00;
6100 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006101 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006102
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006103 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006104 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006105 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006106 ev.key.enc_size = key->enc_size;
6107 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006108 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006109
Johan Hedberg2ceba532014-06-16 19:25:16 +03006110 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006111 ev.key.master = 1;
6112
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006113 memcpy(ev.key.val, key->val, sizeof(key->val));
6114
Marcel Holtmann083368f2013-10-15 14:26:29 -07006115 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006116}
6117
Johan Hedberg95fbac82014-02-19 15:18:31 +02006118void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6119{
6120 struct mgmt_ev_new_irk ev;
6121
6122 memset(&ev, 0, sizeof(ev));
6123
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006124 /* For identity resolving keys from devices that are already
6125 * using a public address or static random address, do not
6126 * ask for storing this key. The identity resolving key really
6127 * is only mandatory for devices using resovlable random
6128 * addresses.
6129 *
6130 * Storing all identity resolving keys has the downside that
6131 * they will be also loaded on next boot of they system. More
6132 * identity resolving keys, means more time during scanning is
6133 * needed to actually resolve these addresses.
6134 */
6135 if (bacmp(&irk->rpa, BDADDR_ANY))
6136 ev.store_hint = 0x01;
6137 else
6138 ev.store_hint = 0x00;
6139
Johan Hedberg95fbac82014-02-19 15:18:31 +02006140 bacpy(&ev.rpa, &irk->rpa);
6141 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6142 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6143 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6144
6145 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6146}
6147
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006148void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6149 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006150{
6151 struct mgmt_ev_new_csrk ev;
6152
6153 memset(&ev, 0, sizeof(ev));
6154
6155 /* Devices using resolvable or non-resolvable random addresses
6156 * without providing an indentity resolving key don't require
6157 * to store signature resolving keys. Their addresses will change
6158 * the next time around.
6159 *
6160 * Only when a remote device provides an identity address
6161 * make sure the signature resolving key is stored. So allow
6162 * static random and public addresses here.
6163 */
6164 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6165 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6166 ev.store_hint = 0x00;
6167 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006168 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006169
6170 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6171 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6172 ev.key.master = csrk->master;
6173 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6174
6175 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6176}
6177
Andre Guedesffb5a8272014-07-01 18:10:11 -03006178void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006179 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6180 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006181{
6182 struct mgmt_ev_new_conn_param ev;
6183
Johan Hedbergc103aea2014-07-02 17:37:34 +03006184 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6185 return;
6186
Andre Guedesffb5a8272014-07-01 18:10:11 -03006187 memset(&ev, 0, sizeof(ev));
6188 bacpy(&ev.addr.bdaddr, bdaddr);
6189 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006190 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006191 ev.min_interval = cpu_to_le16(min_interval);
6192 ev.max_interval = cpu_to_le16(max_interval);
6193 ev.latency = cpu_to_le16(latency);
6194 ev.timeout = cpu_to_le16(timeout);
6195
6196 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6197}
6198
Marcel Holtmann94933992013-10-15 10:26:39 -07006199static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6200 u8 data_len)
6201{
6202 eir[eir_len++] = sizeof(type) + data_len;
6203 eir[eir_len++] = type;
6204 memcpy(&eir[eir_len], data, data_len);
6205 eir_len += data_len;
6206
6207 return eir_len;
6208}
6209
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006210void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6211 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6212 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006213{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006214 char buf[512];
6215 struct mgmt_ev_device_connected *ev = (void *) buf;
6216 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006217
Johan Hedbergb644ba32012-01-17 21:48:47 +02006218 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006219 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006220
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006221 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006222
Johan Hedbergb644ba32012-01-17 21:48:47 +02006223 if (name_len > 0)
6224 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006225 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006226
6227 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006228 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006229 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006230
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006231 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006232
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006233 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6234 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006235}
6236
Johan Hedberg8962ee72011-01-20 12:40:27 +02006237static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6238{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006239 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006240 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006241 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006242
Johan Hedberg88c3df12012-02-09 14:27:38 +02006243 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6244 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006245
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006246 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006247 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006248
6249 *sk = cmd->sk;
6250 sock_hold(*sk);
6251
Johan Hedberga664b5b2011-02-19 12:06:02 -03006252 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006253}
6254
Johan Hedberg124f6e32012-02-09 13:50:12 +02006255static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006256{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006257 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006258 struct mgmt_cp_unpair_device *cp = cmd->param;
6259 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006260
6261 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006262 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6263 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006264
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006265 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6266
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006267 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006268
6269 mgmt_pending_remove(cmd);
6270}
6271
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006272void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006273 u8 link_type, u8 addr_type, u8 reason,
6274 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006275{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006276 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006277 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006278 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006279
Johan Hedberg8b064a32014-02-24 14:52:22 +02006280 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6281 if (power_off) {
6282 struct mgmt_mode *cp = power_off->param;
6283
6284 /* The connection is still in hci_conn_hash so test for 1
6285 * instead of 0 to know if this is the last one.
6286 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006287 if (!cp->val && hci_conn_count(hdev) == 1) {
6288 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006289 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006290 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006291 }
6292
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006293 if (!mgmt_connected)
6294 return;
6295
Andre Guedes57eb7762013-10-30 19:01:41 -03006296 if (link_type != ACL_LINK && link_type != LE_LINK)
6297 return;
6298
Johan Hedberg744cf192011-11-08 20:40:14 +02006299 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006300
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006301 bacpy(&ev.addr.bdaddr, bdaddr);
6302 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6303 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006304
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006305 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006306
6307 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006308 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006309
Johan Hedberg124f6e32012-02-09 13:50:12 +02006310 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006311 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006312}
6313
Marcel Holtmann78929242013-10-06 23:55:47 -07006314void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6315 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006316{
Andre Guedes3655bba2013-10-30 19:01:40 -03006317 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6318 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006319 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006320 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006321
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006322 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6323 hdev);
6324
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006325 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006326 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006327 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006328
Andre Guedes3655bba2013-10-30 19:01:40 -03006329 cp = cmd->param;
6330
6331 if (bacmp(bdaddr, &cp->addr.bdaddr))
6332 return;
6333
6334 if (cp->addr.type != bdaddr_type)
6335 return;
6336
Johan Hedberg88c3df12012-02-09 14:27:38 +02006337 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006338 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006339
Marcel Holtmann78929242013-10-06 23:55:47 -07006340 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6341 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006342
Johan Hedberga664b5b2011-02-19 12:06:02 -03006343 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006344}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006345
Marcel Holtmann445608d2013-10-06 23:55:48 -07006346void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6347 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006348{
6349 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006350 struct pending_cmd *power_off;
6351
6352 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6353 if (power_off) {
6354 struct mgmt_mode *cp = power_off->param;
6355
6356 /* The connection is still in hci_conn_hash so test for 1
6357 * instead of 0 to know if this is the last one.
6358 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006359 if (!cp->val && hci_conn_count(hdev) == 1) {
6360 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006361 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006362 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006363 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006364
Johan Hedberg4c659c32011-11-07 23:13:39 +02006365 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006366 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006367 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006368
Marcel Holtmann445608d2013-10-06 23:55:48 -07006369 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006370}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006371
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006372void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006373{
6374 struct mgmt_ev_pin_code_request ev;
6375
Johan Hedbergd8457692012-02-17 14:24:57 +02006376 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006377 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006378 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006379
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006380 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006381}
6382
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006383void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6384 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006385{
6386 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006387 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006388
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006389 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006390 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006391 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006392
Johan Hedbergd8457692012-02-17 14:24:57 +02006393 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006394 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006395
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006396 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6397 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006398
Johan Hedberga664b5b2011-02-19 12:06:02 -03006399 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006400}
6401
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006402void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6403 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006404{
6405 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006406 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006407
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006408 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006409 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006410 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006411
Johan Hedbergd8457692012-02-17 14:24:57 +02006412 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006413 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006414
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006415 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6416 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006417
Johan Hedberga664b5b2011-02-19 12:06:02 -03006418 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006419}
Johan Hedberga5c29682011-02-19 12:05:57 -03006420
Johan Hedberg744cf192011-11-08 20:40:14 +02006421int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006422 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006423 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006424{
6425 struct mgmt_ev_user_confirm_request ev;
6426
Johan Hedberg744cf192011-11-08 20:40:14 +02006427 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006428
Johan Hedberg272d90d2012-02-09 15:26:12 +02006429 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006430 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006431 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006432 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006433
Johan Hedberg744cf192011-11-08 20:40:14 +02006434 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006435 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006436}
6437
Johan Hedberg272d90d2012-02-09 15:26:12 +02006438int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006439 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006440{
6441 struct mgmt_ev_user_passkey_request ev;
6442
6443 BT_DBG("%s", hdev->name);
6444
Johan Hedberg272d90d2012-02-09 15:26:12 +02006445 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006446 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006447
6448 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006449 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006450}
6451
Brian Gix0df4c182011-11-16 13:53:13 -08006452static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006453 u8 link_type, u8 addr_type, u8 status,
6454 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006455{
6456 struct pending_cmd *cmd;
6457 struct mgmt_rp_user_confirm_reply rp;
6458 int err;
6459
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006460 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006461 if (!cmd)
6462 return -ENOENT;
6463
Johan Hedberg272d90d2012-02-09 15:26:12 +02006464 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006465 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006466 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006467 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006468
Johan Hedberga664b5b2011-02-19 12:06:02 -03006469 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006470
6471 return err;
6472}
6473
Johan Hedberg744cf192011-11-08 20:40:14 +02006474int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006475 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006476{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006477 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006478 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006479}
6480
Johan Hedberg272d90d2012-02-09 15:26:12 +02006481int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006482 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006483{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006484 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006485 status,
6486 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006487}
Johan Hedberg2a611692011-02-19 12:06:00 -03006488
Brian Gix604086b2011-11-23 08:28:33 -08006489int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006490 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006491{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006492 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006493 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006494}
6495
Johan Hedberg272d90d2012-02-09 15:26:12 +02006496int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006497 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006498{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006499 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006500 status,
6501 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006502}
6503
Johan Hedberg92a25252012-09-06 18:39:26 +03006504int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6505 u8 link_type, u8 addr_type, u32 passkey,
6506 u8 entered)
6507{
6508 struct mgmt_ev_passkey_notify ev;
6509
6510 BT_DBG("%s", hdev->name);
6511
6512 bacpy(&ev.addr.bdaddr, bdaddr);
6513 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6514 ev.passkey = __cpu_to_le32(passkey);
6515 ev.entered = entered;
6516
6517 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6518}
6519
Marcel Holtmanne5460992013-10-15 14:26:23 -07006520void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6521 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006522{
6523 struct mgmt_ev_auth_failed ev;
6524
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006525 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006526 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006527 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006528
Marcel Holtmanne5460992013-10-15 14:26:23 -07006529 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006530}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006531
Marcel Holtmann464996a2013-10-15 14:26:24 -07006532void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006533{
6534 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006535 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006536
6537 if (status) {
6538 u8 mgmt_err = mgmt_status(status);
6539 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006540 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006541 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006542 }
6543
Marcel Holtmann464996a2013-10-15 14:26:24 -07006544 if (test_bit(HCI_AUTH, &hdev->flags))
6545 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6546 &hdev->dev_flags);
6547 else
6548 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6549 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006550
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006551 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006552 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006553
Johan Hedberg47990ea2012-02-22 11:58:37 +02006554 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006555 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006556
6557 if (match.sk)
6558 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006559}
6560
Johan Hedberg890ea892013-03-15 17:06:52 -05006561static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006562{
Johan Hedberg890ea892013-03-15 17:06:52 -05006563 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006564 struct hci_cp_write_eir cp;
6565
Johan Hedberg976eb202012-10-24 21:12:01 +03006566 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006567 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006568
Johan Hedbergc80da272012-02-22 15:38:48 +02006569 memset(hdev->eir, 0, sizeof(hdev->eir));
6570
Johan Hedbergcacaf522012-02-21 00:52:42 +02006571 memset(&cp, 0, sizeof(cp));
6572
Johan Hedberg890ea892013-03-15 17:06:52 -05006573 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006574}
6575
Marcel Holtmann3e248562013-10-15 14:26:25 -07006576void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006577{
6578 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006579 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006580 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006581
6582 if (status) {
6583 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006584
6585 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006586 &hdev->dev_flags)) {
6587 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006588 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006589 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006590
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006591 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6592 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006593 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006594 }
6595
6596 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006597 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006598 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006599 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6600 if (!changed)
6601 changed = test_and_clear_bit(HCI_HS_ENABLED,
6602 &hdev->dev_flags);
6603 else
6604 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006605 }
6606
6607 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6608
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006609 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006610 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006611
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006612 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006613 sock_put(match.sk);
6614
Johan Hedberg890ea892013-03-15 17:06:52 -05006615 hci_req_init(&req, hdev);
6616
Johan Hedberg37699722014-06-24 14:00:27 +03006617 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6618 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6619 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6620 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006621 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006622 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006623 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006624 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006625
6626 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006627}
6628
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006629void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6630{
6631 struct cmd_lookup match = { NULL, hdev };
6632 bool changed = false;
6633
6634 if (status) {
6635 u8 mgmt_err = mgmt_status(status);
6636
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006637 if (enable) {
6638 if (test_and_clear_bit(HCI_SC_ENABLED,
6639 &hdev->dev_flags))
6640 new_settings(hdev, NULL);
6641 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6642 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006643
6644 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6645 cmd_status_rsp, &mgmt_err);
6646 return;
6647 }
6648
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006649 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006650 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006651 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006652 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006653 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6654 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006655
6656 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6657 settings_rsp, &match);
6658
6659 if (changed)
6660 new_settings(hdev, match.sk);
6661
6662 if (match.sk)
6663 sock_put(match.sk);
6664}
6665
Johan Hedberg92da6092013-03-15 17:06:55 -05006666static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006667{
6668 struct cmd_lookup *match = data;
6669
Johan Hedberg90e70452012-02-23 23:09:40 +02006670 if (match->sk == NULL) {
6671 match->sk = cmd->sk;
6672 sock_hold(match->sk);
6673 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006674}
6675
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006676void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6677 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006678{
Johan Hedberg90e70452012-02-23 23:09:40 +02006679 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006680
Johan Hedberg92da6092013-03-15 17:06:55 -05006681 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6682 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6683 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006684
6685 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006686 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6687 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006688
6689 if (match.sk)
6690 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006691}
6692
Marcel Holtmann7667da32013-10-15 14:26:27 -07006693void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006694{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006695 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006696 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006697
Johan Hedberg13928972013-03-15 17:07:00 -05006698 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006699 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006700
6701 memset(&ev, 0, sizeof(ev));
6702 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006703 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006704
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006705 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006706 if (!cmd) {
6707 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006708
Johan Hedberg13928972013-03-15 17:07:00 -05006709 /* If this is a HCI command related to powering on the
6710 * HCI dev don't send any mgmt signals.
6711 */
6712 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006713 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006714 }
6715
Marcel Holtmann7667da32013-10-15 14:26:27 -07006716 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6717 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006718}
Szymon Jancc35938b2011-03-22 13:12:21 +01006719
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006720void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6721 u8 *randomizer192, u8 *hash256,
6722 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006723{
6724 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006725
Johan Hedberg744cf192011-11-08 20:40:14 +02006726 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006727
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006728 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006729 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006730 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006731
6732 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006733 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6734 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006735 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006736 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6737 hash256 && randomizer256) {
6738 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006739
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006740 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6741 memcpy(rp.randomizer192, randomizer192,
6742 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006743
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006744 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6745 memcpy(rp.randomizer256, randomizer256,
6746 sizeof(rp.randomizer256));
6747
6748 cmd_complete(cmd->sk, hdev->id,
6749 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6750 &rp, sizeof(rp));
6751 } else {
6752 struct mgmt_rp_read_local_oob_data rp;
6753
6754 memcpy(rp.hash, hash192, sizeof(rp.hash));
6755 memcpy(rp.randomizer, randomizer192,
6756 sizeof(rp.randomizer));
6757
6758 cmd_complete(cmd->sk, hdev->id,
6759 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6760 &rp, sizeof(rp));
6761 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006762 }
6763
6764 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006765}
Johan Hedberge17acd42011-03-30 23:57:16 +03006766
Marcel Holtmann901801b2013-10-06 23:55:51 -07006767void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006768 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6769 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006770{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006771 char buf[512];
6772 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006773 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006774
Johan Hedberg75ce2082014-07-02 22:42:01 +03006775 /* Don't send events for a non-kernel initiated discovery. With
6776 * LE one exception is if we have pend_le_reports > 0 in which
6777 * case we're doing passive scanning and want these events.
6778 */
6779 if (!hci_discovery_active(hdev)) {
6780 if (link_type == ACL_LINK)
6781 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006782 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006783 return;
6784 }
Andre Guedes12602d02013-04-30 15:29:40 -03006785
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006786 /* Make sure that the buffer is big enough. The 5 extra bytes
6787 * are for the potential CoD field.
6788 */
6789 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006790 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006791
Johan Hedberg1dc06092012-01-15 21:01:23 +02006792 memset(buf, 0, sizeof(buf));
6793
Johan Hedberg841c5642014-07-07 12:45:54 +03006794 bacpy(&ev->addr.bdaddr, bdaddr);
6795 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006796 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006797 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006798
Johan Hedberg1dc06092012-01-15 21:01:23 +02006799 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006800 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006801
Johan Hedberg1dc06092012-01-15 21:01:23 +02006802 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6803 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006804 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006805
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006806 if (scan_rsp_len > 0)
6807 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6808
6809 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6810 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006811
Marcel Holtmann901801b2013-10-06 23:55:51 -07006812 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006813}
Johan Hedberga88a9652011-03-30 13:18:12 +03006814
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006815void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6816 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006817{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006818 struct mgmt_ev_device_found *ev;
6819 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6820 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006821
Johan Hedbergb644ba32012-01-17 21:48:47 +02006822 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006823
Johan Hedbergb644ba32012-01-17 21:48:47 +02006824 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006825
Johan Hedbergb644ba32012-01-17 21:48:47 +02006826 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006827 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006828 ev->rssi = rssi;
6829
6830 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006831 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006832
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006833 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006834
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006835 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006836}
Johan Hedberg314b2382011-04-27 10:29:57 -04006837
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006838void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006839{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006840 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006841 struct pending_cmd *cmd;
6842
Andre Guedes343fb142011-11-22 17:14:19 -03006843 BT_DBG("%s discovering %u", hdev->name, discovering);
6844
Johan Hedberg164a6e72011-11-01 17:06:44 +02006845 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006846 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006847 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006848 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006849
6850 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006851 u8 type = hdev->discovery.type;
6852
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006853 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6854 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006855 mgmt_pending_remove(cmd);
6856 }
6857
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006858 memset(&ev, 0, sizeof(ev));
6859 ev.type = hdev->discovery.type;
6860 ev.discovering = discovering;
6861
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006862 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006863}
Antti Julku5e762442011-08-25 16:48:02 +03006864
Marcel Holtmann5976e602013-10-06 04:08:14 -07006865static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6866{
6867 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006868}
6869
6870void mgmt_reenable_advertising(struct hci_dev *hdev)
6871{
6872 struct hci_request req;
6873
Marcel Holtmann5976e602013-10-06 04:08:14 -07006874 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6875 return;
6876
6877 hci_req_init(&req, hdev);
6878 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006879 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006880}