blob: 944e6463fd6148e6ddf567f740c4c52597aaeeac [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200132#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
133 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
134
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135struct pending_cmd {
136 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200137 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100139 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200558
Andre Guedesed3fa312012-07-24 15:03:46 -0300559 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300560 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500561 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
562 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300563 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200580 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200582
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200583 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
584 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585 settings |= MGMT_SETTING_CONFIGURATION;
586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587 return settings;
588}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200589
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200590static u32 get_current_settings(struct hci_dev *hdev)
591{
592 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200593
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200594 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100595 settings |= MGMT_SETTING_POWERED;
596
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200597 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200598 settings |= MGMT_SETTING_CONNECTABLE;
599
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500600 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
601 settings |= MGMT_SETTING_FAST_CONNECTABLE;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_DISCOVERABLE;
605
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200606 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_PAIRABLE;
608
Johan Hedberg56f87902013-10-02 13:43:13 +0300609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_BREDR;
611
Johan Hedberg06199cf2012-02-22 16:37:11 +0200612 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200614
Johan Hedberg47990ea2012-02-22 11:58:37 +0200615 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200617
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200618 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200620
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200621 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
622 settings |= MGMT_SETTING_HS;
623
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200624 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300625 settings |= MGMT_SETTING_ADVERTISING;
626
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_SECURE_CONN;
629
Johan Hedberg0663b292014-06-24 13:15:50 +0300630 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800631 settings |= MGMT_SETTING_DEBUG_KEYS;
632
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200633 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
634 settings |= MGMT_SETTING_PRIVACY;
635
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200636 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200637}
638
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300639#define PNP_INFO_SVCLASS_ID 0x1200
640
Johan Hedberg213202e2013-01-27 00:31:33 +0200641static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
642{
643 u8 *ptr = data, *uuids_start = NULL;
644 struct bt_uuid *uuid;
645
646 if (len < 4)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 u16 uuid16;
651
652 if (uuid->size != 16)
653 continue;
654
655 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
656 if (uuid16 < 0x1100)
657 continue;
658
659 if (uuid16 == PNP_INFO_SVCLASS_ID)
660 continue;
661
662 if (!uuids_start) {
663 uuids_start = ptr;
664 uuids_start[0] = 1;
665 uuids_start[1] = EIR_UUID16_ALL;
666 ptr += 2;
667 }
668
669 /* Stop if not enough space to put next UUID */
670 if ((ptr - data) + sizeof(u16) > len) {
671 uuids_start[1] = EIR_UUID16_SOME;
672 break;
673 }
674
675 *ptr++ = (uuid16 & 0x00ff);
676 *ptr++ = (uuid16 & 0xff00) >> 8;
677 uuids_start[0] += sizeof(uuid16);
678 }
679
680 return ptr;
681}
682
Johan Hedbergcdf19632013-01-27 00:31:34 +0200683static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
684{
685 u8 *ptr = data, *uuids_start = NULL;
686 struct bt_uuid *uuid;
687
688 if (len < 6)
689 return ptr;
690
691 list_for_each_entry(uuid, &hdev->uuids, list) {
692 if (uuid->size != 32)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID32_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u32) > len) {
704 uuids_start[1] = EIR_UUID32_SOME;
705 break;
706 }
707
708 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
709 ptr += sizeof(u32);
710 uuids_start[0] += sizeof(u32);
711 }
712
713 return ptr;
714}
715
Johan Hedbergc00d5752013-01-27 00:31:35 +0200716static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 18)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 128)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID128_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + 16 > len) {
737 uuids_start[1] = EIR_UUID128_SOME;
738 break;
739 }
740
741 memcpy(ptr, uuid->uuid, 16);
742 ptr += 16;
743 uuids_start[0] += 16;
744 }
745
746 return ptr;
747}
748
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300749static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
750{
751 struct pending_cmd *cmd;
752
753 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
754 if (cmd->opcode == opcode)
755 return cmd;
756 }
757
758 return NULL;
759}
760
Johan Hedberg95868422014-06-28 17:54:07 +0300761static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
762 struct hci_dev *hdev,
763 const void *data)
764{
765 struct pending_cmd *cmd;
766
767 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
768 if (cmd->user_data != data)
769 continue;
770 if (cmd->opcode == opcode)
771 return cmd;
772 }
773
774 return NULL;
775}
776
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700777static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
778{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700779 u8 ad_len = 0;
780 size_t name_len;
781
782 name_len = strlen(hdev->dev_name);
783 if (name_len > 0) {
784 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
785
786 if (name_len > max_len) {
787 name_len = max_len;
788 ptr[1] = EIR_NAME_SHORT;
789 } else
790 ptr[1] = EIR_NAME_COMPLETE;
791
792 ptr[0] = name_len + 1;
793
794 memcpy(ptr + 2, hdev->dev_name, name_len);
795
796 ad_len += (name_len + 2);
797 ptr += (name_len + 2);
798 }
799
800 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700801}
802
803static void update_scan_rsp_data(struct hci_request *req)
804{
805 struct hci_dev *hdev = req->hdev;
806 struct hci_cp_le_set_scan_rsp_data cp;
807 u8 len;
808
Johan Hedberg7751ef12013-10-19 23:38:15 +0300809 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700810 return;
811
812 memset(&cp, 0, sizeof(cp));
813
814 len = create_scan_rsp_data(hdev, cp.data);
815
Johan Hedbergeb438b52013-10-16 15:31:07 +0300816 if (hdev->scan_rsp_data_len == len &&
817 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700818 return;
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
821 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822
823 cp.length = len;
824
825 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
826}
827
Johan Hedberg9a43e252013-10-20 19:00:07 +0300828static u8 get_adv_discov_flags(struct hci_dev *hdev)
829{
830 struct pending_cmd *cmd;
831
832 /* If there's a pending mgmt command the flags will not yet have
833 * their final values, so check for this first.
834 */
835 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
836 if (cmd) {
837 struct mgmt_mode *cp = cmd->param;
838 if (cp->val == 0x01)
839 return LE_AD_GENERAL;
840 else if (cp->val == 0x02)
841 return LE_AD_LIMITED;
842 } else {
843 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_LIMITED;
845 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_GENERAL;
847 }
848
849 return 0;
850}
851
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700852static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853{
854 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberg9a43e252013-10-20 19:00:07 +0300856 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberge8340042014-01-30 11:16:50 -0800858 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
861 if (flags) {
862 BT_DBG("adv flags 0x%02x", flags);
863
864 ptr[0] = 2;
865 ptr[1] = EIR_FLAGS;
866 ptr[2] = flags;
867
868 ad_len += 3;
869 ptr += 3;
870 }
871
872 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
873 ptr[0] = 2;
874 ptr[1] = EIR_TX_POWER;
875 ptr[2] = (u8) hdev->adv_tx_power;
876
877 ad_len += 3;
878 ptr += 3;
879 }
880
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700881 return ad_len;
882}
883
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700884static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885{
886 struct hci_dev *hdev = req->hdev;
887 struct hci_cp_le_set_adv_data cp;
888 u8 len;
889
Johan Hedberg10994ce2013-10-19 23:38:16 +0300890 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891 return;
892
893 memset(&cp, 0, sizeof(cp));
894
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700895 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896
897 if (hdev->adv_data_len == len &&
898 memcmp(cp.data, hdev->adv_data, len) == 0)
899 return;
900
901 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
902 hdev->adv_data_len = len;
903
904 cp.length = len;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
907}
908
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300909static void create_eir(struct hci_dev *hdev, u8 *data)
910{
911 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300912 size_t name_len;
913
914 name_len = strlen(hdev->dev_name);
915
916 if (name_len > 0) {
917 /* EIR Data type */
918 if (name_len > 48) {
919 name_len = 48;
920 ptr[1] = EIR_NAME_SHORT;
921 } else
922 ptr[1] = EIR_NAME_COMPLETE;
923
924 /* EIR Data length */
925 ptr[0] = name_len + 1;
926
927 memcpy(ptr + 2, hdev->dev_name, name_len);
928
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300929 ptr += (name_len + 2);
930 }
931
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100932 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700933 ptr[0] = 2;
934 ptr[1] = EIR_TX_POWER;
935 ptr[2] = (u8) hdev->inq_tx_power;
936
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700937 ptr += 3;
938 }
939
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700940 if (hdev->devid_source > 0) {
941 ptr[0] = 9;
942 ptr[1] = EIR_DEVICE_ID;
943
944 put_unaligned_le16(hdev->devid_source, ptr + 2);
945 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
946 put_unaligned_le16(hdev->devid_product, ptr + 6);
947 put_unaligned_le16(hdev->devid_version, ptr + 8);
948
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700949 ptr += 10;
950 }
951
Johan Hedberg213202e2013-01-27 00:31:33 +0200952 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200953 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200954 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300955}
956
Johan Hedberg890ea892013-03-15 17:06:52 -0500957static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300958{
Johan Hedberg890ea892013-03-15 17:06:52 -0500959 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300960 struct hci_cp_write_eir cp;
961
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200962 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500963 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200964
Johan Hedberg976eb202012-10-24 21:12:01 +0300965 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500966 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200968 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200971 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500972 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973
974 memset(&cp, 0, sizeof(cp));
975
976 create_eir(hdev, cp.data);
977
978 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
981 memcpy(hdev->eir, cp.data, sizeof(cp.data));
982
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984}
985
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200986static u8 get_service_classes(struct hci_dev *hdev)
987{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300988 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200989 u8 val = 0;
990
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300991 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200992 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200993
994 return val;
995}
996
Johan Hedberg890ea892013-03-15 17:06:52 -0500997static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200998{
Johan Hedberg890ea892013-03-15 17:06:52 -0500999 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 cod[3];
1001
1002 BT_DBG("%s", hdev->name);
1003
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001004 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001005 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001006
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001007 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1008 return;
1009
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001010 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001011 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001012
1013 cod[0] = hdev->minor_class;
1014 cod[1] = hdev->major_class;
1015 cod[2] = get_service_classes(hdev);
1016
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001017 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1018 cod[1] |= 0x20;
1019
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001020 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001024}
1025
Johan Hedberga4858cb2014-02-25 19:56:31 +02001026static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001027{
1028 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001029
1030 /* If there's a pending mgmt command the flag will not yet have
1031 * it's final value, so check for this first.
1032 */
1033 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1034 if (cmd) {
1035 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037 }
1038
Johan Hedberga4858cb2014-02-25 19:56:31 +02001039 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040}
1041
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001042static void disable_advertising(struct hci_request *req)
1043{
1044 u8 enable = 0x00;
1045
1046 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1047}
1048
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001049static void enable_advertising(struct hci_request *req)
1050{
1051 struct hci_dev *hdev = req->hdev;
1052 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001053 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001054 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001055
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001056 if (hci_conn_num(hdev, LE_LINK) > 0)
1057 return;
1058
1059 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1060 disable_advertising(req);
1061
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001062 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001063 * hci_update_random_address knows that it's safe to go ahead
1064 * and write a new random address. The flag will be set back on
1065 * as soon as the SET_ADV_ENABLE HCI command completes.
1066 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001067 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001068
Johan Hedberga4858cb2014-02-25 19:56:31 +02001069 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001070
Johan Hedberga4858cb2014-02-25 19:56:31 +02001071 /* Set require_privacy to true only when non-connectable
1072 * advertising is used. In that case it is fine to use a
1073 * non-resolvable private address.
1074 */
1075 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001076 return;
1077
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001078 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001079 cp.min_interval = cpu_to_le16(0x0800);
1080 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001081 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001082 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001083 cp.channel_map = hdev->le_adv_channel_map;
1084
1085 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1086
1087 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1088}
1089
Johan Hedberg7d785252011-12-15 00:47:39 +02001090static void service_cache_off(struct work_struct *work)
1091{
1092 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001093 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001094 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001095
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001096 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001097 return;
1098
Johan Hedberg890ea892013-03-15 17:06:52 -05001099 hci_req_init(&req, hdev);
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101 hci_dev_lock(hdev);
1102
Johan Hedberg890ea892013-03-15 17:06:52 -05001103 update_eir(&req);
1104 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001105
1106 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001107
1108 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001109}
1110
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001111static void rpa_expired(struct work_struct *work)
1112{
1113 struct hci_dev *hdev = container_of(work, struct hci_dev,
1114 rpa_expired.work);
1115 struct hci_request req;
1116
1117 BT_DBG("");
1118
1119 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1120
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001121 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122 return;
1123
1124 /* The generation of a new RPA and programming it into the
1125 * controller happens in the enable_advertising() function.
1126 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001127 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001128 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001129 hci_req_run(&req, NULL);
1130}
1131
Johan Hedberg6a919082012-02-28 06:17:26 +02001132static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001133{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001134 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001135 return;
1136
Johan Hedberg4f87da82012-03-02 19:55:56 +02001137 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001139
Johan Hedberg4f87da82012-03-02 19:55:56 +02001140 /* Non-mgmt controlled devices get this bit set
1141 * implicitly so that pairing works for them, however
1142 * for mgmt we require user-space to explicitly enable
1143 * it
1144 */
1145 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001146}
1147
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001148static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001149 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001150{
1151 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001152
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001153 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001154
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001155 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001156
Johan Hedberg03811012010-12-08 00:21:06 +02001157 memset(&rp, 0, sizeof(rp));
1158
Johan Hedberg03811012010-12-08 00:21:06 +02001159 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001160
1161 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001162 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001163
1164 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1165 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1166
1167 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001168
1169 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001170 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001171
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001172 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001174 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001175 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001176}
1177
1178static void mgmt_pending_free(struct pending_cmd *cmd)
1179{
1180 sock_put(cmd->sk);
1181 kfree(cmd->param);
1182 kfree(cmd);
1183}
1184
1185static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 struct hci_dev *hdev, void *data,
1187 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001188{
1189 struct pending_cmd *cmd;
1190
Johan Hedbergfca20012014-06-28 17:54:05 +03001191 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001192 if (!cmd)
1193 return NULL;
1194
1195 cmd->opcode = opcode;
1196 cmd->index = hdev->id;
1197
Andre Guedes12b94562012-06-07 19:05:45 -03001198 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001199 if (!cmd->param) {
1200 kfree(cmd);
1201 return NULL;
1202 }
1203
1204 if (data)
1205 memcpy(cmd->param, data, len);
1206
1207 cmd->sk = sk;
1208 sock_hold(sk);
1209
1210 list_add(&cmd->list, &hdev->mgmt_pending);
1211
1212 return cmd;
1213}
1214
1215static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001216 void (*cb)(struct pending_cmd *cmd,
1217 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001218 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001219{
Andre Guedesa3d09352013-02-01 11:21:30 -03001220 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001221
Andre Guedesa3d09352013-02-01 11:21:30 -03001222 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001223 if (opcode > 0 && cmd->opcode != opcode)
1224 continue;
1225
1226 cb(cmd, data);
1227 }
1228}
1229
Johan Hedberg03811012010-12-08 00:21:06 +02001230static void mgmt_pending_remove(struct pending_cmd *cmd)
1231{
1232 list_del(&cmd->list);
1233 mgmt_pending_free(cmd);
1234}
1235
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001236static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001237{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001238 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001239
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001240 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001241 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001242}
1243
Johan Hedberg8b064a32014-02-24 14:52:22 +02001244static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1245{
1246 BT_DBG("%s status 0x%02x", hdev->name, status);
1247
Johan Hedberga3172b72014-02-28 09:33:44 +02001248 if (hci_conn_count(hdev) == 0) {
1249 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001250 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001251 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001252}
1253
Johan Hedberg21a60d32014-06-10 14:05:58 +03001254static void hci_stop_discovery(struct hci_request *req)
1255{
1256 struct hci_dev *hdev = req->hdev;
1257 struct hci_cp_remote_name_req_cancel cp;
1258 struct inquiry_entry *e;
1259
1260 switch (hdev->discovery.state) {
1261 case DISCOVERY_FINDING:
1262 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1263 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1264 } else {
1265 cancel_delayed_work(&hdev->le_scan_disable);
1266 hci_req_add_le_scan_disable(req);
1267 }
1268
1269 break;
1270
1271 case DISCOVERY_RESOLVING:
1272 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1273 NAME_PENDING);
1274 if (!e)
1275 return;
1276
1277 bacpy(&cp.bdaddr, &e->data.bdaddr);
1278 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1279 &cp);
1280
1281 break;
1282
1283 default:
1284 /* Passive scanning */
1285 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1286 hci_req_add_le_scan_disable(req);
1287 break;
1288 }
1289}
1290
Johan Hedberg8b064a32014-02-24 14:52:22 +02001291static int clean_up_hci_state(struct hci_dev *hdev)
1292{
1293 struct hci_request req;
1294 struct hci_conn *conn;
1295
1296 hci_req_init(&req, hdev);
1297
1298 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1299 test_bit(HCI_PSCAN, &hdev->flags)) {
1300 u8 scan = 0x00;
1301 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1302 }
1303
Johan Hedberg73e082f2014-07-08 15:07:51 +03001304 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001305 disable_advertising(&req);
1306
Johan Hedbergf8680f12014-06-10 14:05:59 +03001307 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001308
1309 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1310 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001311 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
Johan Hedbergc9910d02014-02-27 14:35:12 +02001313 switch (conn->state) {
1314 case BT_CONNECTED:
1315 case BT_CONFIG:
1316 dc.handle = cpu_to_le16(conn->handle);
1317 dc.reason = 0x15; /* Terminated due to Power Off */
1318 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1319 break;
1320 case BT_CONNECT:
1321 if (conn->type == LE_LINK)
1322 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1323 0, NULL);
1324 else if (conn->type == ACL_LINK)
1325 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1326 6, &conn->dst);
1327 break;
1328 case BT_CONNECT2:
1329 bacpy(&rej.bdaddr, &conn->dst);
1330 rej.reason = 0x15; /* Terminated due to Power Off */
1331 if (conn->type == ACL_LINK)
1332 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1333 sizeof(rej), &rej);
1334 else if (conn->type == SCO_LINK)
1335 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1336 sizeof(rej), &rej);
1337 break;
1338 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001339 }
1340
1341 return hci_req_run(&req, clean_up_hci_complete);
1342}
1343
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001344static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001345 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001346{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001347 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001348 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001349 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001350
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001351 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001352
Johan Hedberga7e80f22013-01-09 16:05:19 +02001353 if (cp->val != 0x00 && cp->val != 0x01)
1354 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1355 MGMT_STATUS_INVALID_PARAMS);
1356
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001357 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001358
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001359 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1360 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1361 MGMT_STATUS_BUSY);
1362 goto failed;
1363 }
1364
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001365 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1366 cancel_delayed_work(&hdev->power_off);
1367
1368 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001369 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1370 data, len);
1371 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001372 goto failed;
1373 }
1374 }
1375
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001376 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001377 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001378 goto failed;
1379 }
1380
Johan Hedberg03811012010-12-08 00:21:06 +02001381 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1382 if (!cmd) {
1383 err = -ENOMEM;
1384 goto failed;
1385 }
1386
Johan Hedberg8b064a32014-02-24 14:52:22 +02001387 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001388 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001389 err = 0;
1390 } else {
1391 /* Disconnect connections, stop scans, etc */
1392 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001393 if (!err)
1394 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1395 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001396
Johan Hedberg8b064a32014-02-24 14:52:22 +02001397 /* ENODATA means there were no HCI commands queued */
1398 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001399 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001400 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1401 err = 0;
1402 }
1403 }
Johan Hedberg03811012010-12-08 00:21:06 +02001404
1405failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001406 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001407 return err;
1408}
1409
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001410static int new_settings(struct hci_dev *hdev, struct sock *skip)
1411{
1412 __le32 ev;
1413
1414 ev = cpu_to_le32(get_current_settings(hdev));
1415
1416 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1417}
1418
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001419struct cmd_lookup {
1420 struct sock *sk;
1421 struct hci_dev *hdev;
1422 u8 mgmt_status;
1423};
1424
1425static void settings_rsp(struct pending_cmd *cmd, void *data)
1426{
1427 struct cmd_lookup *match = data;
1428
1429 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1430
1431 list_del(&cmd->list);
1432
1433 if (match->sk == NULL) {
1434 match->sk = cmd->sk;
1435 sock_hold(match->sk);
1436 }
1437
1438 mgmt_pending_free(cmd);
1439}
1440
1441static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1442{
1443 u8 *status = data;
1444
1445 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1446 mgmt_pending_remove(cmd);
1447}
1448
Johan Hedberge6fe7982013-10-02 15:45:22 +03001449static u8 mgmt_bredr_support(struct hci_dev *hdev)
1450{
1451 if (!lmp_bredr_capable(hdev))
1452 return MGMT_STATUS_NOT_SUPPORTED;
1453 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1454 return MGMT_STATUS_REJECTED;
1455 else
1456 return MGMT_STATUS_SUCCESS;
1457}
1458
1459static u8 mgmt_le_support(struct hci_dev *hdev)
1460{
1461 if (!lmp_le_capable(hdev))
1462 return MGMT_STATUS_NOT_SUPPORTED;
1463 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1464 return MGMT_STATUS_REJECTED;
1465 else
1466 return MGMT_STATUS_SUCCESS;
1467}
1468
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001469static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1470{
1471 struct pending_cmd *cmd;
1472 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001473 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001474 bool changed;
1475
1476 BT_DBG("status 0x%02x", status);
1477
1478 hci_dev_lock(hdev);
1479
1480 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1481 if (!cmd)
1482 goto unlock;
1483
1484 if (status) {
1485 u8 mgmt_err = mgmt_status(status);
1486 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001487 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001488 goto remove_cmd;
1489 }
1490
1491 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001492 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001493 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1494 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001495
1496 if (hdev->discov_timeout > 0) {
1497 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1498 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1499 to);
1500 }
1501 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001502 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1503 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001504 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001505
1506 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1507
1508 if (changed)
1509 new_settings(hdev, cmd->sk);
1510
Marcel Holtmann970ba522013-10-15 06:33:57 -07001511 /* When the discoverable mode gets changed, make sure
1512 * that class of device has the limited discoverable
1513 * bit correctly set.
1514 */
1515 hci_req_init(&req, hdev);
1516 update_class(&req);
1517 hci_req_run(&req, NULL);
1518
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001519remove_cmd:
1520 mgmt_pending_remove(cmd);
1521
1522unlock:
1523 hci_dev_unlock(hdev);
1524}
1525
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001526static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001527 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001528{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001529 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001530 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001531 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001532 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001533 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001534 int err;
1535
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001536 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001537
Johan Hedberg9a43e252013-10-20 19:00:07 +03001538 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1539 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001540 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001541 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001542
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001543 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001544 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1545 MGMT_STATUS_INVALID_PARAMS);
1546
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001547 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001548
1549 /* Disabling discoverable requires that no timeout is set,
1550 * and enabling limited discoverable requires a timeout.
1551 */
1552 if ((cp->val == 0x00 && timeout > 0) ||
1553 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001554 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001555 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001556
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001557 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001558
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001559 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001560 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001561 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001562 goto failed;
1563 }
1564
1565 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001566 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001567 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001568 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001569 goto failed;
1570 }
1571
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001572 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001573 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001574 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001575 goto failed;
1576 }
1577
1578 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001579 bool changed = false;
1580
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001581 /* Setting limited discoverable when powered off is
1582 * not a valid operation since it requires a timeout
1583 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1584 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001585 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1586 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1587 changed = true;
1588 }
1589
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001590 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001591 if (err < 0)
1592 goto failed;
1593
1594 if (changed)
1595 err = new_settings(hdev, sk);
1596
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001597 goto failed;
1598 }
1599
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001600 /* If the current mode is the same, then just update the timeout
1601 * value with the new value. And if only the timeout gets updated,
1602 * then no need for any HCI transactions.
1603 */
1604 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1605 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1606 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001607 cancel_delayed_work(&hdev->discov_off);
1608 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001609
Marcel Holtmann36261542013-10-15 08:28:51 -07001610 if (cp->val && hdev->discov_timeout > 0) {
1611 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001612 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001613 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001614 }
1615
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001616 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001617 goto failed;
1618 }
1619
1620 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1621 if (!cmd) {
1622 err = -ENOMEM;
1623 goto failed;
1624 }
1625
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001626 /* Cancel any potential discoverable timeout that might be
1627 * still active and store new timeout value. The arming of
1628 * the timeout happens in the complete handler.
1629 */
1630 cancel_delayed_work(&hdev->discov_off);
1631 hdev->discov_timeout = timeout;
1632
Johan Hedbergb456f872013-10-19 23:38:22 +03001633 /* Limited discoverable mode */
1634 if (cp->val == 0x02)
1635 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1636 else
1637 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1638
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001639 hci_req_init(&req, hdev);
1640
Johan Hedberg9a43e252013-10-20 19:00:07 +03001641 /* The procedure for LE-only controllers is much simpler - just
1642 * update the advertising data.
1643 */
1644 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1645 goto update_ad;
1646
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001647 scan = SCAN_PAGE;
1648
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001649 if (cp->val) {
1650 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001651
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001652 if (cp->val == 0x02) {
1653 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001654 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001655 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1656 hci_cp.iac_lap[1] = 0x8b;
1657 hci_cp.iac_lap[2] = 0x9e;
1658 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1659 hci_cp.iac_lap[4] = 0x8b;
1660 hci_cp.iac_lap[5] = 0x9e;
1661 } else {
1662 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001663 hci_cp.num_iac = 1;
1664 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1665 hci_cp.iac_lap[1] = 0x8b;
1666 hci_cp.iac_lap[2] = 0x9e;
1667 }
1668
1669 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1670 (hci_cp.num_iac * 3) + 1, &hci_cp);
1671
1672 scan |= SCAN_INQUIRY;
1673 } else {
1674 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1675 }
1676
1677 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001678
Johan Hedberg9a43e252013-10-20 19:00:07 +03001679update_ad:
1680 update_adv_data(&req);
1681
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001682 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001683 if (err < 0)
1684 mgmt_pending_remove(cmd);
1685
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001686failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001687 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001688 return err;
1689}
1690
Johan Hedberg406d7802013-03-15 17:07:09 -05001691static void write_fast_connectable(struct hci_request *req, bool enable)
1692{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001693 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001694 struct hci_cp_write_page_scan_activity acp;
1695 u8 type;
1696
Johan Hedberg547003b2013-10-21 16:51:53 +03001697 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1698 return;
1699
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001700 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1701 return;
1702
Johan Hedberg406d7802013-03-15 17:07:09 -05001703 if (enable) {
1704 type = PAGE_SCAN_TYPE_INTERLACED;
1705
1706 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001707 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001708 } else {
1709 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1710
1711 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001712 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001713 }
1714
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001715 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001716
Johan Hedbergbd98b992013-03-15 17:07:13 -05001717 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1718 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1719 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1720 sizeof(acp), &acp);
1721
1722 if (hdev->page_scan_type != type)
1723 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001724}
1725
Johan Hedberg2b76f452013-03-15 17:07:04 -05001726static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1727{
1728 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001729 struct mgmt_mode *cp;
1730 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001731
1732 BT_DBG("status 0x%02x", status);
1733
1734 hci_dev_lock(hdev);
1735
1736 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1737 if (!cmd)
1738 goto unlock;
1739
Johan Hedberg37438c12013-10-14 16:20:05 +03001740 if (status) {
1741 u8 mgmt_err = mgmt_status(status);
1742 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1743 goto remove_cmd;
1744 }
1745
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001746 cp = cmd->param;
1747 if (cp->val)
1748 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1749 else
1750 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1751
Johan Hedberg2b76f452013-03-15 17:07:04 -05001752 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1753
Johan Hedberg2b7be332014-07-07 14:40:22 +03001754 if (changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001755 new_settings(hdev, cmd->sk);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001756 hci_update_background_scan(hdev);
1757 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001758
Johan Hedberg37438c12013-10-14 16:20:05 +03001759remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001760 mgmt_pending_remove(cmd);
1761
1762unlock:
1763 hci_dev_unlock(hdev);
1764}
1765
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001766static int set_connectable_update_settings(struct hci_dev *hdev,
1767 struct sock *sk, u8 val)
1768{
1769 bool changed = false;
1770 int err;
1771
1772 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1773 changed = true;
1774
1775 if (val) {
1776 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1777 } else {
1778 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1779 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1780 }
1781
1782 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1783 if (err < 0)
1784 return err;
1785
1786 if (changed)
1787 return new_settings(hdev, sk);
1788
1789 return 0;
1790}
1791
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001792static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001793 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001794{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001795 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001796 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001797 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001798 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001799 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001800
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001801 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001802
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001803 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1804 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001805 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001806 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001807
Johan Hedberga7e80f22013-01-09 16:05:19 +02001808 if (cp->val != 0x00 && cp->val != 0x01)
1809 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1810 MGMT_STATUS_INVALID_PARAMS);
1811
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001812 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001813
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001814 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001815 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001816 goto failed;
1817 }
1818
1819 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001820 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001821 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001822 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001823 goto failed;
1824 }
1825
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001826 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1827 if (!cmd) {
1828 err = -ENOMEM;
1829 goto failed;
1830 }
1831
Johan Hedberg2b76f452013-03-15 17:07:04 -05001832 hci_req_init(&req, hdev);
1833
Johan Hedberg9a43e252013-10-20 19:00:07 +03001834 /* If BR/EDR is not enabled and we disable advertising as a
1835 * by-product of disabling connectable, we need to update the
1836 * advertising flags.
1837 */
1838 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1839 if (!cp->val) {
1840 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1841 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1842 }
1843 update_adv_data(&req);
1844 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001845 if (cp->val) {
1846 scan = SCAN_PAGE;
1847 } else {
1848 scan = 0;
1849
1850 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001851 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001852 cancel_delayed_work(&hdev->discov_off);
1853 }
1854
1855 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1856 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001857
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001858 /* If we're going from non-connectable to connectable or
1859 * vice-versa when fast connectable is enabled ensure that fast
1860 * connectable gets disabled. write_fast_connectable won't do
1861 * anything if the page scan parameters are already what they
1862 * should be.
1863 */
1864 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001865 write_fast_connectable(&req, false);
1866
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001867 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001868 !test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001870
Johan Hedberg2b76f452013-03-15 17:07:04 -05001871 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001872 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001873 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001874 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001875 err = set_connectable_update_settings(hdev, sk,
1876 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001877 goto failed;
1878 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
1880failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001881 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 return err;
1883}
1884
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001885static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001886 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001887{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001888 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001889 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001890 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001891
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001892 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001893
Johan Hedberga7e80f22013-01-09 16:05:19 +02001894 if (cp->val != 0x00 && cp->val != 0x01)
1895 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1896 MGMT_STATUS_INVALID_PARAMS);
1897
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001898 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001899
1900 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001901 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001902 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001903 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001904
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001905 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001906 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001907 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001908
Marcel Holtmann55594352013-10-06 16:11:57 -07001909 if (changed)
1910 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001911
Marcel Holtmann55594352013-10-06 16:11:57 -07001912unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001913 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001914 return err;
1915}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001916
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001917static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1918 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001919{
1920 struct mgmt_mode *cp = data;
1921 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001922 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001923 int err;
1924
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001925 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001926
Johan Hedberge6fe7982013-10-02 15:45:22 +03001927 status = mgmt_bredr_support(hdev);
1928 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001929 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001930 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001931
Johan Hedberga7e80f22013-01-09 16:05:19 +02001932 if (cp->val != 0x00 && cp->val != 0x01)
1933 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1934 MGMT_STATUS_INVALID_PARAMS);
1935
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001936 hci_dev_lock(hdev);
1937
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001938 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001939 bool changed = false;
1940
1941 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001942 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001943 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1944 changed = true;
1945 }
1946
1947 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1948 if (err < 0)
1949 goto failed;
1950
1951 if (changed)
1952 err = new_settings(hdev, sk);
1953
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001954 goto failed;
1955 }
1956
1957 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001958 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001959 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001960 goto failed;
1961 }
1962
1963 val = !!cp->val;
1964
1965 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1966 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1967 goto failed;
1968 }
1969
1970 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1971 if (!cmd) {
1972 err = -ENOMEM;
1973 goto failed;
1974 }
1975
1976 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1977 if (err < 0) {
1978 mgmt_pending_remove(cmd);
1979 goto failed;
1980 }
1981
1982failed:
1983 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001984 return err;
1985}
1986
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001987static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001988{
1989 struct mgmt_mode *cp = data;
1990 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001991 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001992 int err;
1993
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001994 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001995
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001996 status = mgmt_bredr_support(hdev);
1997 if (status)
1998 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1999
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002000 if (!lmp_ssp_capable(hdev))
2001 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2002 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002003
Johan Hedberga7e80f22013-01-09 16:05:19 +02002004 if (cp->val != 0x00 && cp->val != 0x01)
2005 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2006 MGMT_STATUS_INVALID_PARAMS);
2007
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002008 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002009
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002010 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002011 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002012
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002013 if (cp->val) {
2014 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2015 &hdev->dev_flags);
2016 } else {
2017 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2018 &hdev->dev_flags);
2019 if (!changed)
2020 changed = test_and_clear_bit(HCI_HS_ENABLED,
2021 &hdev->dev_flags);
2022 else
2023 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002024 }
2025
2026 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2027 if (err < 0)
2028 goto failed;
2029
2030 if (changed)
2031 err = new_settings(hdev, sk);
2032
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002033 goto failed;
2034 }
2035
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002036 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2037 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002038 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2039 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002040 goto failed;
2041 }
2042
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002043 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002044 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
Johan Hedberg37699722014-06-24 14:00:27 +03002054 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2055 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2056 sizeof(cp->val), &cp->val);
2057
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002058 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002059 if (err < 0) {
2060 mgmt_pending_remove(cmd);
2061 goto failed;
2062 }
2063
2064failed:
2065 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066 return err;
2067}
2068
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002069static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002070{
2071 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002072 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002073 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002074 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002075
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002076 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002077
Johan Hedberge6fe7982013-10-02 15:45:22 +03002078 status = mgmt_bredr_support(hdev);
2079 if (status)
2080 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002081
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002082 if (!lmp_ssp_capable(hdev))
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2084 MGMT_STATUS_NOT_SUPPORTED);
2085
2086 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2087 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2088 MGMT_STATUS_REJECTED);
2089
Johan Hedberga7e80f22013-01-09 16:05:19 +02002090 if (cp->val != 0x00 && cp->val != 0x01)
2091 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2092 MGMT_STATUS_INVALID_PARAMS);
2093
Marcel Holtmannee392692013-10-01 22:59:23 -07002094 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002095
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002096 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002097 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002098 } else {
2099 if (hdev_is_powered(hdev)) {
2100 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2101 MGMT_STATUS_REJECTED);
2102 goto unlock;
2103 }
2104
Marcel Holtmannee392692013-10-01 22:59:23 -07002105 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002106 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002107
2108 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2109 if (err < 0)
2110 goto unlock;
2111
2112 if (changed)
2113 err = new_settings(hdev, sk);
2114
2115unlock:
2116 hci_dev_unlock(hdev);
2117 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002118}
2119
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002120static void le_enable_complete(struct hci_dev *hdev, u8 status)
2121{
2122 struct cmd_lookup match = { NULL, hdev };
2123
2124 if (status) {
2125 u8 mgmt_err = mgmt_status(status);
2126
2127 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2128 &mgmt_err);
2129 return;
2130 }
2131
2132 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2133
2134 new_settings(hdev, match.sk);
2135
2136 if (match.sk)
2137 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002138
2139 /* Make sure the controller has a good default for
2140 * advertising data. Restrict the update to when LE
2141 * has actually been enabled. During power on, the
2142 * update in powered_update_hci will take care of it.
2143 */
2144 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2145 struct hci_request req;
2146
2147 hci_dev_lock(hdev);
2148
2149 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002150 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002151 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002152 hci_req_run(&req, NULL);
2153
Johan Hedberga70f4b52014-07-07 15:19:50 +03002154 hci_update_background_scan(hdev);
2155
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002156 hci_dev_unlock(hdev);
2157 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002158}
2159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002160static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002161{
2162 struct mgmt_mode *cp = data;
2163 struct hci_cp_write_le_host_supported hci_cp;
2164 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002165 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002166 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002167 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002168
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002169 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002170
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002171 if (!lmp_le_capable(hdev))
2172 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2173 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002174
Johan Hedberga7e80f22013-01-09 16:05:19 +02002175 if (cp->val != 0x00 && cp->val != 0x01)
2176 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2177 MGMT_STATUS_INVALID_PARAMS);
2178
Johan Hedbergc73eee92013-04-19 18:35:21 +03002179 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002180 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002181 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2182 MGMT_STATUS_REJECTED);
2183
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002184 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002185
2186 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002187 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002188
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002189 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002190 bool changed = false;
2191
2192 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2193 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2194 changed = true;
2195 }
2196
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002197 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2198 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002199 changed = true;
2200 }
2201
Johan Hedberg06199cf2012-02-22 16:37:11 +02002202 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2203 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002204 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002205
2206 if (changed)
2207 err = new_settings(hdev, sk);
2208
Johan Hedberg1de028c2012-02-29 19:55:35 -08002209 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002210 }
2211
Johan Hedberg4375f102013-09-25 13:26:10 +03002212 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2213 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002214 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002215 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002216 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002217 }
2218
2219 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2220 if (!cmd) {
2221 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002222 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002223 }
2224
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002225 hci_req_init(&req, hdev);
2226
Johan Hedberg06199cf2012-02-22 16:37:11 +02002227 memset(&hci_cp, 0, sizeof(hci_cp));
2228
2229 if (val) {
2230 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002231 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002232 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002233 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002234 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002235 }
2236
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002237 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2238 &hci_cp);
2239
2240 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302241 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002242 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002243
Johan Hedberg1de028c2012-02-29 19:55:35 -08002244unlock:
2245 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246 return err;
2247}
2248
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002249/* This is a helper function to test for pending mgmt commands that can
2250 * cause CoD or EIR HCI commands. We can only allow one such pending
2251 * mgmt command at a time since otherwise we cannot easily track what
2252 * the current values are, will be, and based on that calculate if a new
2253 * HCI command needs to be sent and if yes with what value.
2254 */
2255static bool pending_eir_or_class(struct hci_dev *hdev)
2256{
2257 struct pending_cmd *cmd;
2258
2259 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2260 switch (cmd->opcode) {
2261 case MGMT_OP_ADD_UUID:
2262 case MGMT_OP_REMOVE_UUID:
2263 case MGMT_OP_SET_DEV_CLASS:
2264 case MGMT_OP_SET_POWERED:
2265 return true;
2266 }
2267 }
2268
2269 return false;
2270}
2271
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002272static const u8 bluetooth_base_uuid[] = {
2273 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2274 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2275};
2276
2277static u8 get_uuid_size(const u8 *uuid)
2278{
2279 u32 val;
2280
2281 if (memcmp(uuid, bluetooth_base_uuid, 12))
2282 return 128;
2283
2284 val = get_unaligned_le32(&uuid[12]);
2285 if (val > 0xffff)
2286 return 32;
2287
2288 return 16;
2289}
2290
Johan Hedberg92da6092013-03-15 17:06:55 -05002291static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2292{
2293 struct pending_cmd *cmd;
2294
2295 hci_dev_lock(hdev);
2296
2297 cmd = mgmt_pending_find(mgmt_op, hdev);
2298 if (!cmd)
2299 goto unlock;
2300
2301 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2302 hdev->dev_class, 3);
2303
2304 mgmt_pending_remove(cmd);
2305
2306unlock:
2307 hci_dev_unlock(hdev);
2308}
2309
2310static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2311{
2312 BT_DBG("status 0x%02x", status);
2313
2314 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2315}
2316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002317static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002318{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002319 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002320 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002321 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002322 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002323 int err;
2324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002325 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002326
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002327 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002328
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002329 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002330 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002331 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002332 goto failed;
2333 }
2334
Andre Guedes92c4c202012-06-07 19:05:44 -03002335 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002336 if (!uuid) {
2337 err = -ENOMEM;
2338 goto failed;
2339 }
2340
2341 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002342 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002343 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002344
Johan Hedbergde66aa62013-01-27 00:31:27 +02002345 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002346
Johan Hedberg890ea892013-03-15 17:06:52 -05002347 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002348
Johan Hedberg890ea892013-03-15 17:06:52 -05002349 update_class(&req);
2350 update_eir(&req);
2351
Johan Hedberg92da6092013-03-15 17:06:55 -05002352 err = hci_req_run(&req, add_uuid_complete);
2353 if (err < 0) {
2354 if (err != -ENODATA)
2355 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002356
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002357 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002358 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002359 goto failed;
2360 }
2361
2362 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002363 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002364 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002365 goto failed;
2366 }
2367
2368 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002369
2370failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002371 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002372 return err;
2373}
2374
Johan Hedberg24b78d02012-02-23 23:24:30 +02002375static bool enable_service_cache(struct hci_dev *hdev)
2376{
2377 if (!hdev_is_powered(hdev))
2378 return false;
2379
2380 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002381 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2382 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002383 return true;
2384 }
2385
2386 return false;
2387}
2388
Johan Hedberg92da6092013-03-15 17:06:55 -05002389static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2390{
2391 BT_DBG("status 0x%02x", status);
2392
2393 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2394}
2395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002397 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002398{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002399 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002400 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002401 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002402 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 -05002403 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404 int err, found;
2405
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002406 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002407
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002408 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002409
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002410 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002411 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002412 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002413 goto unlock;
2414 }
2415
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002416 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002417 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002418
Johan Hedberg24b78d02012-02-23 23:24:30 +02002419 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002420 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002421 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002422 goto unlock;
2423 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002424
Johan Hedberg9246a862012-02-23 21:33:16 +02002425 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002426 }
2427
2428 found = 0;
2429
Johan Hedberg056341c2013-01-27 00:31:30 +02002430 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002431 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2432 continue;
2433
2434 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002435 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002436 found++;
2437 }
2438
2439 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002440 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002441 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002442 goto unlock;
2443 }
2444
Johan Hedberg9246a862012-02-23 21:33:16 +02002445update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002446 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002447
Johan Hedberg890ea892013-03-15 17:06:52 -05002448 update_class(&req);
2449 update_eir(&req);
2450
Johan Hedberg92da6092013-03-15 17:06:55 -05002451 err = hci_req_run(&req, remove_uuid_complete);
2452 if (err < 0) {
2453 if (err != -ENODATA)
2454 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002455
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002456 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002457 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002458 goto unlock;
2459 }
2460
2461 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002462 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002463 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002464 goto unlock;
2465 }
2466
2467 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002468
2469unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002470 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002471 return err;
2472}
2473
Johan Hedberg92da6092013-03-15 17:06:55 -05002474static void set_class_complete(struct hci_dev *hdev, u8 status)
2475{
2476 BT_DBG("status 0x%02x", status);
2477
2478 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2479}
2480
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002481static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002482 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002483{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002484 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002485 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002486 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002487 int err;
2488
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002490
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002491 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002492 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2493 MGMT_STATUS_NOT_SUPPORTED);
2494
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002495 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002496
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002497 if (pending_eir_or_class(hdev)) {
2498 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2499 MGMT_STATUS_BUSY);
2500 goto unlock;
2501 }
2502
2503 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2504 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2505 MGMT_STATUS_INVALID_PARAMS);
2506 goto unlock;
2507 }
2508
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002509 hdev->major_class = cp->major;
2510 hdev->minor_class = cp->minor;
2511
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002512 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002513 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002514 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002515 goto unlock;
2516 }
2517
Johan Hedberg890ea892013-03-15 17:06:52 -05002518 hci_req_init(&req, hdev);
2519
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002520 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002521 hci_dev_unlock(hdev);
2522 cancel_delayed_work_sync(&hdev->service_cache);
2523 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002525 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002526
Johan Hedberg890ea892013-03-15 17:06:52 -05002527 update_class(&req);
2528
Johan Hedberg92da6092013-03-15 17:06:55 -05002529 err = hci_req_run(&req, set_class_complete);
2530 if (err < 0) {
2531 if (err != -ENODATA)
2532 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 goto unlock;
2537 }
2538
2539 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002541 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 goto unlock;
2543 }
2544
2545 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002546
Johan Hedbergb5235a62012-02-21 14:32:24 +02002547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002549 return err;
2550}
2551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002552static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002553 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002554{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002555 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002556 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2557 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002558 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002559 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002560 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002561
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002562 BT_DBG("request for %s", hdev->name);
2563
2564 if (!lmp_bredr_capable(hdev))
2565 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2566 MGMT_STATUS_NOT_SUPPORTED);
2567
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002568 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002569 if (key_count > max_key_count) {
2570 BT_ERR("load_link_keys: too big key_count value %u",
2571 key_count);
2572 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2573 MGMT_STATUS_INVALID_PARAMS);
2574 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002575
Johan Hedberg86742e12011-11-07 23:13:38 +02002576 expected_len = sizeof(*cp) + key_count *
2577 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002578 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002579 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002580 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002581 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002582 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002583 }
2584
Johan Hedberg4ae14302013-01-20 14:27:13 +02002585 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2586 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2587 MGMT_STATUS_INVALID_PARAMS);
2588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002589 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002590 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002591
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002592 for (i = 0; i < key_count; i++) {
2593 struct mgmt_link_key_info *key = &cp->keys[i];
2594
Marcel Holtmann8e991132014-01-10 02:07:25 -08002595 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002596 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2597 MGMT_STATUS_INVALID_PARAMS);
2598 }
2599
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002600 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002601
2602 hci_link_keys_clear(hdev);
2603
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002604 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002605 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2606 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002607 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002608 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2609 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002610
2611 if (changed)
2612 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002613
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002614 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002615 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002616
Johan Hedberg58e92932014-06-24 14:00:26 +03002617 /* Always ignore debug keys and require a new pairing if
2618 * the user wants to use them.
2619 */
2620 if (key->type == HCI_LK_DEBUG_COMBINATION)
2621 continue;
2622
Johan Hedberg7652ff62014-06-24 13:15:49 +03002623 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2624 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002625 }
2626
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002627 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002628
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002629 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002630
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002631 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632}
2633
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002634static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002635 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002636{
2637 struct mgmt_ev_device_unpaired ev;
2638
2639 bacpy(&ev.addr.bdaddr, bdaddr);
2640 ev.addr.type = addr_type;
2641
2642 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002643 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002644}
2645
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002646static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002647 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002648{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002649 struct mgmt_cp_unpair_device *cp = data;
2650 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002651 struct hci_cp_disconnect dc;
2652 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002654 int err;
2655
Johan Hedberga8a1d192011-11-10 15:54:38 +02002656 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002657 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2658 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002659
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002660 if (!bdaddr_type_is_valid(cp->addr.type))
2661 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2662 MGMT_STATUS_INVALID_PARAMS,
2663 &rp, sizeof(rp));
2664
Johan Hedberg118da702013-01-20 14:27:20 +02002665 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2666 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2667 MGMT_STATUS_INVALID_PARAMS,
2668 &rp, sizeof(rp));
2669
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002670 hci_dev_lock(hdev);
2671
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002672 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002673 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002674 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002675 goto unlock;
2676 }
2677
Johan Hedberge0b2b272014-02-18 17:14:31 +02002678 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002679 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002680 } else {
2681 u8 addr_type;
2682
2683 if (cp->addr.type == BDADDR_LE_PUBLIC)
2684 addr_type = ADDR_LE_DEV_PUBLIC;
2685 else
2686 addr_type = ADDR_LE_DEV_RANDOM;
2687
Johan Hedberga7ec7332014-02-18 17:14:35 +02002688 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2689
Andre Guedesa9b0a042014-02-26 20:21:52 -03002690 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2691
Johan Hedberge0b2b272014-02-18 17:14:31 +02002692 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2693 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002694
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002695 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002696 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002697 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002698 goto unlock;
2699 }
2700
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002701 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002702 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002703 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002704 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002705 else
2706 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002707 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002708 } else {
2709 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711
Johan Hedberga8a1d192011-11-10 15:54:38 +02002712 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002713 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002714 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002715 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002716 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002717 }
2718
Johan Hedberg124f6e32012-02-09 13:50:12 +02002719 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002720 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002721 if (!cmd) {
2722 err = -ENOMEM;
2723 goto unlock;
2724 }
2725
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002726 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002727 dc.reason = 0x13; /* Remote User Terminated Connection */
2728 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2729 if (err < 0)
2730 mgmt_pending_remove(cmd);
2731
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002733 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002734 return err;
2735}
2736
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002737static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002738 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002739{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002740 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002741 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002742 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002743 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002744 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002745 int err;
2746
2747 BT_DBG("");
2748
Johan Hedberg06a63b12013-01-20 14:27:21 +02002749 memset(&rp, 0, sizeof(rp));
2750 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2751 rp.addr.type = cp->addr.type;
2752
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002753 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002754 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2755 MGMT_STATUS_INVALID_PARAMS,
2756 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002757
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002758 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002759
2760 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002761 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2762 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002763 goto failed;
2764 }
2765
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002766 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002767 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2768 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002769 goto failed;
2770 }
2771
Andre Guedes591f47f2012-04-24 21:02:49 -03002772 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002773 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2774 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002775 else
2776 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002777
Vishal Agarwalf9607272012-06-13 05:32:43 +05302778 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002779 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2780 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002781 goto failed;
2782 }
2783
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002784 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002785 if (!cmd) {
2786 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002787 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002788 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002789
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002790 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002791 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002792
2793 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2794 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002795 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002796
2797failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002798 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002799 return err;
2800}
2801
Andre Guedes57c14772012-04-24 21:02:50 -03002802static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002803{
2804 switch (link_type) {
2805 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002806 switch (addr_type) {
2807 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002808 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002809
Johan Hedberg48264f02011-11-09 13:58:58 +02002810 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002811 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002812 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002813 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002814
Johan Hedberg4c659c32011-11-07 23:13:39 +02002815 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002816 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002817 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002818 }
2819}
2820
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002821static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2822 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002823{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002824 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002825 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002826 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002827 int err;
2828 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002829
2830 BT_DBG("");
2831
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002832 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002833
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002834 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002835 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002836 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002837 goto unlock;
2838 }
2839
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002840 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002841 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2842 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002843 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002844 }
2845
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002846 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002847 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002848 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002849 err = -ENOMEM;
2850 goto unlock;
2851 }
2852
Johan Hedberg2784eb42011-01-21 13:56:35 +02002853 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002854 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002855 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2856 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002857 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002858 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002859 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002860 continue;
2861 i++;
2862 }
2863
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002864 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002865
Johan Hedberg4c659c32011-11-07 23:13:39 +02002866 /* Recalculate length in case of filtered SCO connections, etc */
2867 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002869 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002870 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002871
Johan Hedberga38528f2011-01-22 06:46:43 +02002872 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002873
2874unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002875 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002876 return err;
2877}
2878
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002879static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002880 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002881{
2882 struct pending_cmd *cmd;
2883 int err;
2884
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002885 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002886 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002887 if (!cmd)
2888 return -ENOMEM;
2889
Johan Hedbergd8457692012-02-17 14:24:57 +02002890 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002891 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002892 if (err < 0)
2893 mgmt_pending_remove(cmd);
2894
2895 return err;
2896}
2897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002898static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002899 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002900{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002901 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002902 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002903 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002904 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002905 int err;
2906
2907 BT_DBG("");
2908
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002909 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002910
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002911 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002912 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002913 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002914 goto failed;
2915 }
2916
Johan Hedbergd8457692012-02-17 14:24:57 +02002917 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002918 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002919 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002920 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002921 goto failed;
2922 }
2923
2924 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002925 struct mgmt_cp_pin_code_neg_reply ncp;
2926
2927 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002928
2929 BT_ERR("PIN code is not 16 bytes long");
2930
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002931 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002932 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002933 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002934 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002935
2936 goto failed;
2937 }
2938
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002939 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002940 if (!cmd) {
2941 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002942 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002943 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002944
Johan Hedbergd8457692012-02-17 14:24:57 +02002945 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002946 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002947 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002948
2949 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2950 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002951 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002952
2953failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002954 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002955 return err;
2956}
2957
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002958static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2959 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002960{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002961 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002962
2963 BT_DBG("");
2964
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002965 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2966 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2967 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2968
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002969 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002970
2971 hdev->io_capability = cp->io_capability;
2972
2973 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002974 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002976 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002977
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2979 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002980}
2981
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002982static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002983{
2984 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002985 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002986
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002987 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002988 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2989 continue;
2990
Johan Hedberge9a416b2011-02-19 12:05:56 -03002991 if (cmd->user_data != conn)
2992 continue;
2993
2994 return cmd;
2995 }
2996
2997 return NULL;
2998}
2999
3000static void pairing_complete(struct pending_cmd *cmd, u8 status)
3001{
3002 struct mgmt_rp_pair_device rp;
3003 struct hci_conn *conn = cmd->user_data;
3004
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003005 bacpy(&rp.addr.bdaddr, &conn->dst);
3006 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003007
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003008 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003009 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003010
3011 /* So we don't get further callbacks for this connection */
3012 conn->connect_cfm_cb = NULL;
3013 conn->security_cfm_cb = NULL;
3014 conn->disconn_cfm_cb = NULL;
3015
David Herrmann76a68ba2013-04-06 20:28:37 +02003016 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003017
Johan Hedberga664b5b2011-02-19 12:06:02 -03003018 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003019}
3020
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003021void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3022{
3023 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3024 struct pending_cmd *cmd;
3025
3026 cmd = find_pairing(conn);
3027 if (cmd)
3028 pairing_complete(cmd, status);
3029}
3030
Johan Hedberge9a416b2011-02-19 12:05:56 -03003031static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3032{
3033 struct pending_cmd *cmd;
3034
3035 BT_DBG("status %u", status);
3036
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003037 cmd = find_pairing(conn);
3038 if (!cmd)
3039 BT_DBG("Unable to find a pending command");
3040 else
Johan Hedberge2113262012-02-18 15:20:03 +02003041 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003042}
3043
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003044static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303045{
3046 struct pending_cmd *cmd;
3047
3048 BT_DBG("status %u", status);
3049
3050 if (!status)
3051 return;
3052
3053 cmd = find_pairing(conn);
3054 if (!cmd)
3055 BT_DBG("Unable to find a pending command");
3056 else
3057 pairing_complete(cmd, mgmt_status(status));
3058}
3059
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003060static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003061 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003062{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003063 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003064 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003065 struct pending_cmd *cmd;
3066 u8 sec_level, auth_type;
3067 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003068 int err;
3069
3070 BT_DBG("");
3071
Szymon Jancf950a30e2013-01-18 12:48:07 +01003072 memset(&rp, 0, sizeof(rp));
3073 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3074 rp.addr.type = cp->addr.type;
3075
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003076 if (!bdaddr_type_is_valid(cp->addr.type))
3077 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3078 MGMT_STATUS_INVALID_PARAMS,
3079 &rp, sizeof(rp));
3080
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003081 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3082 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3083 MGMT_STATUS_INVALID_PARAMS,
3084 &rp, sizeof(rp));
3085
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003086 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003087
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003088 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003089 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3090 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003091 goto unlock;
3092 }
3093
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003094 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003095 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003096
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003097 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003098 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3099 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003100 } else {
3101 u8 addr_type;
3102
3103 /* Convert from L2CAP channel address type to HCI address type
3104 */
3105 if (cp->addr.type == BDADDR_LE_PUBLIC)
3106 addr_type = ADDR_LE_DEV_PUBLIC;
3107 else
3108 addr_type = ADDR_LE_DEV_RANDOM;
3109
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003110 /* When pairing a new device, it is expected to remember
3111 * this device for future connections. Adding the connection
3112 * parameter information ahead of time allows tracking
3113 * of the slave preferred values and will speed up any
3114 * further connection establishment.
3115 *
3116 * If connection parameters already exist, then they
3117 * will be kept and this function does nothing.
3118 */
3119 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3120
Johan Hedbergcdd62752014-07-07 15:02:28 +03003121 /* Request a connection with master = true role */
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003122 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedbergcdd62752014-07-07 15:02:28 +03003123 sec_level, HCI_LE_CONN_TIMEOUT, true);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003124 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003125
Ville Tervo30e76272011-02-22 16:10:53 -03003126 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003127 int status;
3128
3129 if (PTR_ERR(conn) == -EBUSY)
3130 status = MGMT_STATUS_BUSY;
3131 else
3132 status = MGMT_STATUS_CONNECT_FAILED;
3133
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003134 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003135 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003136 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137 goto unlock;
3138 }
3139
3140 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003141 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003142 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003143 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003144 goto unlock;
3145 }
3146
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003147 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148 if (!cmd) {
3149 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003150 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003151 goto unlock;
3152 }
3153
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003154 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003155 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003156 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003157 conn->security_cfm_cb = pairing_complete_cb;
3158 conn->disconn_cfm_cb = pairing_complete_cb;
3159 } else {
3160 conn->connect_cfm_cb = le_pairing_complete_cb;
3161 conn->security_cfm_cb = le_pairing_complete_cb;
3162 conn->disconn_cfm_cb = le_pairing_complete_cb;
3163 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003164
Johan Hedberge9a416b2011-02-19 12:05:56 -03003165 conn->io_capability = cp->io_cap;
3166 cmd->user_data = conn;
3167
3168 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003169 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003170 pairing_complete(cmd, 0);
3171
3172 err = 0;
3173
3174unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003175 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003176 return err;
3177}
3178
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003179static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3180 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003181{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003182 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003183 struct pending_cmd *cmd;
3184 struct hci_conn *conn;
3185 int err;
3186
3187 BT_DBG("");
3188
Johan Hedberg28424702012-02-02 04:02:29 +02003189 hci_dev_lock(hdev);
3190
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003191 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003192 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003193 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003194 goto unlock;
3195 }
3196
Johan Hedberg28424702012-02-02 04:02:29 +02003197 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3198 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003199 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003200 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003201 goto unlock;
3202 }
3203
3204 conn = cmd->user_data;
3205
3206 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003207 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003208 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003209 goto unlock;
3210 }
3211
3212 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3213
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003214 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003215 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003216unlock:
3217 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003218 return err;
3219}
3220
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003221static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003222 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003223 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003224{
Johan Hedberga5c29682011-02-19 12:05:57 -03003225 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003226 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003227 int err;
3228
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003229 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003230
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003231 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003232 err = cmd_complete(sk, hdev->id, mgmt_op,
3233 MGMT_STATUS_NOT_POWERED, addr,
3234 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003235 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003236 }
3237
Johan Hedberg1707c602013-03-15 17:07:15 -05003238 if (addr->type == BDADDR_BREDR)
3239 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003240 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003241 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003242
Johan Hedberg272d90d2012-02-09 15:26:12 +02003243 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003244 err = cmd_complete(sk, hdev->id, mgmt_op,
3245 MGMT_STATUS_NOT_CONNECTED, addr,
3246 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003247 goto done;
3248 }
3249
Johan Hedberg1707c602013-03-15 17:07:15 -05003250 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003251 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003252 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003253 err = cmd_complete(sk, hdev->id, mgmt_op,
3254 MGMT_STATUS_SUCCESS, addr,
3255 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003256 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003257 err = cmd_complete(sk, hdev->id, mgmt_op,
3258 MGMT_STATUS_FAILED, addr,
3259 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003260
Brian Gix47c15e22011-11-16 13:53:14 -08003261 goto done;
3262 }
3263
Johan Hedberg1707c602013-03-15 17:07:15 -05003264 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003265 if (!cmd) {
3266 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003267 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003268 }
3269
Brian Gix0df4c182011-11-16 13:53:13 -08003270 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003271 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3272 struct hci_cp_user_passkey_reply cp;
3273
Johan Hedberg1707c602013-03-15 17:07:15 -05003274 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003275 cp.passkey = passkey;
3276 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3277 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003278 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3279 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003280
Johan Hedberga664b5b2011-02-19 12:06:02 -03003281 if (err < 0)
3282 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003283
Brian Gix0df4c182011-11-16 13:53:13 -08003284done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003285 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003286 return err;
3287}
3288
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303289static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3290 void *data, u16 len)
3291{
3292 struct mgmt_cp_pin_code_neg_reply *cp = data;
3293
3294 BT_DBG("");
3295
Johan Hedberg1707c602013-03-15 17:07:15 -05003296 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303297 MGMT_OP_PIN_CODE_NEG_REPLY,
3298 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3299}
3300
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003301static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3302 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003303{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003304 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003305
3306 BT_DBG("");
3307
3308 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003309 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003310 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003311
Johan Hedberg1707c602013-03-15 17:07:15 -05003312 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003313 MGMT_OP_USER_CONFIRM_REPLY,
3314 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003315}
3316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003317static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003318 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003319{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003320 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003321
3322 BT_DBG("");
3323
Johan Hedberg1707c602013-03-15 17:07:15 -05003324 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003325 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3326 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003327}
3328
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003329static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3330 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003331{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003332 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003333
3334 BT_DBG("");
3335
Johan Hedberg1707c602013-03-15 17:07:15 -05003336 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003337 MGMT_OP_USER_PASSKEY_REPLY,
3338 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003339}
3340
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003341static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003342 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003343{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003344 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003345
3346 BT_DBG("");
3347
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_PASSKEY_NEG_REPLY,
3350 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003351}
3352
Johan Hedberg13928972013-03-15 17:07:00 -05003353static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003354{
Johan Hedberg13928972013-03-15 17:07:00 -05003355 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003356 struct hci_cp_write_local_name cp;
3357
Johan Hedberg13928972013-03-15 17:07:00 -05003358 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003359
Johan Hedberg890ea892013-03-15 17:06:52 -05003360 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003361}
3362
Johan Hedberg13928972013-03-15 17:07:00 -05003363static void set_name_complete(struct hci_dev *hdev, u8 status)
3364{
3365 struct mgmt_cp_set_local_name *cp;
3366 struct pending_cmd *cmd;
3367
3368 BT_DBG("status 0x%02x", status);
3369
3370 hci_dev_lock(hdev);
3371
3372 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3373 if (!cmd)
3374 goto unlock;
3375
3376 cp = cmd->param;
3377
3378 if (status)
3379 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3380 mgmt_status(status));
3381 else
3382 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3383 cp, sizeof(*cp));
3384
3385 mgmt_pending_remove(cmd);
3386
3387unlock:
3388 hci_dev_unlock(hdev);
3389}
3390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003391static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003392 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003393{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003394 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003395 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003396 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003397 int err;
3398
3399 BT_DBG("");
3400
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003401 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003402
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003403 /* If the old values are the same as the new ones just return a
3404 * direct command complete event.
3405 */
3406 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3407 !memcmp(hdev->short_name, cp->short_name,
3408 sizeof(hdev->short_name))) {
3409 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3410 data, len);
3411 goto failed;
3412 }
3413
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003414 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003415
Johan Hedbergb5235a62012-02-21 14:32:24 +02003416 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003417 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003418
3419 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003420 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003421 if (err < 0)
3422 goto failed;
3423
3424 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003425 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003426
Johan Hedbergb5235a62012-02-21 14:32:24 +02003427 goto failed;
3428 }
3429
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003430 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003431 if (!cmd) {
3432 err = -ENOMEM;
3433 goto failed;
3434 }
3435
Johan Hedberg13928972013-03-15 17:07:00 -05003436 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3437
Johan Hedberg890ea892013-03-15 17:06:52 -05003438 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003439
3440 if (lmp_bredr_capable(hdev)) {
3441 update_name(&req);
3442 update_eir(&req);
3443 }
3444
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003445 /* The name is stored in the scan response data and so
3446 * no need to udpate the advertising data here.
3447 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003448 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003449 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003450
Johan Hedberg13928972013-03-15 17:07:00 -05003451 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003452 if (err < 0)
3453 mgmt_pending_remove(cmd);
3454
3455failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003456 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003457 return err;
3458}
3459
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003460static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003461 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003462{
Szymon Jancc35938b2011-03-22 13:12:21 +01003463 struct pending_cmd *cmd;
3464 int err;
3465
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003466 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003467
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003468 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003469
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003470 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003471 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003472 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003473 goto unlock;
3474 }
3475
Andre Guedes9a1a1992012-07-24 15:03:48 -03003476 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003477 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003478 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003479 goto unlock;
3480 }
3481
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003482 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003483 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003485 goto unlock;
3486 }
3487
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003488 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003489 if (!cmd) {
3490 err = -ENOMEM;
3491 goto unlock;
3492 }
3493
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003494 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3495 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3496 0, NULL);
3497 else
3498 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3499
Szymon Jancc35938b2011-03-22 13:12:21 +01003500 if (err < 0)
3501 mgmt_pending_remove(cmd);
3502
3503unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003504 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003505 return err;
3506}
3507
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003508static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003509 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003510{
Szymon Janc2763eda2011-03-22 13:12:22 +01003511 int err;
3512
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003513 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003514
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003515 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003516
Marcel Holtmannec109112014-01-10 02:07:30 -08003517 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3518 struct mgmt_cp_add_remote_oob_data *cp = data;
3519 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003520
Marcel Holtmannec109112014-01-10 02:07:30 -08003521 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3522 cp->hash, cp->randomizer);
3523 if (err < 0)
3524 status = MGMT_STATUS_FAILED;
3525 else
3526 status = MGMT_STATUS_SUCCESS;
3527
3528 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3529 status, &cp->addr, sizeof(cp->addr));
3530 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3531 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3532 u8 status;
3533
3534 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3535 cp->hash192,
3536 cp->randomizer192,
3537 cp->hash256,
3538 cp->randomizer256);
3539 if (err < 0)
3540 status = MGMT_STATUS_FAILED;
3541 else
3542 status = MGMT_STATUS_SUCCESS;
3543
3544 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3545 status, &cp->addr, sizeof(cp->addr));
3546 } else {
3547 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3548 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3549 MGMT_STATUS_INVALID_PARAMS);
3550 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003551
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003552 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003553 return err;
3554}
3555
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003556static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003557 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003558{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003559 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003560 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003561 int err;
3562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003563 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003564
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003565 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003566
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003567 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003568 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003569 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003570 else
Szymon Janca6785be2012-12-13 15:11:21 +01003571 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003572
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003573 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003574 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003575
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003576 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003577 return err;
3578}
3579
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003580static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3581{
3582 struct pending_cmd *cmd;
3583 u8 type;
3584 int err;
3585
3586 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3587
3588 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3589 if (!cmd)
3590 return -ENOENT;
3591
3592 type = hdev->discovery.type;
3593
3594 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3595 &type, sizeof(type));
3596 mgmt_pending_remove(cmd);
3597
3598 return err;
3599}
3600
Andre Guedes7c307722013-04-30 15:29:28 -03003601static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3602{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003603 unsigned long timeout = 0;
3604
Andre Guedes7c307722013-04-30 15:29:28 -03003605 BT_DBG("status %d", status);
3606
3607 if (status) {
3608 hci_dev_lock(hdev);
3609 mgmt_start_discovery_failed(hdev, status);
3610 hci_dev_unlock(hdev);
3611 return;
3612 }
3613
3614 hci_dev_lock(hdev);
3615 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3616 hci_dev_unlock(hdev);
3617
3618 switch (hdev->discovery.type) {
3619 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003620 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003621 break;
3622
3623 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003624 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003625 break;
3626
3627 case DISCOV_TYPE_BREDR:
3628 break;
3629
3630 default:
3631 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3632 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003633
3634 if (!timeout)
3635 return;
3636
3637 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003638}
3639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003640static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003641 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003642{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003643 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003644 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003645 struct hci_cp_le_set_scan_param param_cp;
3646 struct hci_cp_le_set_scan_enable enable_cp;
3647 struct hci_cp_inquiry inq_cp;
3648 struct hci_request req;
3649 /* General inquiry access code (GIAC) */
3650 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003651 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003652 int err;
3653
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003654 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003655
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003656 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003657
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003658 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003659 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003660 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003661 goto failed;
3662 }
3663
Andre Guedes642be6c2012-03-21 00:03:37 -03003664 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3665 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3666 MGMT_STATUS_BUSY);
3667 goto failed;
3668 }
3669
Johan Hedbergff9ef572012-01-04 14:23:45 +02003670 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003671 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003672 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003673 goto failed;
3674 }
3675
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003676 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003677 if (!cmd) {
3678 err = -ENOMEM;
3679 goto failed;
3680 }
3681
Andre Guedes4aab14e2012-02-17 20:39:36 -03003682 hdev->discovery.type = cp->type;
3683
Andre Guedes7c307722013-04-30 15:29:28 -03003684 hci_req_init(&req, hdev);
3685
Andre Guedes4aab14e2012-02-17 20:39:36 -03003686 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003687 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003688 status = mgmt_bredr_support(hdev);
3689 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003690 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003691 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003692 mgmt_pending_remove(cmd);
3693 goto failed;
3694 }
3695
Andre Guedes7c307722013-04-30 15:29:28 -03003696 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3697 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3698 MGMT_STATUS_BUSY);
3699 mgmt_pending_remove(cmd);
3700 goto failed;
3701 }
3702
3703 hci_inquiry_cache_flush(hdev);
3704
3705 memset(&inq_cp, 0, sizeof(inq_cp));
3706 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003707 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003708 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003709 break;
3710
3711 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003712 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003713 status = mgmt_le_support(hdev);
3714 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003715 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003716 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003717 mgmt_pending_remove(cmd);
3718 goto failed;
3719 }
3720
Andre Guedes7c307722013-04-30 15:29:28 -03003721 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003722 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003723 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3724 MGMT_STATUS_NOT_SUPPORTED);
3725 mgmt_pending_remove(cmd);
3726 goto failed;
3727 }
3728
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003729 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3730 /* Don't let discovery abort an outgoing
3731 * connection attempt that's using directed
3732 * advertising.
3733 */
3734 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3735 BT_CONNECT)) {
3736 err = cmd_status(sk, hdev->id,
3737 MGMT_OP_START_DISCOVERY,
3738 MGMT_STATUS_REJECTED);
3739 mgmt_pending_remove(cmd);
3740 goto failed;
3741 }
3742
3743 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003744 }
3745
Andre Guedesc54c3862014-02-26 20:21:50 -03003746 /* If controller is scanning, it means the background scanning
3747 * is running. Thus, we should temporarily stop it in order to
3748 * set the discovery scanning parameters.
3749 */
3750 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3751 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003752
3753 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003754
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003755 /* All active scans will be done with either a resolvable
3756 * private address (when privacy feature has been enabled)
3757 * or unresolvable private address.
3758 */
3759 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003760 if (err < 0) {
3761 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3762 MGMT_STATUS_FAILED);
3763 mgmt_pending_remove(cmd);
3764 goto failed;
3765 }
3766
Andre Guedes7c307722013-04-30 15:29:28 -03003767 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003768 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3769 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003770 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003771 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3772 &param_cp);
3773
3774 memset(&enable_cp, 0, sizeof(enable_cp));
3775 enable_cp.enable = LE_SCAN_ENABLE;
3776 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3777 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3778 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003779 break;
3780
Andre Guedesf39799f2012-02-17 20:39:35 -03003781 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003782 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3783 MGMT_STATUS_INVALID_PARAMS);
3784 mgmt_pending_remove(cmd);
3785 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003786 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003787
Andre Guedes7c307722013-04-30 15:29:28 -03003788 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003789 if (err < 0)
3790 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003791 else
3792 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003793
3794failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003795 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003796 return err;
3797}
3798
Andre Guedes1183fdc2013-04-30 15:29:35 -03003799static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3800{
3801 struct pending_cmd *cmd;
3802 int err;
3803
3804 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3805 if (!cmd)
3806 return -ENOENT;
3807
3808 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3809 &hdev->discovery.type, sizeof(hdev->discovery.type));
3810 mgmt_pending_remove(cmd);
3811
3812 return err;
3813}
3814
Andre Guedes0e05bba2013-04-30 15:29:33 -03003815static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3816{
3817 BT_DBG("status %d", status);
3818
3819 hci_dev_lock(hdev);
3820
3821 if (status) {
3822 mgmt_stop_discovery_failed(hdev, status);
3823 goto unlock;
3824 }
3825
3826 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3827
3828unlock:
3829 hci_dev_unlock(hdev);
3830}
3831
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003832static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003833 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003834{
Johan Hedbergd9306502012-02-20 23:25:18 +02003835 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003836 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003837 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003838 int err;
3839
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003840 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003841
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003842 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003843
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003844 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003845 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003846 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3847 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003848 goto unlock;
3849 }
3850
3851 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003852 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003853 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3854 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003855 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003856 }
3857
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003858 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003859 if (!cmd) {
3860 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003861 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003862 }
3863
Andre Guedes0e05bba2013-04-30 15:29:33 -03003864 hci_req_init(&req, hdev);
3865
Johan Hedberg21a60d32014-06-10 14:05:58 +03003866 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003867
Johan Hedberg21a60d32014-06-10 14:05:58 +03003868 err = hci_req_run(&req, stop_discovery_complete);
3869 if (!err) {
3870 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003871 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003872 }
3873
Johan Hedberg21a60d32014-06-10 14:05:58 +03003874 mgmt_pending_remove(cmd);
3875
3876 /* If no HCI commands were sent we're done */
3877 if (err == -ENODATA) {
3878 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3879 &mgmt_cp->type, sizeof(mgmt_cp->type));
3880 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3881 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003882
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003883unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003884 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003885 return err;
3886}
3887
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003888static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003889 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003890{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003891 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003892 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003893 int err;
3894
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003895 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003896
Johan Hedberg561aafb2012-01-04 13:31:59 +02003897 hci_dev_lock(hdev);
3898
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003899 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003900 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3901 MGMT_STATUS_FAILED, &cp->addr,
3902 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003903 goto failed;
3904 }
3905
Johan Hedberga198e7b2012-02-17 14:27:06 +02003906 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003907 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003908 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3909 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3910 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003911 goto failed;
3912 }
3913
3914 if (cp->name_known) {
3915 e->name_state = NAME_KNOWN;
3916 list_del(&e->list);
3917 } else {
3918 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003919 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003920 }
3921
Johan Hedberge3846622013-01-09 15:29:33 +02003922 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3923 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003924
3925failed:
3926 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003927 return err;
3928}
3929
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003930static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003931 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003932{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003933 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003934 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003935 int err;
3936
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003937 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003938
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003939 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003940 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3941 MGMT_STATUS_INVALID_PARAMS,
3942 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003943
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003944 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003945
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003946 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003947 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003948 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003949 goto done;
3950 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003951
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003952 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3953 sk);
3954 status = MGMT_STATUS_SUCCESS;
3955
3956done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003957 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003958 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003959
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003960 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003961
3962 return err;
3963}
3964
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003965static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003966 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003967{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003968 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003969 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003970 int err;
3971
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003972 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003973
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003974 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003975 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3976 MGMT_STATUS_INVALID_PARAMS,
3977 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003978
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003979 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003980
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003981 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003982 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003983 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003984 goto done;
3985 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003986
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003987 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3988 sk);
3989 status = MGMT_STATUS_SUCCESS;
3990
3991done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003992 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003993 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003994
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003995 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003996
3997 return err;
3998}
3999
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004000static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4001 u16 len)
4002{
4003 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004004 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004005 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004006 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004007
4008 BT_DBG("%s", hdev->name);
4009
Szymon Jancc72d4b82012-03-16 16:02:57 +01004010 source = __le16_to_cpu(cp->source);
4011
4012 if (source > 0x0002)
4013 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4014 MGMT_STATUS_INVALID_PARAMS);
4015
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004016 hci_dev_lock(hdev);
4017
Szymon Jancc72d4b82012-03-16 16:02:57 +01004018 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004019 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4020 hdev->devid_product = __le16_to_cpu(cp->product);
4021 hdev->devid_version = __le16_to_cpu(cp->version);
4022
4023 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4024
Johan Hedberg890ea892013-03-15 17:06:52 -05004025 hci_req_init(&req, hdev);
4026 update_eir(&req);
4027 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004028
4029 hci_dev_unlock(hdev);
4030
4031 return err;
4032}
4033
Johan Hedberg4375f102013-09-25 13:26:10 +03004034static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4035{
4036 struct cmd_lookup match = { NULL, hdev };
4037
4038 if (status) {
4039 u8 mgmt_err = mgmt_status(status);
4040
4041 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4042 cmd_status_rsp, &mgmt_err);
4043 return;
4044 }
4045
Johan Hedbergc93bd152014-07-08 15:07:48 +03004046 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4047 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4048 else
4049 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4050
Johan Hedberg4375f102013-09-25 13:26:10 +03004051 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4052 &match);
4053
4054 new_settings(hdev, match.sk);
4055
4056 if (match.sk)
4057 sock_put(match.sk);
4058}
4059
Marcel Holtmann21b51872013-10-10 09:47:53 -07004060static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4061 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004062{
4063 struct mgmt_mode *cp = data;
4064 struct pending_cmd *cmd;
4065 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004066 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004067 int err;
4068
4069 BT_DBG("request for %s", hdev->name);
4070
Johan Hedberge6fe7982013-10-02 15:45:22 +03004071 status = mgmt_le_support(hdev);
4072 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004073 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004074 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004075
4076 if (cp->val != 0x00 && cp->val != 0x01)
4077 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4078 MGMT_STATUS_INVALID_PARAMS);
4079
4080 hci_dev_lock(hdev);
4081
4082 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004083 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004084
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004085 /* The following conditions are ones which mean that we should
4086 * not do any HCI communication but directly send a mgmt
4087 * response to user space (after toggling the flag if
4088 * necessary).
4089 */
4090 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004091 hci_conn_num(hdev, LE_LINK) > 0 ||
4092 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4093 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004094 bool changed = false;
4095
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004096 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4097 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004098 changed = true;
4099 }
4100
4101 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4102 if (err < 0)
4103 goto unlock;
4104
4105 if (changed)
4106 err = new_settings(hdev, sk);
4107
4108 goto unlock;
4109 }
4110
4111 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4112 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4113 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4114 MGMT_STATUS_BUSY);
4115 goto unlock;
4116 }
4117
4118 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4119 if (!cmd) {
4120 err = -ENOMEM;
4121 goto unlock;
4122 }
4123
4124 hci_req_init(&req, hdev);
4125
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004126 if (val)
4127 enable_advertising(&req);
4128 else
4129 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004130
4131 err = hci_req_run(&req, set_advertising_complete);
4132 if (err < 0)
4133 mgmt_pending_remove(cmd);
4134
4135unlock:
4136 hci_dev_unlock(hdev);
4137 return err;
4138}
4139
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004140static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4141 void *data, u16 len)
4142{
4143 struct mgmt_cp_set_static_address *cp = data;
4144 int err;
4145
4146 BT_DBG("%s", hdev->name);
4147
Marcel Holtmann62af4442013-10-02 22:10:32 -07004148 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004149 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004150 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004151
4152 if (hdev_is_powered(hdev))
4153 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4154 MGMT_STATUS_REJECTED);
4155
4156 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4157 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4158 return cmd_status(sk, hdev->id,
4159 MGMT_OP_SET_STATIC_ADDRESS,
4160 MGMT_STATUS_INVALID_PARAMS);
4161
4162 /* Two most significant bits shall be set */
4163 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4164 return cmd_status(sk, hdev->id,
4165 MGMT_OP_SET_STATIC_ADDRESS,
4166 MGMT_STATUS_INVALID_PARAMS);
4167 }
4168
4169 hci_dev_lock(hdev);
4170
4171 bacpy(&hdev->static_addr, &cp->bdaddr);
4172
4173 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4174
4175 hci_dev_unlock(hdev);
4176
4177 return err;
4178}
4179
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004180static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4181 void *data, u16 len)
4182{
4183 struct mgmt_cp_set_scan_params *cp = data;
4184 __u16 interval, window;
4185 int err;
4186
4187 BT_DBG("%s", hdev->name);
4188
4189 if (!lmp_le_capable(hdev))
4190 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4191 MGMT_STATUS_NOT_SUPPORTED);
4192
4193 interval = __le16_to_cpu(cp->interval);
4194
4195 if (interval < 0x0004 || interval > 0x4000)
4196 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4197 MGMT_STATUS_INVALID_PARAMS);
4198
4199 window = __le16_to_cpu(cp->window);
4200
4201 if (window < 0x0004 || window > 0x4000)
4202 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4203 MGMT_STATUS_INVALID_PARAMS);
4204
Marcel Holtmann899e1072013-10-14 09:55:32 -07004205 if (window > interval)
4206 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4207 MGMT_STATUS_INVALID_PARAMS);
4208
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004209 hci_dev_lock(hdev);
4210
4211 hdev->le_scan_interval = interval;
4212 hdev->le_scan_window = window;
4213
4214 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4215
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004216 /* If background scan is running, restart it so new parameters are
4217 * loaded.
4218 */
4219 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4220 hdev->discovery.state == DISCOVERY_STOPPED) {
4221 struct hci_request req;
4222
4223 hci_req_init(&req, hdev);
4224
4225 hci_req_add_le_scan_disable(&req);
4226 hci_req_add_le_passive_scan(&req);
4227
4228 hci_req_run(&req, NULL);
4229 }
4230
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004231 hci_dev_unlock(hdev);
4232
4233 return err;
4234}
4235
Johan Hedberg33e38b32013-03-15 17:07:05 -05004236static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4237{
4238 struct pending_cmd *cmd;
4239
4240 BT_DBG("status 0x%02x", status);
4241
4242 hci_dev_lock(hdev);
4243
4244 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4245 if (!cmd)
4246 goto unlock;
4247
4248 if (status) {
4249 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4250 mgmt_status(status));
4251 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004252 struct mgmt_mode *cp = cmd->param;
4253
4254 if (cp->val)
4255 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4256 else
4257 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4258
Johan Hedberg33e38b32013-03-15 17:07:05 -05004259 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4260 new_settings(hdev, cmd->sk);
4261 }
4262
4263 mgmt_pending_remove(cmd);
4264
4265unlock:
4266 hci_dev_unlock(hdev);
4267}
4268
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004269static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004270 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004271{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004272 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004273 struct pending_cmd *cmd;
4274 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004275 int err;
4276
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004277 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004278
Johan Hedberg56f87902013-10-02 13:43:13 +03004279 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4280 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004281 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4282 MGMT_STATUS_NOT_SUPPORTED);
4283
Johan Hedberga7e80f22013-01-09 16:05:19 +02004284 if (cp->val != 0x00 && cp->val != 0x01)
4285 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4286 MGMT_STATUS_INVALID_PARAMS);
4287
Johan Hedberg5400c042012-02-21 16:40:33 +02004288 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004289 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004290 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004291
4292 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004293 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004294 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004295
4296 hci_dev_lock(hdev);
4297
Johan Hedberg05cbf292013-03-15 17:07:07 -05004298 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4299 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4300 MGMT_STATUS_BUSY);
4301 goto unlock;
4302 }
4303
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004304 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4305 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4306 hdev);
4307 goto unlock;
4308 }
4309
Johan Hedberg33e38b32013-03-15 17:07:05 -05004310 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4311 data, len);
4312 if (!cmd) {
4313 err = -ENOMEM;
4314 goto unlock;
4315 }
4316
4317 hci_req_init(&req, hdev);
4318
Johan Hedberg406d7802013-03-15 17:07:09 -05004319 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004320
4321 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004322 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004323 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004324 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004325 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004326 }
4327
Johan Hedberg33e38b32013-03-15 17:07:05 -05004328unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004329 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004330
Antti Julkuf6422ec2011-06-22 13:11:56 +03004331 return err;
4332}
4333
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004334static void set_bredr_scan(struct hci_request *req)
4335{
4336 struct hci_dev *hdev = req->hdev;
4337 u8 scan = 0;
4338
4339 /* Ensure that fast connectable is disabled. This function will
4340 * not do anything if the page scan parameters are already what
4341 * they should be.
4342 */
4343 write_fast_connectable(req, false);
4344
4345 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4346 scan |= SCAN_PAGE;
4347 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4348 scan |= SCAN_INQUIRY;
4349
4350 if (scan)
4351 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4352}
4353
Johan Hedberg0663ca22013-10-02 13:43:14 +03004354static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4355{
4356 struct pending_cmd *cmd;
4357
4358 BT_DBG("status 0x%02x", status);
4359
4360 hci_dev_lock(hdev);
4361
4362 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4363 if (!cmd)
4364 goto unlock;
4365
4366 if (status) {
4367 u8 mgmt_err = mgmt_status(status);
4368
4369 /* We need to restore the flag if related HCI commands
4370 * failed.
4371 */
4372 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4373
4374 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4375 } else {
4376 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4377 new_settings(hdev, cmd->sk);
4378 }
4379
4380 mgmt_pending_remove(cmd);
4381
4382unlock:
4383 hci_dev_unlock(hdev);
4384}
4385
4386static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4387{
4388 struct mgmt_mode *cp = data;
4389 struct pending_cmd *cmd;
4390 struct hci_request req;
4391 int err;
4392
4393 BT_DBG("request for %s", hdev->name);
4394
4395 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4396 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4397 MGMT_STATUS_NOT_SUPPORTED);
4398
4399 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4400 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4401 MGMT_STATUS_REJECTED);
4402
4403 if (cp->val != 0x00 && cp->val != 0x01)
4404 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4405 MGMT_STATUS_INVALID_PARAMS);
4406
4407 hci_dev_lock(hdev);
4408
4409 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4410 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4411 goto unlock;
4412 }
4413
4414 if (!hdev_is_powered(hdev)) {
4415 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004416 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4417 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4418 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4419 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4420 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4421 }
4422
4423 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4424
4425 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4426 if (err < 0)
4427 goto unlock;
4428
4429 err = new_settings(hdev, sk);
4430 goto unlock;
4431 }
4432
4433 /* Reject disabling when powered on */
4434 if (!cp->val) {
4435 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4436 MGMT_STATUS_REJECTED);
4437 goto unlock;
4438 }
4439
4440 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4441 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4442 MGMT_STATUS_BUSY);
4443 goto unlock;
4444 }
4445
4446 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4447 if (!cmd) {
4448 err = -ENOMEM;
4449 goto unlock;
4450 }
4451
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004452 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004453 * generates the correct flags.
4454 */
4455 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4456
4457 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004458
4459 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4460 set_bredr_scan(&req);
4461
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004462 /* Since only the advertising data flags will change, there
4463 * is no need to update the scan response data.
4464 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004465 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004466
Johan Hedberg0663ca22013-10-02 13:43:14 +03004467 err = hci_req_run(&req, set_bredr_complete);
4468 if (err < 0)
4469 mgmt_pending_remove(cmd);
4470
4471unlock:
4472 hci_dev_unlock(hdev);
4473 return err;
4474}
4475
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004476static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4477 void *data, u16 len)
4478{
4479 struct mgmt_mode *cp = data;
4480 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004481 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004482 int err;
4483
4484 BT_DBG("request for %s", hdev->name);
4485
4486 status = mgmt_bredr_support(hdev);
4487 if (status)
4488 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4489 status);
4490
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004491 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004492 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004493 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4494 MGMT_STATUS_NOT_SUPPORTED);
4495
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004496 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004497 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4498 MGMT_STATUS_INVALID_PARAMS);
4499
4500 hci_dev_lock(hdev);
4501
4502 if (!hdev_is_powered(hdev)) {
4503 bool changed;
4504
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004505 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004506 changed = !test_and_set_bit(HCI_SC_ENABLED,
4507 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004508 if (cp->val == 0x02)
4509 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4510 else
4511 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4512 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004513 changed = test_and_clear_bit(HCI_SC_ENABLED,
4514 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004515 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4516 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004517
4518 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4519 if (err < 0)
4520 goto failed;
4521
4522 if (changed)
4523 err = new_settings(hdev, sk);
4524
4525 goto failed;
4526 }
4527
4528 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4529 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4530 MGMT_STATUS_BUSY);
4531 goto failed;
4532 }
4533
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004534 val = !!cp->val;
4535
4536 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4537 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004538 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4539 goto failed;
4540 }
4541
4542 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4543 if (!cmd) {
4544 err = -ENOMEM;
4545 goto failed;
4546 }
4547
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004548 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004549 if (err < 0) {
4550 mgmt_pending_remove(cmd);
4551 goto failed;
4552 }
4553
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004554 if (cp->val == 0x02)
4555 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4556 else
4557 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4558
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004559failed:
4560 hci_dev_unlock(hdev);
4561 return err;
4562}
4563
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004564static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4565 void *data, u16 len)
4566{
4567 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004568 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004569 int err;
4570
4571 BT_DBG("request for %s", hdev->name);
4572
Johan Hedbergb97109792014-06-24 14:00:28 +03004573 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004574 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4575 MGMT_STATUS_INVALID_PARAMS);
4576
4577 hci_dev_lock(hdev);
4578
4579 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004580 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4581 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004582 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004583 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4584 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004585
Johan Hedbergb97109792014-06-24 14:00:28 +03004586 if (cp->val == 0x02)
4587 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4588 &hdev->dev_flags);
4589 else
4590 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4591 &hdev->dev_flags);
4592
4593 if (hdev_is_powered(hdev) && use_changed &&
4594 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4595 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4596 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4597 sizeof(mode), &mode);
4598 }
4599
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004600 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4601 if (err < 0)
4602 goto unlock;
4603
4604 if (changed)
4605 err = new_settings(hdev, sk);
4606
4607unlock:
4608 hci_dev_unlock(hdev);
4609 return err;
4610}
4611
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004612static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4613 u16 len)
4614{
4615 struct mgmt_cp_set_privacy *cp = cp_data;
4616 bool changed;
4617 int err;
4618
4619 BT_DBG("request for %s", hdev->name);
4620
4621 if (!lmp_le_capable(hdev))
4622 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4623 MGMT_STATUS_NOT_SUPPORTED);
4624
4625 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4626 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4627 MGMT_STATUS_INVALID_PARAMS);
4628
4629 if (hdev_is_powered(hdev))
4630 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4631 MGMT_STATUS_REJECTED);
4632
4633 hci_dev_lock(hdev);
4634
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004635 /* If user space supports this command it is also expected to
4636 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4637 */
4638 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4639
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004640 if (cp->privacy) {
4641 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4642 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4643 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4644 } else {
4645 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4646 memset(hdev->irk, 0, sizeof(hdev->irk));
4647 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4648 }
4649
4650 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4651 if (err < 0)
4652 goto unlock;
4653
4654 if (changed)
4655 err = new_settings(hdev, sk);
4656
4657unlock:
4658 hci_dev_unlock(hdev);
4659 return err;
4660}
4661
Johan Hedberg41edf162014-02-18 10:19:35 +02004662static bool irk_is_valid(struct mgmt_irk_info *irk)
4663{
4664 switch (irk->addr.type) {
4665 case BDADDR_LE_PUBLIC:
4666 return true;
4667
4668 case BDADDR_LE_RANDOM:
4669 /* Two most significant bits shall be set */
4670 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4671 return false;
4672 return true;
4673 }
4674
4675 return false;
4676}
4677
4678static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4679 u16 len)
4680{
4681 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004682 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4683 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004684 u16 irk_count, expected_len;
4685 int i, err;
4686
4687 BT_DBG("request for %s", hdev->name);
4688
4689 if (!lmp_le_capable(hdev))
4690 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4691 MGMT_STATUS_NOT_SUPPORTED);
4692
4693 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004694 if (irk_count > max_irk_count) {
4695 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4696 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4697 MGMT_STATUS_INVALID_PARAMS);
4698 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004699
4700 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4701 if (expected_len != len) {
4702 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004703 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004704 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4705 MGMT_STATUS_INVALID_PARAMS);
4706 }
4707
4708 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4709
4710 for (i = 0; i < irk_count; i++) {
4711 struct mgmt_irk_info *key = &cp->irks[i];
4712
4713 if (!irk_is_valid(key))
4714 return cmd_status(sk, hdev->id,
4715 MGMT_OP_LOAD_IRKS,
4716 MGMT_STATUS_INVALID_PARAMS);
4717 }
4718
4719 hci_dev_lock(hdev);
4720
4721 hci_smp_irks_clear(hdev);
4722
4723 for (i = 0; i < irk_count; i++) {
4724 struct mgmt_irk_info *irk = &cp->irks[i];
4725 u8 addr_type;
4726
4727 if (irk->addr.type == BDADDR_LE_PUBLIC)
4728 addr_type = ADDR_LE_DEV_PUBLIC;
4729 else
4730 addr_type = ADDR_LE_DEV_RANDOM;
4731
4732 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4733 BDADDR_ANY);
4734 }
4735
4736 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4737
4738 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4739
4740 hci_dev_unlock(hdev);
4741
4742 return err;
4743}
4744
Johan Hedberg3f706b72013-01-20 14:27:16 +02004745static bool ltk_is_valid(struct mgmt_ltk_info *key)
4746{
4747 if (key->master != 0x00 && key->master != 0x01)
4748 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004749
4750 switch (key->addr.type) {
4751 case BDADDR_LE_PUBLIC:
4752 return true;
4753
4754 case BDADDR_LE_RANDOM:
4755 /* Two most significant bits shall be set */
4756 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4757 return false;
4758 return true;
4759 }
4760
4761 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004762}
4763
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004764static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004765 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004766{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004767 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004768 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4769 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004770 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004771 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004772
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004773 BT_DBG("request for %s", hdev->name);
4774
4775 if (!lmp_le_capable(hdev))
4776 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4777 MGMT_STATUS_NOT_SUPPORTED);
4778
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004779 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004780 if (key_count > max_key_count) {
4781 BT_ERR("load_ltks: too big key_count value %u", key_count);
4782 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4783 MGMT_STATUS_INVALID_PARAMS);
4784 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004785
4786 expected_len = sizeof(*cp) + key_count *
4787 sizeof(struct mgmt_ltk_info);
4788 if (expected_len != len) {
4789 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004790 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004791 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004792 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004793 }
4794
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004795 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004796
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004797 for (i = 0; i < key_count; i++) {
4798 struct mgmt_ltk_info *key = &cp->keys[i];
4799
Johan Hedberg3f706b72013-01-20 14:27:16 +02004800 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004801 return cmd_status(sk, hdev->id,
4802 MGMT_OP_LOAD_LONG_TERM_KEYS,
4803 MGMT_STATUS_INVALID_PARAMS);
4804 }
4805
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004806 hci_dev_lock(hdev);
4807
4808 hci_smp_ltks_clear(hdev);
4809
4810 for (i = 0; i < key_count; i++) {
4811 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004812 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004813
4814 if (key->addr.type == BDADDR_LE_PUBLIC)
4815 addr_type = ADDR_LE_DEV_PUBLIC;
4816 else
4817 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004818
4819 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004820 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004821 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004822 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004823
Johan Hedberg61b43352014-05-29 19:36:53 +03004824 switch (key->type) {
4825 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004826 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004827 break;
4828 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004829 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004830 break;
4831 default:
4832 continue;
4833 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004834
Johan Hedberg35d70272014-02-19 14:57:47 +02004835 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004836 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004837 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004838 }
4839
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004840 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4841 NULL, 0);
4842
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004843 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004844
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004845 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004846}
4847
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004848struct cmd_conn_lookup {
4849 struct hci_conn *conn;
4850 bool valid_tx_power;
4851 u8 mgmt_status;
4852};
4853
4854static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4855{
4856 struct cmd_conn_lookup *match = data;
4857 struct mgmt_cp_get_conn_info *cp;
4858 struct mgmt_rp_get_conn_info rp;
4859 struct hci_conn *conn = cmd->user_data;
4860
4861 if (conn != match->conn)
4862 return;
4863
4864 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4865
4866 memset(&rp, 0, sizeof(rp));
4867 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4868 rp.addr.type = cp->addr.type;
4869
4870 if (!match->mgmt_status) {
4871 rp.rssi = conn->rssi;
4872
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004873 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004874 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004875 rp.max_tx_power = conn->max_tx_power;
4876 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004877 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004878 rp.max_tx_power = HCI_TX_POWER_INVALID;
4879 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004880 }
4881
4882 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4883 match->mgmt_status, &rp, sizeof(rp));
4884
4885 hci_conn_drop(conn);
4886
4887 mgmt_pending_remove(cmd);
4888}
4889
4890static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4891{
4892 struct hci_cp_read_rssi *cp;
4893 struct hci_conn *conn;
4894 struct cmd_conn_lookup match;
4895 u16 handle;
4896
4897 BT_DBG("status 0x%02x", status);
4898
4899 hci_dev_lock(hdev);
4900
4901 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004902 * otherwise we assume it's not valid. At the moment we assume that
4903 * either both or none of current and max values are valid to keep code
4904 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004905 */
4906 match.valid_tx_power = !status;
4907
4908 /* Commands sent in request are either Read RSSI or Read Transmit Power
4909 * Level so we check which one was last sent to retrieve connection
4910 * handle. Both commands have handle as first parameter so it's safe to
4911 * cast data on the same command struct.
4912 *
4913 * First command sent is always Read RSSI and we fail only if it fails.
4914 * In other case we simply override error to indicate success as we
4915 * already remembered if TX power value is actually valid.
4916 */
4917 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4918 if (!cp) {
4919 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4920 status = 0;
4921 }
4922
4923 if (!cp) {
4924 BT_ERR("invalid sent_cmd in response");
4925 goto unlock;
4926 }
4927
4928 handle = __le16_to_cpu(cp->handle);
4929 conn = hci_conn_hash_lookup_handle(hdev, handle);
4930 if (!conn) {
4931 BT_ERR("unknown handle (%d) in response", handle);
4932 goto unlock;
4933 }
4934
4935 match.conn = conn;
4936 match.mgmt_status = mgmt_status(status);
4937
4938 /* Cache refresh is complete, now reply for mgmt request for given
4939 * connection only.
4940 */
4941 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4942 get_conn_info_complete, &match);
4943
4944unlock:
4945 hci_dev_unlock(hdev);
4946}
4947
4948static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4949 u16 len)
4950{
4951 struct mgmt_cp_get_conn_info *cp = data;
4952 struct mgmt_rp_get_conn_info rp;
4953 struct hci_conn *conn;
4954 unsigned long conn_info_age;
4955 int err = 0;
4956
4957 BT_DBG("%s", hdev->name);
4958
4959 memset(&rp, 0, sizeof(rp));
4960 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4961 rp.addr.type = cp->addr.type;
4962
4963 if (!bdaddr_type_is_valid(cp->addr.type))
4964 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4965 MGMT_STATUS_INVALID_PARAMS,
4966 &rp, sizeof(rp));
4967
4968 hci_dev_lock(hdev);
4969
4970 if (!hdev_is_powered(hdev)) {
4971 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4972 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4973 goto unlock;
4974 }
4975
4976 if (cp->addr.type == BDADDR_BREDR)
4977 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4978 &cp->addr.bdaddr);
4979 else
4980 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4981
4982 if (!conn || conn->state != BT_CONNECTED) {
4983 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4984 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4985 goto unlock;
4986 }
4987
4988 /* To avoid client trying to guess when to poll again for information we
4989 * calculate conn info age as random value between min/max set in hdev.
4990 */
4991 conn_info_age = hdev->conn_info_min_age +
4992 prandom_u32_max(hdev->conn_info_max_age -
4993 hdev->conn_info_min_age);
4994
4995 /* Query controller to refresh cached values if they are too old or were
4996 * never read.
4997 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004998 if (time_after(jiffies, conn->conn_info_timestamp +
4999 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005000 !conn->conn_info_timestamp) {
5001 struct hci_request req;
5002 struct hci_cp_read_tx_power req_txp_cp;
5003 struct hci_cp_read_rssi req_rssi_cp;
5004 struct pending_cmd *cmd;
5005
5006 hci_req_init(&req, hdev);
5007 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5008 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5009 &req_rssi_cp);
5010
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005011 /* For LE links TX power does not change thus we don't need to
5012 * query for it once value is known.
5013 */
5014 if (!bdaddr_type_is_le(cp->addr.type) ||
5015 conn->tx_power == HCI_TX_POWER_INVALID) {
5016 req_txp_cp.handle = cpu_to_le16(conn->handle);
5017 req_txp_cp.type = 0x00;
5018 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5019 sizeof(req_txp_cp), &req_txp_cp);
5020 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005021
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005022 /* Max TX power needs to be read only once per connection */
5023 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5024 req_txp_cp.handle = cpu_to_le16(conn->handle);
5025 req_txp_cp.type = 0x01;
5026 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5027 sizeof(req_txp_cp), &req_txp_cp);
5028 }
5029
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005030 err = hci_req_run(&req, conn_info_refresh_complete);
5031 if (err < 0)
5032 goto unlock;
5033
5034 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5035 data, len);
5036 if (!cmd) {
5037 err = -ENOMEM;
5038 goto unlock;
5039 }
5040
5041 hci_conn_hold(conn);
5042 cmd->user_data = conn;
5043
5044 conn->conn_info_timestamp = jiffies;
5045 } else {
5046 /* Cache is valid, just reply with values cached in hci_conn */
5047 rp.rssi = conn->rssi;
5048 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005049 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005050
5051 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5052 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5053 }
5054
5055unlock:
5056 hci_dev_unlock(hdev);
5057 return err;
5058}
5059
Johan Hedberg95868422014-06-28 17:54:07 +03005060static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5061{
5062 struct mgmt_cp_get_clock_info *cp;
5063 struct mgmt_rp_get_clock_info rp;
5064 struct hci_cp_read_clock *hci_cp;
5065 struct pending_cmd *cmd;
5066 struct hci_conn *conn;
5067
5068 BT_DBG("%s status %u", hdev->name, status);
5069
5070 hci_dev_lock(hdev);
5071
5072 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5073 if (!hci_cp)
5074 goto unlock;
5075
5076 if (hci_cp->which) {
5077 u16 handle = __le16_to_cpu(hci_cp->handle);
5078 conn = hci_conn_hash_lookup_handle(hdev, handle);
5079 } else {
5080 conn = NULL;
5081 }
5082
5083 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5084 if (!cmd)
5085 goto unlock;
5086
5087 cp = cmd->param;
5088
5089 memset(&rp, 0, sizeof(rp));
5090 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5091
5092 if (status)
5093 goto send_rsp;
5094
5095 rp.local_clock = cpu_to_le32(hdev->clock);
5096
5097 if (conn) {
5098 rp.piconet_clock = cpu_to_le32(conn->clock);
5099 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5100 }
5101
5102send_rsp:
5103 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5104 &rp, sizeof(rp));
5105 mgmt_pending_remove(cmd);
5106 if (conn)
5107 hci_conn_drop(conn);
5108
5109unlock:
5110 hci_dev_unlock(hdev);
5111}
5112
5113static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5114 u16 len)
5115{
5116 struct mgmt_cp_get_clock_info *cp = data;
5117 struct mgmt_rp_get_clock_info rp;
5118 struct hci_cp_read_clock hci_cp;
5119 struct pending_cmd *cmd;
5120 struct hci_request req;
5121 struct hci_conn *conn;
5122 int err;
5123
5124 BT_DBG("%s", hdev->name);
5125
5126 memset(&rp, 0, sizeof(rp));
5127 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5128 rp.addr.type = cp->addr.type;
5129
5130 if (cp->addr.type != BDADDR_BREDR)
5131 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5132 MGMT_STATUS_INVALID_PARAMS,
5133 &rp, sizeof(rp));
5134
5135 hci_dev_lock(hdev);
5136
5137 if (!hdev_is_powered(hdev)) {
5138 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5139 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5140 goto unlock;
5141 }
5142
5143 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5144 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5145 &cp->addr.bdaddr);
5146 if (!conn || conn->state != BT_CONNECTED) {
5147 err = cmd_complete(sk, hdev->id,
5148 MGMT_OP_GET_CLOCK_INFO,
5149 MGMT_STATUS_NOT_CONNECTED,
5150 &rp, sizeof(rp));
5151 goto unlock;
5152 }
5153 } else {
5154 conn = NULL;
5155 }
5156
5157 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5158 if (!cmd) {
5159 err = -ENOMEM;
5160 goto unlock;
5161 }
5162
5163 hci_req_init(&req, hdev);
5164
5165 memset(&hci_cp, 0, sizeof(hci_cp));
5166 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5167
5168 if (conn) {
5169 hci_conn_hold(conn);
5170 cmd->user_data = conn;
5171
5172 hci_cp.handle = cpu_to_le16(conn->handle);
5173 hci_cp.which = 0x01; /* Piconet clock */
5174 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5175 }
5176
5177 err = hci_req_run(&req, get_clock_info_complete);
5178 if (err < 0)
5179 mgmt_pending_remove(cmd);
5180
5181unlock:
5182 hci_dev_unlock(hdev);
5183 return err;
5184}
5185
Marcel Holtmann8afef092014-06-29 22:28:34 +02005186static void device_added(struct sock *sk, struct hci_dev *hdev,
5187 bdaddr_t *bdaddr, u8 type, u8 action)
5188{
5189 struct mgmt_ev_device_added ev;
5190
5191 bacpy(&ev.addr.bdaddr, bdaddr);
5192 ev.addr.type = type;
5193 ev.action = action;
5194
5195 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5196}
5197
Marcel Holtmann2faade52014-06-29 19:44:03 +02005198static int add_device(struct sock *sk, struct hci_dev *hdev,
5199 void *data, u16 len)
5200{
5201 struct mgmt_cp_add_device *cp = data;
5202 u8 auto_conn, addr_type;
5203 int err;
5204
5205 BT_DBG("%s", hdev->name);
5206
5207 if (!bdaddr_type_is_le(cp->addr.type) ||
5208 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5209 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5210 MGMT_STATUS_INVALID_PARAMS,
5211 &cp->addr, sizeof(cp->addr));
5212
5213 if (cp->action != 0x00 && cp->action != 0x01)
5214 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5215 MGMT_STATUS_INVALID_PARAMS,
5216 &cp->addr, sizeof(cp->addr));
5217
5218 hci_dev_lock(hdev);
5219
5220 if (cp->addr.type == BDADDR_LE_PUBLIC)
5221 addr_type = ADDR_LE_DEV_PUBLIC;
5222 else
5223 addr_type = ADDR_LE_DEV_RANDOM;
5224
5225 if (cp->action)
5226 auto_conn = HCI_AUTO_CONN_ALWAYS;
5227 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005228 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005229
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005230 /* If the connection parameters don't exist for this device,
5231 * they will be created and configured with defaults.
5232 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005233 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5234 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005235 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5236 MGMT_STATUS_FAILED,
5237 &cp->addr, sizeof(cp->addr));
5238 goto unlock;
5239 }
5240
Marcel Holtmann8afef092014-06-29 22:28:34 +02005241 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5242
Marcel Holtmann2faade52014-06-29 19:44:03 +02005243 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5244 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5245
5246unlock:
5247 hci_dev_unlock(hdev);
5248 return err;
5249}
5250
Marcel Holtmann8afef092014-06-29 22:28:34 +02005251static void device_removed(struct sock *sk, struct hci_dev *hdev,
5252 bdaddr_t *bdaddr, u8 type)
5253{
5254 struct mgmt_ev_device_removed ev;
5255
5256 bacpy(&ev.addr.bdaddr, bdaddr);
5257 ev.addr.type = type;
5258
5259 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5260}
5261
Marcel Holtmann2faade52014-06-29 19:44:03 +02005262static int remove_device(struct sock *sk, struct hci_dev *hdev,
5263 void *data, u16 len)
5264{
5265 struct mgmt_cp_remove_device *cp = data;
5266 int err;
5267
5268 BT_DBG("%s", hdev->name);
5269
5270 hci_dev_lock(hdev);
5271
5272 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005273 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005274 u8 addr_type;
5275
5276 if (!bdaddr_type_is_le(cp->addr.type)) {
5277 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5278 MGMT_STATUS_INVALID_PARAMS,
5279 &cp->addr, sizeof(cp->addr));
5280 goto unlock;
5281 }
5282
5283 if (cp->addr.type == BDADDR_LE_PUBLIC)
5284 addr_type = ADDR_LE_DEV_PUBLIC;
5285 else
5286 addr_type = ADDR_LE_DEV_RANDOM;
5287
Johan Hedbergc71593d2014-07-02 17:37:28 +03005288 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5289 addr_type);
5290 if (!params) {
5291 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5292 MGMT_STATUS_INVALID_PARAMS,
5293 &cp->addr, sizeof(cp->addr));
5294 goto unlock;
5295 }
5296
5297 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5298 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5299 MGMT_STATUS_INVALID_PARAMS,
5300 &cp->addr, sizeof(cp->addr));
5301 goto unlock;
5302 }
5303
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005304 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005305 list_del(&params->list);
5306 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005307 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005308
5309 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005310 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005311 struct hci_conn_params *p, *tmp;
5312
Marcel Holtmann2faade52014-06-29 19:44:03 +02005313 if (cp->addr.type) {
5314 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5315 MGMT_STATUS_INVALID_PARAMS,
5316 &cp->addr, sizeof(cp->addr));
5317 goto unlock;
5318 }
5319
Johan Hedberg19de0822014-07-06 13:06:51 +03005320 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5321 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5322 continue;
5323 device_removed(sk, hdev, &p->addr, p->addr_type);
5324 list_del(&p->action);
5325 list_del(&p->list);
5326 kfree(p);
5327 }
5328
5329 BT_DBG("All LE connection parameters were removed");
5330
5331 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005332 }
5333
5334 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5335 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5336
5337unlock:
5338 hci_dev_unlock(hdev);
5339 return err;
5340}
5341
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005342static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5343 u16 len)
5344{
5345 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005346 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5347 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005348 u16 param_count, expected_len;
5349 int i;
5350
5351 if (!lmp_le_capable(hdev))
5352 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5353 MGMT_STATUS_NOT_SUPPORTED);
5354
5355 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005356 if (param_count > max_param_count) {
5357 BT_ERR("load_conn_param: too big param_count value %u",
5358 param_count);
5359 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5360 MGMT_STATUS_INVALID_PARAMS);
5361 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005362
5363 expected_len = sizeof(*cp) + param_count *
5364 sizeof(struct mgmt_conn_param);
5365 if (expected_len != len) {
5366 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5367 expected_len, len);
5368 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5369 MGMT_STATUS_INVALID_PARAMS);
5370 }
5371
5372 BT_DBG("%s param_count %u", hdev->name, param_count);
5373
5374 hci_dev_lock(hdev);
5375
5376 hci_conn_params_clear_disabled(hdev);
5377
5378 for (i = 0; i < param_count; i++) {
5379 struct mgmt_conn_param *param = &cp->params[i];
5380 struct hci_conn_params *hci_param;
5381 u16 min, max, latency, timeout;
5382 u8 addr_type;
5383
5384 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5385 param->addr.type);
5386
5387 if (param->addr.type == BDADDR_LE_PUBLIC) {
5388 addr_type = ADDR_LE_DEV_PUBLIC;
5389 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5390 addr_type = ADDR_LE_DEV_RANDOM;
5391 } else {
5392 BT_ERR("Ignoring invalid connection parameters");
5393 continue;
5394 }
5395
5396 min = le16_to_cpu(param->min_interval);
5397 max = le16_to_cpu(param->max_interval);
5398 latency = le16_to_cpu(param->latency);
5399 timeout = le16_to_cpu(param->timeout);
5400
5401 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5402 min, max, latency, timeout);
5403
5404 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5405 BT_ERR("Ignoring invalid connection parameters");
5406 continue;
5407 }
5408
5409 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5410 addr_type);
5411 if (!hci_param) {
5412 BT_ERR("Failed to add connection parameters");
5413 continue;
5414 }
5415
5416 hci_param->conn_min_interval = min;
5417 hci_param->conn_max_interval = max;
5418 hci_param->conn_latency = latency;
5419 hci_param->supervision_timeout = timeout;
5420 }
5421
5422 hci_dev_unlock(hdev);
5423
5424 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5425}
5426
Marcel Holtmanndbece372014-07-04 18:11:55 +02005427static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5428 void *data, u16 len)
5429{
5430 struct mgmt_cp_set_external_config *cp = data;
5431 bool changed;
5432 int err;
5433
5434 BT_DBG("%s", hdev->name);
5435
5436 if (hdev_is_powered(hdev))
5437 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5438 MGMT_STATUS_REJECTED);
5439
5440 if (cp->config != 0x00 && cp->config != 0x01)
5441 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5442 MGMT_STATUS_INVALID_PARAMS);
5443
5444 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5445 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5446 MGMT_STATUS_NOT_SUPPORTED);
5447
5448 hci_dev_lock(hdev);
5449
5450 if (cp->config)
5451 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5452 &hdev->dev_flags);
5453 else
5454 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5455 &hdev->dev_flags);
5456
5457 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5458 if (err < 0)
5459 goto unlock;
5460
5461 if (!changed)
5462 goto unlock;
5463
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005464 err = new_options(hdev, sk);
5465
Marcel Holtmanndbece372014-07-04 18:11:55 +02005466 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5467 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005468
5469 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5470 set_bit(HCI_CONFIG, &hdev->dev_flags);
5471 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5472
5473 queue_work(hdev->req_workqueue, &hdev->power_on);
5474 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005475 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005476 mgmt_index_added(hdev);
5477 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005478 }
5479
5480unlock:
5481 hci_dev_unlock(hdev);
5482 return err;
5483}
5484
Marcel Holtmann9713c172014-07-06 12:11:15 +02005485static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5486 void *data, u16 len)
5487{
5488 struct mgmt_cp_set_public_address *cp = data;
5489 bool changed;
5490 int err;
5491
5492 BT_DBG("%s", hdev->name);
5493
5494 if (hdev_is_powered(hdev))
5495 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5496 MGMT_STATUS_REJECTED);
5497
5498 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5499 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5500 MGMT_STATUS_INVALID_PARAMS);
5501
5502 if (!hdev->set_bdaddr)
5503 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5504 MGMT_STATUS_NOT_SUPPORTED);
5505
5506 hci_dev_lock(hdev);
5507
5508 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5509 bacpy(&hdev->public_addr, &cp->bdaddr);
5510
5511 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5512 if (err < 0)
5513 goto unlock;
5514
5515 if (!changed)
5516 goto unlock;
5517
5518 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5519 err = new_options(hdev, sk);
5520
5521 if (is_configured(hdev)) {
5522 mgmt_index_removed(hdev);
5523
5524 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5525
5526 set_bit(HCI_CONFIG, &hdev->dev_flags);
5527 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5528
5529 queue_work(hdev->req_workqueue, &hdev->power_on);
5530 }
5531
5532unlock:
5533 hci_dev_unlock(hdev);
5534 return err;
5535}
5536
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005537static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005538 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5539 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005540 bool var_len;
5541 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005542} mgmt_handlers[] = {
5543 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005544 { read_version, false, MGMT_READ_VERSION_SIZE },
5545 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5546 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5547 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5548 { set_powered, false, MGMT_SETTING_SIZE },
5549 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5550 { set_connectable, false, MGMT_SETTING_SIZE },
5551 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5552 { set_pairable, false, MGMT_SETTING_SIZE },
5553 { set_link_security, false, MGMT_SETTING_SIZE },
5554 { set_ssp, false, MGMT_SETTING_SIZE },
5555 { set_hs, false, MGMT_SETTING_SIZE },
5556 { set_le, false, MGMT_SETTING_SIZE },
5557 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5558 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5559 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5560 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5561 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5562 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5563 { disconnect, false, MGMT_DISCONNECT_SIZE },
5564 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5565 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5566 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5567 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5568 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5569 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5570 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5571 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5572 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5573 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5574 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5575 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005576 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005577 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5578 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5579 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5580 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5581 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5582 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005583 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005584 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005585 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005586 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005587 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005588 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005589 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005590 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005591 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005592 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005593 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005594 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5595 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005596 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5597 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005598 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005599 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005600 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005601};
5602
Johan Hedberg03811012010-12-08 00:21:06 +02005603int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5604{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005605 void *buf;
5606 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005607 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005608 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005609 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005610 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005611 int err;
5612
5613 BT_DBG("got %zu bytes", msglen);
5614
5615 if (msglen < sizeof(*hdr))
5616 return -EINVAL;
5617
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005618 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005619 if (!buf)
5620 return -ENOMEM;
5621
5622 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5623 err = -EFAULT;
5624 goto done;
5625 }
5626
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005627 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005628 opcode = __le16_to_cpu(hdr->opcode);
5629 index = __le16_to_cpu(hdr->index);
5630 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005631
5632 if (len != msglen - sizeof(*hdr)) {
5633 err = -EINVAL;
5634 goto done;
5635 }
5636
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005637 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005638 hdev = hci_dev_get(index);
5639 if (!hdev) {
5640 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005641 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005642 goto done;
5643 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005644
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005645 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005646 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005647 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005648 err = cmd_status(sk, index, opcode,
5649 MGMT_STATUS_INVALID_INDEX);
5650 goto done;
5651 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005652
5653 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005654 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005655 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5656 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005657 err = cmd_status(sk, index, opcode,
5658 MGMT_STATUS_INVALID_INDEX);
5659 goto done;
5660 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005661 }
5662
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005663 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005664 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005665 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005666 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005667 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005668 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005669 }
5670
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005671 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5672 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5673 err = cmd_status(sk, index, opcode,
5674 MGMT_STATUS_INVALID_INDEX);
5675 goto done;
5676 }
5677
5678 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5679 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005680 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005681 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005682 goto done;
5683 }
5684
Johan Hedbergbe22b542012-03-01 22:24:41 +02005685 handler = &mgmt_handlers[opcode];
5686
5687 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005688 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005689 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005690 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005691 goto done;
5692 }
5693
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005694 if (hdev)
5695 mgmt_init_hdev(sk, hdev);
5696
5697 cp = buf + sizeof(*hdr);
5698
Johan Hedbergbe22b542012-03-01 22:24:41 +02005699 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005700 if (err < 0)
5701 goto done;
5702
Johan Hedberg03811012010-12-08 00:21:06 +02005703 err = msglen;
5704
5705done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005706 if (hdev)
5707 hci_dev_put(hdev);
5708
Johan Hedberg03811012010-12-08 00:21:06 +02005709 kfree(buf);
5710 return err;
5711}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005712
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005713void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005714{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005715 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005716 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005717
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005718 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5719 return;
5720
5721 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5722 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5723 else
5724 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005725}
5726
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005727void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005728{
Johan Hedberg5f159032012-03-02 03:13:19 +02005729 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005730
Marcel Holtmann1514b892013-10-06 08:25:01 -07005731 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005732 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005733
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005734 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5735 return;
5736
Johan Hedberg744cf192011-11-08 20:40:14 +02005737 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005738
Marcel Holtmannedd38962014-07-02 21:30:55 +02005739 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5740 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5741 else
5742 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005743}
5744
Andre Guedes6046dc32014-02-26 20:21:51 -03005745/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005746static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005747{
5748 struct hci_conn_params *p;
5749
5750 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005751 /* Needed for AUTO_OFF case where might not "really"
5752 * have been powered off.
5753 */
5754 list_del_init(&p->action);
5755
5756 switch (p->auto_connect) {
5757 case HCI_AUTO_CONN_ALWAYS:
5758 list_add(&p->action, &hdev->pend_le_conns);
5759 break;
5760 case HCI_AUTO_CONN_REPORT:
5761 list_add(&p->action, &hdev->pend_le_reports);
5762 break;
5763 default:
5764 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005765 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005766 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005767
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005768 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005769}
5770
Johan Hedberg229ab392013-03-15 17:06:53 -05005771static void powered_complete(struct hci_dev *hdev, u8 status)
5772{
5773 struct cmd_lookup match = { NULL, hdev };
5774
5775 BT_DBG("status 0x%02x", status);
5776
5777 hci_dev_lock(hdev);
5778
Johan Hedbergd7347f32014-07-04 12:37:23 +03005779 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005780
Johan Hedberg229ab392013-03-15 17:06:53 -05005781 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5782
5783 new_settings(hdev, match.sk);
5784
5785 hci_dev_unlock(hdev);
5786
5787 if (match.sk)
5788 sock_put(match.sk);
5789}
5790
Johan Hedberg70da6242013-03-15 17:06:51 -05005791static int powered_update_hci(struct hci_dev *hdev)
5792{
Johan Hedberg890ea892013-03-15 17:06:52 -05005793 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005794 u8 link_sec;
5795
Johan Hedberg890ea892013-03-15 17:06:52 -05005796 hci_req_init(&req, hdev);
5797
Johan Hedberg70da6242013-03-15 17:06:51 -05005798 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5799 !lmp_host_ssp_capable(hdev)) {
5800 u8 ssp = 1;
5801
Johan Hedberg890ea892013-03-15 17:06:52 -05005802 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005803 }
5804
Johan Hedbergc73eee92013-04-19 18:35:21 +03005805 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5806 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005807 struct hci_cp_write_le_host_supported cp;
5808
5809 cp.le = 1;
5810 cp.simul = lmp_le_br_capable(hdev);
5811
5812 /* Check first if we already have the right
5813 * host state (host features set)
5814 */
5815 if (cp.le != lmp_host_le_capable(hdev) ||
5816 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005817 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5818 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005819 }
5820
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005821 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005822 /* Make sure the controller has a good default for
5823 * advertising data. This also applies to the case
5824 * where BR/EDR was toggled during the AUTO_OFF phase.
5825 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005826 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005827 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005828 update_scan_rsp_data(&req);
5829 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005830
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005831 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5832 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005833 }
5834
Johan Hedberg70da6242013-03-15 17:06:51 -05005835 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5836 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005837 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5838 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005839
5840 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005841 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5842 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005843 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005844 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005845 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005846 }
5847
Johan Hedberg229ab392013-03-15 17:06:53 -05005848 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005849}
5850
Johan Hedberg744cf192011-11-08 20:40:14 +02005851int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005852{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005853 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005854 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5855 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005856 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005857
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005858 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5859 return 0;
5860
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005861 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005862 if (powered_update_hci(hdev) == 0)
5863 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005864
Johan Hedberg229ab392013-03-15 17:06:53 -05005865 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5866 &match);
5867 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005868 }
5869
Johan Hedberg229ab392013-03-15 17:06:53 -05005870 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5871 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5872
5873 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5874 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5875 zero_cod, sizeof(zero_cod), NULL);
5876
5877new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005878 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005879
5880 if (match.sk)
5881 sock_put(match.sk);
5882
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005883 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005884}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005885
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005886void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005887{
5888 struct pending_cmd *cmd;
5889 u8 status;
5890
5891 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5892 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005893 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005894
5895 if (err == -ERFKILL)
5896 status = MGMT_STATUS_RFKILLED;
5897 else
5898 status = MGMT_STATUS_FAILED;
5899
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005900 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005901
5902 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005903}
5904
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005905void mgmt_discoverable_timeout(struct hci_dev *hdev)
5906{
5907 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005908
5909 hci_dev_lock(hdev);
5910
5911 /* When discoverable timeout triggers, then just make sure
5912 * the limited discoverable flag is cleared. Even in the case
5913 * of a timeout triggered from general discoverable, it is
5914 * safe to unconditionally clear the flag.
5915 */
5916 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005917 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005918
5919 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005920 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5921 u8 scan = SCAN_PAGE;
5922 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5923 sizeof(scan), &scan);
5924 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005925 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005926 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005927 hci_req_run(&req, NULL);
5928
5929 hdev->discov_timeout = 0;
5930
Johan Hedberg9a43e252013-10-20 19:00:07 +03005931 new_settings(hdev, NULL);
5932
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005933 hci_dev_unlock(hdev);
5934}
5935
Marcel Holtmann86a75642013-10-15 06:33:54 -07005936void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005937{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005938 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005939
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005940 /* Nothing needed here if there's a pending command since that
5941 * commands request completion callback takes care of everything
5942 * necessary.
5943 */
5944 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005945 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005946
Johan Hedbergbd107992014-02-24 14:52:19 +02005947 /* Powering off may clear the scan mode - don't let that interfere */
5948 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5949 return;
5950
Johan Hedberg9a43e252013-10-20 19:00:07 +03005951 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005952 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005953 } else {
5954 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005955 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005956 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005957
Johan Hedberg9a43e252013-10-20 19:00:07 +03005958 if (changed) {
5959 struct hci_request req;
5960
5961 /* In case this change in discoverable was triggered by
5962 * a disabling of connectable there could be a need to
5963 * update the advertising flags.
5964 */
5965 hci_req_init(&req, hdev);
5966 update_adv_data(&req);
5967 hci_req_run(&req, NULL);
5968
Marcel Holtmann86a75642013-10-15 06:33:54 -07005969 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005970 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005971}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005972
Marcel Holtmanna3309162013-10-15 06:33:55 -07005973void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005974{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005975 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005976
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005977 /* Nothing needed here if there's a pending command since that
5978 * commands request completion callback takes care of everything
5979 * necessary.
5980 */
5981 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005982 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005983
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005984 /* Powering off may clear the scan mode - don't let that interfere */
5985 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5986 return;
5987
Marcel Holtmanna3309162013-10-15 06:33:55 -07005988 if (connectable)
5989 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5990 else
5991 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005992
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005993 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005994 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005995}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005996
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005997void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005998{
Johan Hedbergca69b792011-11-11 18:10:00 +02005999 u8 mgmt_err = mgmt_status(status);
6000
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006001 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02006002 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006003 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006004
6005 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02006006 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006007 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006008}
6009
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006010void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6011 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006012{
Johan Hedberg86742e12011-11-07 23:13:38 +02006013 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006014
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006015 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006016
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006017 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006018 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006019 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006020 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006021 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006022 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006023
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006024 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006025}
Johan Hedbergf7520542011-01-20 12:34:39 +02006026
Johan Hedbergd7b25452014-05-23 13:19:53 +03006027static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6028{
6029 if (ltk->authenticated)
6030 return MGMT_LTK_AUTHENTICATED;
6031
6032 return MGMT_LTK_UNAUTHENTICATED;
6033}
6034
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006035void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006036{
6037 struct mgmt_ev_new_long_term_key ev;
6038
6039 memset(&ev, 0, sizeof(ev));
6040
Marcel Holtmann5192d302014-02-19 17:11:58 -08006041 /* Devices using resolvable or non-resolvable random addresses
6042 * without providing an indentity resolving key don't require
6043 * to store long term keys. Their addresses will change the
6044 * next time around.
6045 *
6046 * Only when a remote device provides an identity address
6047 * make sure the long term key is stored. If the remote
6048 * identity is known, the long term keys are internally
6049 * mapped to the identity address. So allow static random
6050 * and public addresses here.
6051 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006052 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6053 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6054 ev.store_hint = 0x00;
6055 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006056 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006057
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006058 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006059 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006060 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006061 ev.key.enc_size = key->enc_size;
6062 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006063 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006064
Johan Hedberg2ceba532014-06-16 19:25:16 +03006065 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006066 ev.key.master = 1;
6067
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006068 memcpy(ev.key.val, key->val, sizeof(key->val));
6069
Marcel Holtmann083368f2013-10-15 14:26:29 -07006070 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006071}
6072
Johan Hedberg95fbac82014-02-19 15:18:31 +02006073void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6074{
6075 struct mgmt_ev_new_irk ev;
6076
6077 memset(&ev, 0, sizeof(ev));
6078
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006079 /* For identity resolving keys from devices that are already
6080 * using a public address or static random address, do not
6081 * ask for storing this key. The identity resolving key really
6082 * is only mandatory for devices using resovlable random
6083 * addresses.
6084 *
6085 * Storing all identity resolving keys has the downside that
6086 * they will be also loaded on next boot of they system. More
6087 * identity resolving keys, means more time during scanning is
6088 * needed to actually resolve these addresses.
6089 */
6090 if (bacmp(&irk->rpa, BDADDR_ANY))
6091 ev.store_hint = 0x01;
6092 else
6093 ev.store_hint = 0x00;
6094
Johan Hedberg95fbac82014-02-19 15:18:31 +02006095 bacpy(&ev.rpa, &irk->rpa);
6096 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6097 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6098 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6099
6100 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6101}
6102
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006103void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6104 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006105{
6106 struct mgmt_ev_new_csrk ev;
6107
6108 memset(&ev, 0, sizeof(ev));
6109
6110 /* Devices using resolvable or non-resolvable random addresses
6111 * without providing an indentity resolving key don't require
6112 * to store signature resolving keys. Their addresses will change
6113 * the next time around.
6114 *
6115 * Only when a remote device provides an identity address
6116 * make sure the signature resolving key is stored. So allow
6117 * static random and public addresses here.
6118 */
6119 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6120 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6121 ev.store_hint = 0x00;
6122 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006123 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006124
6125 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6126 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6127 ev.key.master = csrk->master;
6128 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6129
6130 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6131}
6132
Andre Guedesffb5a8272014-07-01 18:10:11 -03006133void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006134 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6135 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006136{
6137 struct mgmt_ev_new_conn_param ev;
6138
Johan Hedbergc103aea2014-07-02 17:37:34 +03006139 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6140 return;
6141
Andre Guedesffb5a8272014-07-01 18:10:11 -03006142 memset(&ev, 0, sizeof(ev));
6143 bacpy(&ev.addr.bdaddr, bdaddr);
6144 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006145 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006146 ev.min_interval = cpu_to_le16(min_interval);
6147 ev.max_interval = cpu_to_le16(max_interval);
6148 ev.latency = cpu_to_le16(latency);
6149 ev.timeout = cpu_to_le16(timeout);
6150
6151 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6152}
6153
Marcel Holtmann94933992013-10-15 10:26:39 -07006154static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6155 u8 data_len)
6156{
6157 eir[eir_len++] = sizeof(type) + data_len;
6158 eir[eir_len++] = type;
6159 memcpy(&eir[eir_len], data, data_len);
6160 eir_len += data_len;
6161
6162 return eir_len;
6163}
6164
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006165void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6166 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6167 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006168{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006169 char buf[512];
6170 struct mgmt_ev_device_connected *ev = (void *) buf;
6171 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006172
Johan Hedbergb644ba32012-01-17 21:48:47 +02006173 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006174 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006175
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006176 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006177
Johan Hedbergb644ba32012-01-17 21:48:47 +02006178 if (name_len > 0)
6179 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006180 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006181
6182 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006183 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006184 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006185
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006186 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006187
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006188 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6189 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006190}
6191
Johan Hedberg8962ee72011-01-20 12:40:27 +02006192static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6193{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006194 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006195 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006196 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006197
Johan Hedberg88c3df12012-02-09 14:27:38 +02006198 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6199 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006200
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006201 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006202 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006203
6204 *sk = cmd->sk;
6205 sock_hold(*sk);
6206
Johan Hedberga664b5b2011-02-19 12:06:02 -03006207 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006208}
6209
Johan Hedberg124f6e32012-02-09 13:50:12 +02006210static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006211{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006212 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006213 struct mgmt_cp_unpair_device *cp = cmd->param;
6214 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006215
6216 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006217 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6218 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006219
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006220 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6221
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006222 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006223
6224 mgmt_pending_remove(cmd);
6225}
6226
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006227void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006228 u8 link_type, u8 addr_type, u8 reason,
6229 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006230{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006231 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006232 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006233 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006234
Johan Hedberg8b064a32014-02-24 14:52:22 +02006235 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6236 if (power_off) {
6237 struct mgmt_mode *cp = power_off->param;
6238
6239 /* The connection is still in hci_conn_hash so test for 1
6240 * instead of 0 to know if this is the last one.
6241 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006242 if (!cp->val && hci_conn_count(hdev) == 1) {
6243 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006244 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006245 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006246 }
6247
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006248 if (!mgmt_connected)
6249 return;
6250
Andre Guedes57eb7762013-10-30 19:01:41 -03006251 if (link_type != ACL_LINK && link_type != LE_LINK)
6252 return;
6253
Johan Hedberg744cf192011-11-08 20:40:14 +02006254 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006255
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006256 bacpy(&ev.addr.bdaddr, bdaddr);
6257 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6258 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006259
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006260 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006261
6262 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006263 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006264
Johan Hedberg124f6e32012-02-09 13:50:12 +02006265 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006266 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006267}
6268
Marcel Holtmann78929242013-10-06 23:55:47 -07006269void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6270 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006271{
Andre Guedes3655bba2013-10-30 19:01:40 -03006272 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6273 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006274 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006275 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006276
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006277 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6278 hdev);
6279
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006280 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006281 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006282 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006283
Andre Guedes3655bba2013-10-30 19:01:40 -03006284 cp = cmd->param;
6285
6286 if (bacmp(bdaddr, &cp->addr.bdaddr))
6287 return;
6288
6289 if (cp->addr.type != bdaddr_type)
6290 return;
6291
Johan Hedberg88c3df12012-02-09 14:27:38 +02006292 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006293 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006294
Marcel Holtmann78929242013-10-06 23:55:47 -07006295 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6296 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006297
Johan Hedberga664b5b2011-02-19 12:06:02 -03006298 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006299}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006300
Marcel Holtmann445608d2013-10-06 23:55:48 -07006301void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6302 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006303{
6304 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006305 struct pending_cmd *power_off;
6306
6307 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6308 if (power_off) {
6309 struct mgmt_mode *cp = power_off->param;
6310
6311 /* The connection is still in hci_conn_hash so test for 1
6312 * instead of 0 to know if this is the last one.
6313 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006314 if (!cp->val && hci_conn_count(hdev) == 1) {
6315 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006316 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006317 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006318 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006319
Johan Hedberg4c659c32011-11-07 23:13:39 +02006320 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006321 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006322 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006323
Marcel Holtmann445608d2013-10-06 23:55:48 -07006324 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006325}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006326
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006327void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006328{
6329 struct mgmt_ev_pin_code_request ev;
6330
Johan Hedbergd8457692012-02-17 14:24:57 +02006331 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006332 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006333 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006334
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006335 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006336}
6337
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006338void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6339 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006340{
6341 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006342 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006343
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006344 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006345 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006346 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006347
Johan Hedbergd8457692012-02-17 14:24:57 +02006348 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006349 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006350
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006351 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6352 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006353
Johan Hedberga664b5b2011-02-19 12:06:02 -03006354 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006355}
6356
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006357void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6358 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006359{
6360 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006361 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006362
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006363 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006364 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006365 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006366
Johan Hedbergd8457692012-02-17 14:24:57 +02006367 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006368 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006369
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006370 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6371 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006372
Johan Hedberga664b5b2011-02-19 12:06:02 -03006373 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006374}
Johan Hedberga5c29682011-02-19 12:05:57 -03006375
Johan Hedberg744cf192011-11-08 20:40:14 +02006376int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006377 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006378 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006379{
6380 struct mgmt_ev_user_confirm_request ev;
6381
Johan Hedberg744cf192011-11-08 20:40:14 +02006382 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006383
Johan Hedberg272d90d2012-02-09 15:26:12 +02006384 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006385 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006386 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006387 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006388
Johan Hedberg744cf192011-11-08 20:40:14 +02006389 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006390 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006391}
6392
Johan Hedberg272d90d2012-02-09 15:26:12 +02006393int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006394 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006395{
6396 struct mgmt_ev_user_passkey_request ev;
6397
6398 BT_DBG("%s", hdev->name);
6399
Johan Hedberg272d90d2012-02-09 15:26:12 +02006400 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006401 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006402
6403 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006404 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006405}
6406
Brian Gix0df4c182011-11-16 13:53:13 -08006407static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006408 u8 link_type, u8 addr_type, u8 status,
6409 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006410{
6411 struct pending_cmd *cmd;
6412 struct mgmt_rp_user_confirm_reply rp;
6413 int err;
6414
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006415 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006416 if (!cmd)
6417 return -ENOENT;
6418
Johan Hedberg272d90d2012-02-09 15:26:12 +02006419 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006420 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006421 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006422 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006423
Johan Hedberga664b5b2011-02-19 12:06:02 -03006424 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006425
6426 return err;
6427}
6428
Johan Hedberg744cf192011-11-08 20:40:14 +02006429int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006430 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006431{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006432 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006433 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006434}
6435
Johan Hedberg272d90d2012-02-09 15:26:12 +02006436int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006437 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006438{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006439 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006440 status,
6441 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006442}
Johan Hedberg2a611692011-02-19 12:06:00 -03006443
Brian Gix604086b2011-11-23 08:28:33 -08006444int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006445 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006446{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006447 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006448 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006449}
6450
Johan Hedberg272d90d2012-02-09 15:26:12 +02006451int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006452 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006453{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006454 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006455 status,
6456 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006457}
6458
Johan Hedberg92a25252012-09-06 18:39:26 +03006459int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6460 u8 link_type, u8 addr_type, u32 passkey,
6461 u8 entered)
6462{
6463 struct mgmt_ev_passkey_notify ev;
6464
6465 BT_DBG("%s", hdev->name);
6466
6467 bacpy(&ev.addr.bdaddr, bdaddr);
6468 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6469 ev.passkey = __cpu_to_le32(passkey);
6470 ev.entered = entered;
6471
6472 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6473}
6474
Marcel Holtmanne5460992013-10-15 14:26:23 -07006475void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6476 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006477{
6478 struct mgmt_ev_auth_failed ev;
6479
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006480 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006481 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006482 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006483
Marcel Holtmanne5460992013-10-15 14:26:23 -07006484 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006485}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006486
Marcel Holtmann464996a2013-10-15 14:26:24 -07006487void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006488{
6489 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006490 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006491
6492 if (status) {
6493 u8 mgmt_err = mgmt_status(status);
6494 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006495 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006496 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006497 }
6498
Marcel Holtmann464996a2013-10-15 14:26:24 -07006499 if (test_bit(HCI_AUTH, &hdev->flags))
6500 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6501 &hdev->dev_flags);
6502 else
6503 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6504 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006505
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006506 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006507 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006508
Johan Hedberg47990ea2012-02-22 11:58:37 +02006509 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006510 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006511
6512 if (match.sk)
6513 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006514}
6515
Johan Hedberg890ea892013-03-15 17:06:52 -05006516static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006517{
Johan Hedberg890ea892013-03-15 17:06:52 -05006518 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006519 struct hci_cp_write_eir cp;
6520
Johan Hedberg976eb202012-10-24 21:12:01 +03006521 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006522 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006523
Johan Hedbergc80da272012-02-22 15:38:48 +02006524 memset(hdev->eir, 0, sizeof(hdev->eir));
6525
Johan Hedbergcacaf522012-02-21 00:52:42 +02006526 memset(&cp, 0, sizeof(cp));
6527
Johan Hedberg890ea892013-03-15 17:06:52 -05006528 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006529}
6530
Marcel Holtmann3e248562013-10-15 14:26:25 -07006531void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006532{
6533 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006534 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006535 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006536
6537 if (status) {
6538 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006539
6540 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006541 &hdev->dev_flags)) {
6542 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006543 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006544 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006545
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006546 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6547 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006548 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006549 }
6550
6551 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006552 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006553 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006554 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6555 if (!changed)
6556 changed = test_and_clear_bit(HCI_HS_ENABLED,
6557 &hdev->dev_flags);
6558 else
6559 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006560 }
6561
6562 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6563
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006564 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006565 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006566
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006567 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006568 sock_put(match.sk);
6569
Johan Hedberg890ea892013-03-15 17:06:52 -05006570 hci_req_init(&req, hdev);
6571
Johan Hedberg37699722014-06-24 14:00:27 +03006572 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6573 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6574 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6575 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006576 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006577 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006578 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006579 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006580
6581 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006582}
6583
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006584void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6585{
6586 struct cmd_lookup match = { NULL, hdev };
6587 bool changed = false;
6588
6589 if (status) {
6590 u8 mgmt_err = mgmt_status(status);
6591
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006592 if (enable) {
6593 if (test_and_clear_bit(HCI_SC_ENABLED,
6594 &hdev->dev_flags))
6595 new_settings(hdev, NULL);
6596 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6597 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006598
6599 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6600 cmd_status_rsp, &mgmt_err);
6601 return;
6602 }
6603
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006604 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006605 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006606 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006607 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006608 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6609 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006610
6611 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6612 settings_rsp, &match);
6613
6614 if (changed)
6615 new_settings(hdev, match.sk);
6616
6617 if (match.sk)
6618 sock_put(match.sk);
6619}
6620
Johan Hedberg92da6092013-03-15 17:06:55 -05006621static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006622{
6623 struct cmd_lookup *match = data;
6624
Johan Hedberg90e70452012-02-23 23:09:40 +02006625 if (match->sk == NULL) {
6626 match->sk = cmd->sk;
6627 sock_hold(match->sk);
6628 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006629}
6630
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006631void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6632 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006633{
Johan Hedberg90e70452012-02-23 23:09:40 +02006634 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006635
Johan Hedberg92da6092013-03-15 17:06:55 -05006636 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6637 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6638 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006639
6640 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006641 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6642 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006643
6644 if (match.sk)
6645 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006646}
6647
Marcel Holtmann7667da32013-10-15 14:26:27 -07006648void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006649{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006650 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006651 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006652
Johan Hedberg13928972013-03-15 17:07:00 -05006653 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006654 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006655
6656 memset(&ev, 0, sizeof(ev));
6657 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006658 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006659
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006660 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006661 if (!cmd) {
6662 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006663
Johan Hedberg13928972013-03-15 17:07:00 -05006664 /* If this is a HCI command related to powering on the
6665 * HCI dev don't send any mgmt signals.
6666 */
6667 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006668 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006669 }
6670
Marcel Holtmann7667da32013-10-15 14:26:27 -07006671 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6672 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006673}
Szymon Jancc35938b2011-03-22 13:12:21 +01006674
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006675void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6676 u8 *randomizer192, u8 *hash256,
6677 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006678{
6679 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006680
Johan Hedberg744cf192011-11-08 20:40:14 +02006681 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006682
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006683 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006684 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006685 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006686
6687 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006688 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6689 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006690 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006691 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6692 hash256 && randomizer256) {
6693 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006694
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006695 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6696 memcpy(rp.randomizer192, randomizer192,
6697 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006698
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006699 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6700 memcpy(rp.randomizer256, randomizer256,
6701 sizeof(rp.randomizer256));
6702
6703 cmd_complete(cmd->sk, hdev->id,
6704 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6705 &rp, sizeof(rp));
6706 } else {
6707 struct mgmt_rp_read_local_oob_data rp;
6708
6709 memcpy(rp.hash, hash192, sizeof(rp.hash));
6710 memcpy(rp.randomizer, randomizer192,
6711 sizeof(rp.randomizer));
6712
6713 cmd_complete(cmd->sk, hdev->id,
6714 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6715 &rp, sizeof(rp));
6716 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006717 }
6718
6719 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006720}
Johan Hedberge17acd42011-03-30 23:57:16 +03006721
Marcel Holtmann901801b2013-10-06 23:55:51 -07006722void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006723 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6724 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006725{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006726 char buf[512];
6727 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006728 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006729
Johan Hedberg75ce2082014-07-02 22:42:01 +03006730 /* Don't send events for a non-kernel initiated discovery. With
6731 * LE one exception is if we have pend_le_reports > 0 in which
6732 * case we're doing passive scanning and want these events.
6733 */
6734 if (!hci_discovery_active(hdev)) {
6735 if (link_type == ACL_LINK)
6736 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006737 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006738 return;
6739 }
Andre Guedes12602d02013-04-30 15:29:40 -03006740
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006741 /* Make sure that the buffer is big enough. The 5 extra bytes
6742 * are for the potential CoD field.
6743 */
6744 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006745 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006746
Johan Hedberg1dc06092012-01-15 21:01:23 +02006747 memset(buf, 0, sizeof(buf));
6748
Johan Hedberg841c5642014-07-07 12:45:54 +03006749 bacpy(&ev->addr.bdaddr, bdaddr);
6750 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006751 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006752 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006753
Johan Hedberg1dc06092012-01-15 21:01:23 +02006754 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006755 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006756
Johan Hedberg1dc06092012-01-15 21:01:23 +02006757 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6758 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006759 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006760
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006761 if (scan_rsp_len > 0)
6762 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6763
6764 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6765 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006766
Marcel Holtmann901801b2013-10-06 23:55:51 -07006767 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006768}
Johan Hedberga88a9652011-03-30 13:18:12 +03006769
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006770void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6771 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006772{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006773 struct mgmt_ev_device_found *ev;
6774 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6775 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006776
Johan Hedbergb644ba32012-01-17 21:48:47 +02006777 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006778
Johan Hedbergb644ba32012-01-17 21:48:47 +02006779 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006780
Johan Hedbergb644ba32012-01-17 21:48:47 +02006781 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006782 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006783 ev->rssi = rssi;
6784
6785 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006786 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006787
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006788 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006789
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006790 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006791}
Johan Hedberg314b2382011-04-27 10:29:57 -04006792
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006793void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006794{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006795 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006796 struct pending_cmd *cmd;
6797
Andre Guedes343fb142011-11-22 17:14:19 -03006798 BT_DBG("%s discovering %u", hdev->name, discovering);
6799
Johan Hedberg164a6e72011-11-01 17:06:44 +02006800 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006801 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006802 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006803 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006804
6805 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006806 u8 type = hdev->discovery.type;
6807
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006808 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6809 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006810 mgmt_pending_remove(cmd);
6811 }
6812
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006813 memset(&ev, 0, sizeof(ev));
6814 ev.type = hdev->discovery.type;
6815 ev.discovering = discovering;
6816
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006817 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006818}
Antti Julku5e762442011-08-25 16:48:02 +03006819
Marcel Holtmann5976e602013-10-06 04:08:14 -07006820static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6821{
6822 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006823}
6824
6825void mgmt_reenable_advertising(struct hci_dev *hdev)
6826{
6827 struct hci_request req;
6828
Marcel Holtmann5976e602013-10-06 04:08:14 -07006829 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6830 return;
6831
6832 hci_req_init(&req, hdev);
6833 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006834 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006835}