blob: 49581e99685c74d444b609fa5fdc64e6b0747188 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200132#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
133 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
134
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135struct pending_cmd {
136 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200137 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100139 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200580 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200582
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200583 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
584 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585 settings |= MGMT_SETTING_CONFIGURATION;
586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587 return settings;
588}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200589
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200590static u32 get_current_settings(struct hci_dev *hdev)
591{
592 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200593
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200594 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100595 settings |= MGMT_SETTING_POWERED;
596
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200597 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200598 settings |= MGMT_SETTING_CONNECTABLE;
599
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500600 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
601 settings |= MGMT_SETTING_FAST_CONNECTABLE;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_DISCOVERABLE;
605
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200606 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_PAIRABLE;
608
Johan Hedberg56f87902013-10-02 13:43:13 +0300609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_BREDR;
611
Johan Hedberg06199cf2012-02-22 16:37:11 +0200612 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200614
Johan Hedberg47990ea2012-02-22 11:58:37 +0200615 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200617
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200618 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200620
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200621 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
622 settings |= MGMT_SETTING_HS;
623
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200624 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300625 settings |= MGMT_SETTING_ADVERTISING;
626
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_SECURE_CONN;
629
Johan Hedberg0663b292014-06-24 13:15:50 +0300630 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800631 settings |= MGMT_SETTING_DEBUG_KEYS;
632
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200633 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
634 settings |= MGMT_SETTING_PRIVACY;
635
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200636 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200637}
638
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300639#define PNP_INFO_SVCLASS_ID 0x1200
640
Johan Hedberg213202e2013-01-27 00:31:33 +0200641static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
642{
643 u8 *ptr = data, *uuids_start = NULL;
644 struct bt_uuid *uuid;
645
646 if (len < 4)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 u16 uuid16;
651
652 if (uuid->size != 16)
653 continue;
654
655 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
656 if (uuid16 < 0x1100)
657 continue;
658
659 if (uuid16 == PNP_INFO_SVCLASS_ID)
660 continue;
661
662 if (!uuids_start) {
663 uuids_start = ptr;
664 uuids_start[0] = 1;
665 uuids_start[1] = EIR_UUID16_ALL;
666 ptr += 2;
667 }
668
669 /* Stop if not enough space to put next UUID */
670 if ((ptr - data) + sizeof(u16) > len) {
671 uuids_start[1] = EIR_UUID16_SOME;
672 break;
673 }
674
675 *ptr++ = (uuid16 & 0x00ff);
676 *ptr++ = (uuid16 & 0xff00) >> 8;
677 uuids_start[0] += sizeof(uuid16);
678 }
679
680 return ptr;
681}
682
Johan Hedbergcdf19632013-01-27 00:31:34 +0200683static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
684{
685 u8 *ptr = data, *uuids_start = NULL;
686 struct bt_uuid *uuid;
687
688 if (len < 6)
689 return ptr;
690
691 list_for_each_entry(uuid, &hdev->uuids, list) {
692 if (uuid->size != 32)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID32_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u32) > len) {
704 uuids_start[1] = EIR_UUID32_SOME;
705 break;
706 }
707
708 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
709 ptr += sizeof(u32);
710 uuids_start[0] += sizeof(u32);
711 }
712
713 return ptr;
714}
715
Johan Hedbergc00d5752013-01-27 00:31:35 +0200716static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 18)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 128)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID128_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + 16 > len) {
737 uuids_start[1] = EIR_UUID128_SOME;
738 break;
739 }
740
741 memcpy(ptr, uuid->uuid, 16);
742 ptr += 16;
743 uuids_start[0] += 16;
744 }
745
746 return ptr;
747}
748
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300749static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
750{
751 struct pending_cmd *cmd;
752
753 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
754 if (cmd->opcode == opcode)
755 return cmd;
756 }
757
758 return NULL;
759}
760
Johan Hedberg95868422014-06-28 17:54:07 +0300761static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
762 struct hci_dev *hdev,
763 const void *data)
764{
765 struct pending_cmd *cmd;
766
767 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
768 if (cmd->user_data != data)
769 continue;
770 if (cmd->opcode == opcode)
771 return cmd;
772 }
773
774 return NULL;
775}
776
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700777static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
778{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700779 u8 ad_len = 0;
780 size_t name_len;
781
782 name_len = strlen(hdev->dev_name);
783 if (name_len > 0) {
784 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
785
786 if (name_len > max_len) {
787 name_len = max_len;
788 ptr[1] = EIR_NAME_SHORT;
789 } else
790 ptr[1] = EIR_NAME_COMPLETE;
791
792 ptr[0] = name_len + 1;
793
794 memcpy(ptr + 2, hdev->dev_name, name_len);
795
796 ad_len += (name_len + 2);
797 ptr += (name_len + 2);
798 }
799
800 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700801}
802
803static void update_scan_rsp_data(struct hci_request *req)
804{
805 struct hci_dev *hdev = req->hdev;
806 struct hci_cp_le_set_scan_rsp_data cp;
807 u8 len;
808
Johan Hedberg7751ef12013-10-19 23:38:15 +0300809 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700810 return;
811
812 memset(&cp, 0, sizeof(cp));
813
814 len = create_scan_rsp_data(hdev, cp.data);
815
Johan Hedbergeb438b52013-10-16 15:31:07 +0300816 if (hdev->scan_rsp_data_len == len &&
817 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700818 return;
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
821 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822
823 cp.length = len;
824
825 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
826}
827
Johan Hedberg9a43e252013-10-20 19:00:07 +0300828static u8 get_adv_discov_flags(struct hci_dev *hdev)
829{
830 struct pending_cmd *cmd;
831
832 /* If there's a pending mgmt command the flags will not yet have
833 * their final values, so check for this first.
834 */
835 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
836 if (cmd) {
837 struct mgmt_mode *cp = cmd->param;
838 if (cp->val == 0x01)
839 return LE_AD_GENERAL;
840 else if (cp->val == 0x02)
841 return LE_AD_LIMITED;
842 } else {
843 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_LIMITED;
845 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_GENERAL;
847 }
848
849 return 0;
850}
851
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700852static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853{
854 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberg9a43e252013-10-20 19:00:07 +0300856 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberge8340042014-01-30 11:16:50 -0800858 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
861 if (flags) {
862 BT_DBG("adv flags 0x%02x", flags);
863
864 ptr[0] = 2;
865 ptr[1] = EIR_FLAGS;
866 ptr[2] = flags;
867
868 ad_len += 3;
869 ptr += 3;
870 }
871
872 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
873 ptr[0] = 2;
874 ptr[1] = EIR_TX_POWER;
875 ptr[2] = (u8) hdev->adv_tx_power;
876
877 ad_len += 3;
878 ptr += 3;
879 }
880
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700881 return ad_len;
882}
883
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700884static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885{
886 struct hci_dev *hdev = req->hdev;
887 struct hci_cp_le_set_adv_data cp;
888 u8 len;
889
Johan Hedberg10994ce2013-10-19 23:38:16 +0300890 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891 return;
892
893 memset(&cp, 0, sizeof(cp));
894
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700895 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896
897 if (hdev->adv_data_len == len &&
898 memcmp(cp.data, hdev->adv_data, len) == 0)
899 return;
900
901 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
902 hdev->adv_data_len = len;
903
904 cp.length = len;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
907}
908
Johan 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 Hedberg23a48092014-07-08 16:05:06 +03001254static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001255{
1256 struct hci_dev *hdev = req->hdev;
1257 struct hci_cp_remote_name_req_cancel cp;
1258 struct inquiry_entry *e;
1259
1260 switch (hdev->discovery.state) {
1261 case DISCOVERY_FINDING:
1262 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1263 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1264 } else {
1265 cancel_delayed_work(&hdev->le_scan_disable);
1266 hci_req_add_le_scan_disable(req);
1267 }
1268
Johan Hedberg23a48092014-07-08 16:05:06 +03001269 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001270
1271 case DISCOVERY_RESOLVING:
1272 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1273 NAME_PENDING);
1274 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001275 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001276
1277 bacpy(&cp.bdaddr, &e->data.bdaddr);
1278 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1279 &cp);
1280
Johan Hedberg23a48092014-07-08 16:05:06 +03001281 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001282
1283 default:
1284 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001287 return true;
1288 }
1289
Johan Hedberg21a60d32014-06-10 14:05:58 +03001290 break;
1291 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001292
1293 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001294}
1295
Johan Hedberg8b064a32014-02-24 14:52:22 +02001296static int clean_up_hci_state(struct hci_dev *hdev)
1297{
1298 struct hci_request req;
1299 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001300 bool discov_stopped;
1301 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001302
1303 hci_req_init(&req, hdev);
1304
1305 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1306 test_bit(HCI_PSCAN, &hdev->flags)) {
1307 u8 scan = 0x00;
1308 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1309 }
1310
Johan Hedberg73e082f2014-07-08 15:07:51 +03001311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312 disable_advertising(&req);
1313
Johan Hedberg23a48092014-07-08 16:05:06 +03001314 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001315
1316 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1317 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001318 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001319
Johan Hedbergc9910d02014-02-27 14:35:12 +02001320 switch (conn->state) {
1321 case BT_CONNECTED:
1322 case BT_CONFIG:
1323 dc.handle = cpu_to_le16(conn->handle);
1324 dc.reason = 0x15; /* Terminated due to Power Off */
1325 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1326 break;
1327 case BT_CONNECT:
1328 if (conn->type == LE_LINK)
1329 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1330 0, NULL);
1331 else if (conn->type == ACL_LINK)
1332 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1333 6, &conn->dst);
1334 break;
1335 case BT_CONNECT2:
1336 bacpy(&rej.bdaddr, &conn->dst);
1337 rej.reason = 0x15; /* Terminated due to Power Off */
1338 if (conn->type == ACL_LINK)
1339 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1340 sizeof(rej), &rej);
1341 else if (conn->type == SCO_LINK)
1342 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1343 sizeof(rej), &rej);
1344 break;
1345 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001346 }
1347
Johan Hedberg23a48092014-07-08 16:05:06 +03001348 err = hci_req_run(&req, clean_up_hci_complete);
1349 if (!err && discov_stopped)
1350 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1351
1352 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001353}
1354
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001355static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001356 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001357{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001358 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001359 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001360 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001362 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001363
Johan Hedberga7e80f22013-01-09 16:05:19 +02001364 if (cp->val != 0x00 && cp->val != 0x01)
1365 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1366 MGMT_STATUS_INVALID_PARAMS);
1367
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001368 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001369
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001370 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1371 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1372 MGMT_STATUS_BUSY);
1373 goto failed;
1374 }
1375
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001376 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1377 cancel_delayed_work(&hdev->power_off);
1378
1379 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001380 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1381 data, len);
1382 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001383 goto failed;
1384 }
1385 }
1386
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001387 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001388 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001389 goto failed;
1390 }
1391
Johan Hedberg03811012010-12-08 00:21:06 +02001392 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1393 if (!cmd) {
1394 err = -ENOMEM;
1395 goto failed;
1396 }
1397
Johan Hedberg8b064a32014-02-24 14:52:22 +02001398 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001399 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001400 err = 0;
1401 } else {
1402 /* Disconnect connections, stop scans, etc */
1403 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001404 if (!err)
1405 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1406 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 /* ENODATA means there were no HCI commands queued */
1409 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001410 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001411 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1412 err = 0;
1413 }
1414 }
Johan Hedberg03811012010-12-08 00:21:06 +02001415
1416failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001417 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001418 return err;
1419}
1420
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001421static int new_settings(struct hci_dev *hdev, struct sock *skip)
1422{
1423 __le32 ev;
1424
1425 ev = cpu_to_le32(get_current_settings(hdev));
1426
1427 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1428}
1429
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001430struct cmd_lookup {
1431 struct sock *sk;
1432 struct hci_dev *hdev;
1433 u8 mgmt_status;
1434};
1435
1436static void settings_rsp(struct pending_cmd *cmd, void *data)
1437{
1438 struct cmd_lookup *match = data;
1439
1440 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1441
1442 list_del(&cmd->list);
1443
1444 if (match->sk == NULL) {
1445 match->sk = cmd->sk;
1446 sock_hold(match->sk);
1447 }
1448
1449 mgmt_pending_free(cmd);
1450}
1451
1452static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1453{
1454 u8 *status = data;
1455
1456 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1457 mgmt_pending_remove(cmd);
1458}
1459
Johan Hedberge6fe7982013-10-02 15:45:22 +03001460static u8 mgmt_bredr_support(struct hci_dev *hdev)
1461{
1462 if (!lmp_bredr_capable(hdev))
1463 return MGMT_STATUS_NOT_SUPPORTED;
1464 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1465 return MGMT_STATUS_REJECTED;
1466 else
1467 return MGMT_STATUS_SUCCESS;
1468}
1469
1470static u8 mgmt_le_support(struct hci_dev *hdev)
1471{
1472 if (!lmp_le_capable(hdev))
1473 return MGMT_STATUS_NOT_SUPPORTED;
1474 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1475 return MGMT_STATUS_REJECTED;
1476 else
1477 return MGMT_STATUS_SUCCESS;
1478}
1479
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001480static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1481{
1482 struct pending_cmd *cmd;
1483 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001484 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001485 bool changed;
1486
1487 BT_DBG("status 0x%02x", status);
1488
1489 hci_dev_lock(hdev);
1490
1491 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1492 if (!cmd)
1493 goto unlock;
1494
1495 if (status) {
1496 u8 mgmt_err = mgmt_status(status);
1497 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001498 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001499 goto remove_cmd;
1500 }
1501
1502 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001503 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1505 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001506
1507 if (hdev->discov_timeout > 0) {
1508 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1509 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1510 to);
1511 }
1512 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001513 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1514 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001515 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001516
1517 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1518
1519 if (changed)
1520 new_settings(hdev, cmd->sk);
1521
Marcel Holtmann970ba522013-10-15 06:33:57 -07001522 /* When the discoverable mode gets changed, make sure
1523 * that class of device has the limited discoverable
1524 * bit correctly set.
1525 */
1526 hci_req_init(&req, hdev);
1527 update_class(&req);
1528 hci_req_run(&req, NULL);
1529
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001530remove_cmd:
1531 mgmt_pending_remove(cmd);
1532
1533unlock:
1534 hci_dev_unlock(hdev);
1535}
1536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001537static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001538 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001539{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001540 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001541 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001542 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001543 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001544 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001545 int err;
1546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001547 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001548
Johan Hedberg9a43e252013-10-20 19:00:07 +03001549 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1550 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001551 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001552 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001553
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001554 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001555 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1556 MGMT_STATUS_INVALID_PARAMS);
1557
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001558 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001559
1560 /* Disabling discoverable requires that no timeout is set,
1561 * and enabling limited discoverable requires a timeout.
1562 */
1563 if ((cp->val == 0x00 && timeout > 0) ||
1564 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001565 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001566 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001567
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001568 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001569
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001570 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001571 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001572 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001573 goto failed;
1574 }
1575
1576 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001577 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001578 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001579 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001580 goto failed;
1581 }
1582
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001583 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001584 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001585 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 goto failed;
1587 }
1588
1589 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001590 bool changed = false;
1591
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001592 /* Setting limited discoverable when powered off is
1593 * not a valid operation since it requires a timeout
1594 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1595 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001596 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1597 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1598 changed = true;
1599 }
1600
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001601 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001602 if (err < 0)
1603 goto failed;
1604
1605 if (changed)
1606 err = new_settings(hdev, sk);
1607
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001608 goto failed;
1609 }
1610
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001611 /* If the current mode is the same, then just update the timeout
1612 * value with the new value. And if only the timeout gets updated,
1613 * then no need for any HCI transactions.
1614 */
1615 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1616 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1617 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001618 cancel_delayed_work(&hdev->discov_off);
1619 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001620
Marcel Holtmann36261542013-10-15 08:28:51 -07001621 if (cp->val && hdev->discov_timeout > 0) {
1622 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001623 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001624 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001625 }
1626
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001627 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001628 goto failed;
1629 }
1630
1631 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1632 if (!cmd) {
1633 err = -ENOMEM;
1634 goto failed;
1635 }
1636
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001637 /* Cancel any potential discoverable timeout that might be
1638 * still active and store new timeout value. The arming of
1639 * the timeout happens in the complete handler.
1640 */
1641 cancel_delayed_work(&hdev->discov_off);
1642 hdev->discov_timeout = timeout;
1643
Johan Hedbergb456f872013-10-19 23:38:22 +03001644 /* Limited discoverable mode */
1645 if (cp->val == 0x02)
1646 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1647 else
1648 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1649
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001650 hci_req_init(&req, hdev);
1651
Johan Hedberg9a43e252013-10-20 19:00:07 +03001652 /* The procedure for LE-only controllers is much simpler - just
1653 * update the advertising data.
1654 */
1655 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1656 goto update_ad;
1657
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001658 scan = SCAN_PAGE;
1659
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001660 if (cp->val) {
1661 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001662
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001663 if (cp->val == 0x02) {
1664 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001665 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001666 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1667 hci_cp.iac_lap[1] = 0x8b;
1668 hci_cp.iac_lap[2] = 0x9e;
1669 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1670 hci_cp.iac_lap[4] = 0x8b;
1671 hci_cp.iac_lap[5] = 0x9e;
1672 } else {
1673 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001674 hci_cp.num_iac = 1;
1675 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1676 hci_cp.iac_lap[1] = 0x8b;
1677 hci_cp.iac_lap[2] = 0x9e;
1678 }
1679
1680 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1681 (hci_cp.num_iac * 3) + 1, &hci_cp);
1682
1683 scan |= SCAN_INQUIRY;
1684 } else {
1685 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1686 }
1687
1688 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001689
Johan Hedberg9a43e252013-10-20 19:00:07 +03001690update_ad:
1691 update_adv_data(&req);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001694 if (err < 0)
1695 mgmt_pending_remove(cmd);
1696
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001697failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001698 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001699 return err;
1700}
1701
Johan Hedberg406d7802013-03-15 17:07:09 -05001702static void write_fast_connectable(struct hci_request *req, bool enable)
1703{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001704 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001705 struct hci_cp_write_page_scan_activity acp;
1706 u8 type;
1707
Johan Hedberg547003b2013-10-21 16:51:53 +03001708 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1709 return;
1710
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001711 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1712 return;
1713
Johan Hedberg406d7802013-03-15 17:07:09 -05001714 if (enable) {
1715 type = PAGE_SCAN_TYPE_INTERLACED;
1716
1717 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001718 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001719 } else {
1720 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1721
1722 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001723 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001724 }
1725
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001726 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001727
Johan Hedbergbd98b992013-03-15 17:07:13 -05001728 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1729 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1730 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1731 sizeof(acp), &acp);
1732
1733 if (hdev->page_scan_type != type)
1734 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001735}
1736
Johan Hedberg2b76f452013-03-15 17:07:04 -05001737static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1738{
1739 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001740 struct mgmt_mode *cp;
1741 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001742
1743 BT_DBG("status 0x%02x", status);
1744
1745 hci_dev_lock(hdev);
1746
1747 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1748 if (!cmd)
1749 goto unlock;
1750
Johan Hedberg37438c12013-10-14 16:20:05 +03001751 if (status) {
1752 u8 mgmt_err = mgmt_status(status);
1753 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1754 goto remove_cmd;
1755 }
1756
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001757 cp = cmd->param;
1758 if (cp->val)
1759 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1760 else
1761 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1762
Johan Hedberg2b76f452013-03-15 17:07:04 -05001763 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1764
Johan Hedberg2b7be332014-07-07 14:40:22 +03001765 if (changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001766 new_settings(hdev, cmd->sk);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001767 hci_update_background_scan(hdev);
1768 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001769
Johan Hedberg37438c12013-10-14 16:20:05 +03001770remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001771 mgmt_pending_remove(cmd);
1772
1773unlock:
1774 hci_dev_unlock(hdev);
1775}
1776
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001777static int set_connectable_update_settings(struct hci_dev *hdev,
1778 struct sock *sk, u8 val)
1779{
1780 bool changed = false;
1781 int err;
1782
1783 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1784 changed = true;
1785
1786 if (val) {
1787 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1788 } else {
1789 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1790 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1791 }
1792
1793 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1794 if (err < 0)
1795 return err;
1796
Johan Hedberg562064e2014-07-08 16:35:34 +03001797 if (changed) {
1798 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001799 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001800 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001801
1802 return 0;
1803}
1804
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001805static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001806 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001807{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001808 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001809 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001810 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001811 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001812 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001813
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001814 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001815
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001816 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1817 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001818 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001819 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001820
Johan Hedberga7e80f22013-01-09 16:05:19 +02001821 if (cp->val != 0x00 && cp->val != 0x01)
1822 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1823 MGMT_STATUS_INVALID_PARAMS);
1824
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001825 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001826
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001827 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001828 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001829 goto failed;
1830 }
1831
1832 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001833 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001834 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001835 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001836 goto failed;
1837 }
1838
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001839 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1840 if (!cmd) {
1841 err = -ENOMEM;
1842 goto failed;
1843 }
1844
Johan Hedberg2b76f452013-03-15 17:07:04 -05001845 hci_req_init(&req, hdev);
1846
Johan Hedberg9a43e252013-10-20 19:00:07 +03001847 /* If BR/EDR is not enabled and we disable advertising as a
1848 * by-product of disabling connectable, we need to update the
1849 * advertising flags.
1850 */
1851 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1852 if (!cp->val) {
1853 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1854 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1855 }
1856 update_adv_data(&req);
1857 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001858 if (cp->val) {
1859 scan = SCAN_PAGE;
1860 } else {
1861 scan = 0;
1862
1863 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001864 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001865 cancel_delayed_work(&hdev->discov_off);
1866 }
1867
1868 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1869 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001870
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001871 /* If we're going from non-connectable to connectable or
1872 * vice-versa when fast connectable is enabled ensure that fast
1873 * connectable gets disabled. write_fast_connectable won't do
1874 * anything if the page scan parameters are already what they
1875 * should be.
1876 */
1877 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001878 write_fast_connectable(&req, false);
1879
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001880 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001881 !test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001882 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001883
Johan Hedberg2b76f452013-03-15 17:07:04 -05001884 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001885 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001886 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001887 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001888 err = set_connectable_update_settings(hdev, sk,
1889 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001890 goto failed;
1891 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892
1893failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001894 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001895 return err;
1896}
1897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001898static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001899 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001900{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001901 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001902 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001903 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001904
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001905 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001906
Johan Hedberga7e80f22013-01-09 16:05:19 +02001907 if (cp->val != 0x00 && cp->val != 0x01)
1908 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1909 MGMT_STATUS_INVALID_PARAMS);
1910
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001911 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001912
1913 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001914 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001915 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001916 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001917
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001918 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001919 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001920 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001921
Marcel Holtmann55594352013-10-06 16:11:57 -07001922 if (changed)
1923 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001924
Marcel Holtmann55594352013-10-06 16:11:57 -07001925unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001926 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001927 return err;
1928}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001929
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001930static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1931 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001932{
1933 struct mgmt_mode *cp = data;
1934 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001935 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001936 int err;
1937
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001938 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001939
Johan Hedberge6fe7982013-10-02 15:45:22 +03001940 status = mgmt_bredr_support(hdev);
1941 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001942 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001943 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001944
Johan Hedberga7e80f22013-01-09 16:05:19 +02001945 if (cp->val != 0x00 && cp->val != 0x01)
1946 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1947 MGMT_STATUS_INVALID_PARAMS);
1948
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001949 hci_dev_lock(hdev);
1950
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001951 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001952 bool changed = false;
1953
1954 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001955 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001956 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1957 changed = true;
1958 }
1959
1960 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1961 if (err < 0)
1962 goto failed;
1963
1964 if (changed)
1965 err = new_settings(hdev, sk);
1966
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001967 goto failed;
1968 }
1969
1970 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001971 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001972 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001973 goto failed;
1974 }
1975
1976 val = !!cp->val;
1977
1978 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1979 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1980 goto failed;
1981 }
1982
1983 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1984 if (!cmd) {
1985 err = -ENOMEM;
1986 goto failed;
1987 }
1988
1989 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1990 if (err < 0) {
1991 mgmt_pending_remove(cmd);
1992 goto failed;
1993 }
1994
1995failed:
1996 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001997 return err;
1998}
1999
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002000static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002001{
2002 struct mgmt_mode *cp = data;
2003 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002004 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002005 int err;
2006
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002007 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002008
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002009 status = mgmt_bredr_support(hdev);
2010 if (status)
2011 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2012
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002013 if (!lmp_ssp_capable(hdev))
2014 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2015 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002016
Johan Hedberga7e80f22013-01-09 16:05:19 +02002017 if (cp->val != 0x00 && cp->val != 0x01)
2018 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2019 MGMT_STATUS_INVALID_PARAMS);
2020
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002021 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002022
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002023 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002024 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002025
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002026 if (cp->val) {
2027 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2028 &hdev->dev_flags);
2029 } else {
2030 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2031 &hdev->dev_flags);
2032 if (!changed)
2033 changed = test_and_clear_bit(HCI_HS_ENABLED,
2034 &hdev->dev_flags);
2035 else
2036 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002037 }
2038
2039 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2040 if (err < 0)
2041 goto failed;
2042
2043 if (changed)
2044 err = new_settings(hdev, sk);
2045
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002046 goto failed;
2047 }
2048
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002049 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2050 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002051 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2052 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002053 goto failed;
2054 }
2055
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002056 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002057 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2058 goto failed;
2059 }
2060
2061 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2062 if (!cmd) {
2063 err = -ENOMEM;
2064 goto failed;
2065 }
2066
Johan Hedberg37699722014-06-24 14:00:27 +03002067 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2068 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2069 sizeof(cp->val), &cp->val);
2070
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002071 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002072 if (err < 0) {
2073 mgmt_pending_remove(cmd);
2074 goto failed;
2075 }
2076
2077failed:
2078 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002079 return err;
2080}
2081
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002082static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002083{
2084 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002085 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002086 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002087 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002088
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002089 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002090
Johan Hedberge6fe7982013-10-02 15:45:22 +03002091 status = mgmt_bredr_support(hdev);
2092 if (status)
2093 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002094
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002095 if (!lmp_ssp_capable(hdev))
2096 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2097 MGMT_STATUS_NOT_SUPPORTED);
2098
2099 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2100 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2101 MGMT_STATUS_REJECTED);
2102
Johan Hedberga7e80f22013-01-09 16:05:19 +02002103 if (cp->val != 0x00 && cp->val != 0x01)
2104 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2105 MGMT_STATUS_INVALID_PARAMS);
2106
Marcel Holtmannee392692013-10-01 22:59:23 -07002107 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002108
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002109 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002110 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002111 } else {
2112 if (hdev_is_powered(hdev)) {
2113 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2114 MGMT_STATUS_REJECTED);
2115 goto unlock;
2116 }
2117
Marcel Holtmannee392692013-10-01 22:59:23 -07002118 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002119 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002120
2121 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2122 if (err < 0)
2123 goto unlock;
2124
2125 if (changed)
2126 err = new_settings(hdev, sk);
2127
2128unlock:
2129 hci_dev_unlock(hdev);
2130 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002131}
2132
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002133static void le_enable_complete(struct hci_dev *hdev, u8 status)
2134{
2135 struct cmd_lookup match = { NULL, hdev };
2136
2137 if (status) {
2138 u8 mgmt_err = mgmt_status(status);
2139
2140 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2141 &mgmt_err);
2142 return;
2143 }
2144
2145 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2146
2147 new_settings(hdev, match.sk);
2148
2149 if (match.sk)
2150 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002151
2152 /* Make sure the controller has a good default for
2153 * advertising data. Restrict the update to when LE
2154 * has actually been enabled. During power on, the
2155 * update in powered_update_hci will take care of it.
2156 */
2157 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2158 struct hci_request req;
2159
2160 hci_dev_lock(hdev);
2161
2162 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002163 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002164 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002165 hci_req_run(&req, NULL);
2166
Johan Hedberga70f4b52014-07-07 15:19:50 +03002167 hci_update_background_scan(hdev);
2168
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002169 hci_dev_unlock(hdev);
2170 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002171}
2172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002173static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002174{
2175 struct mgmt_mode *cp = data;
2176 struct hci_cp_write_le_host_supported hci_cp;
2177 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002178 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002179 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002180 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002181
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002182 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002183
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002184 if (!lmp_le_capable(hdev))
2185 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2186 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002187
Johan Hedberga7e80f22013-01-09 16:05:19 +02002188 if (cp->val != 0x00 && cp->val != 0x01)
2189 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2190 MGMT_STATUS_INVALID_PARAMS);
2191
Johan Hedbergc73eee92013-04-19 18:35:21 +03002192 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002193 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002194 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2195 MGMT_STATUS_REJECTED);
2196
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002197 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002198
2199 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002200 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002201
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002202 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002203 bool changed = false;
2204
2205 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2206 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2207 changed = true;
2208 }
2209
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002210 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2211 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002212 changed = true;
2213 }
2214
Johan Hedberg06199cf2012-02-22 16:37:11 +02002215 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2216 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002217 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002218
2219 if (changed)
2220 err = new_settings(hdev, sk);
2221
Johan Hedberg1de028c2012-02-29 19:55:35 -08002222 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002223 }
2224
Johan Hedberg4375f102013-09-25 13:26:10 +03002225 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2226 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002227 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002228 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002229 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002230 }
2231
2232 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2233 if (!cmd) {
2234 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002235 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002236 }
2237
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002238 hci_req_init(&req, hdev);
2239
Johan Hedberg06199cf2012-02-22 16:37:11 +02002240 memset(&hci_cp, 0, sizeof(hci_cp));
2241
2242 if (val) {
2243 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002244 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002245 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002246 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002247 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248 }
2249
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002250 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2251 &hci_cp);
2252
2253 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302254 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002255 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002256
Johan Hedberg1de028c2012-02-29 19:55:35 -08002257unlock:
2258 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002259 return err;
2260}
2261
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002262/* This is a helper function to test for pending mgmt commands that can
2263 * cause CoD or EIR HCI commands. We can only allow one such pending
2264 * mgmt command at a time since otherwise we cannot easily track what
2265 * the current values are, will be, and based on that calculate if a new
2266 * HCI command needs to be sent and if yes with what value.
2267 */
2268static bool pending_eir_or_class(struct hci_dev *hdev)
2269{
2270 struct pending_cmd *cmd;
2271
2272 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2273 switch (cmd->opcode) {
2274 case MGMT_OP_ADD_UUID:
2275 case MGMT_OP_REMOVE_UUID:
2276 case MGMT_OP_SET_DEV_CLASS:
2277 case MGMT_OP_SET_POWERED:
2278 return true;
2279 }
2280 }
2281
2282 return false;
2283}
2284
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002285static const u8 bluetooth_base_uuid[] = {
2286 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2287 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2288};
2289
2290static u8 get_uuid_size(const u8 *uuid)
2291{
2292 u32 val;
2293
2294 if (memcmp(uuid, bluetooth_base_uuid, 12))
2295 return 128;
2296
2297 val = get_unaligned_le32(&uuid[12]);
2298 if (val > 0xffff)
2299 return 32;
2300
2301 return 16;
2302}
2303
Johan Hedberg92da6092013-03-15 17:06:55 -05002304static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2305{
2306 struct pending_cmd *cmd;
2307
2308 hci_dev_lock(hdev);
2309
2310 cmd = mgmt_pending_find(mgmt_op, hdev);
2311 if (!cmd)
2312 goto unlock;
2313
2314 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2315 hdev->dev_class, 3);
2316
2317 mgmt_pending_remove(cmd);
2318
2319unlock:
2320 hci_dev_unlock(hdev);
2321}
2322
2323static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2324{
2325 BT_DBG("status 0x%02x", status);
2326
2327 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2328}
2329
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002330static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002331{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002332 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002333 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002334 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002335 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002336 int err;
2337
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002338 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002339
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002340 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002341
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002342 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002343 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002344 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002345 goto failed;
2346 }
2347
Andre Guedes92c4c202012-06-07 19:05:44 -03002348 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002349 if (!uuid) {
2350 err = -ENOMEM;
2351 goto failed;
2352 }
2353
2354 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002355 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002356 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002357
Johan Hedbergde66aa62013-01-27 00:31:27 +02002358 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002359
Johan Hedberg890ea892013-03-15 17:06:52 -05002360 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002361
Johan Hedberg890ea892013-03-15 17:06:52 -05002362 update_class(&req);
2363 update_eir(&req);
2364
Johan Hedberg92da6092013-03-15 17:06:55 -05002365 err = hci_req_run(&req, add_uuid_complete);
2366 if (err < 0) {
2367 if (err != -ENODATA)
2368 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002369
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002370 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002371 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002372 goto failed;
2373 }
2374
2375 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002376 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002377 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002378 goto failed;
2379 }
2380
2381 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002382
2383failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002384 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002385 return err;
2386}
2387
Johan Hedberg24b78d02012-02-23 23:24:30 +02002388static bool enable_service_cache(struct hci_dev *hdev)
2389{
2390 if (!hdev_is_powered(hdev))
2391 return false;
2392
2393 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002394 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2395 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002396 return true;
2397 }
2398
2399 return false;
2400}
2401
Johan Hedberg92da6092013-03-15 17:06:55 -05002402static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2403{
2404 BT_DBG("status 0x%02x", status);
2405
2406 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2407}
2408
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002409static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002410 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002411{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002412 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002413 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002414 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002415 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 -05002416 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002417 int err, found;
2418
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002419 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002420
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002421 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002423 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002424 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002425 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002426 goto unlock;
2427 }
2428
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002429 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002430 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002431
Johan Hedberg24b78d02012-02-23 23:24:30 +02002432 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002433 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002434 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002435 goto unlock;
2436 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002437
Johan Hedberg9246a862012-02-23 21:33:16 +02002438 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002439 }
2440
2441 found = 0;
2442
Johan Hedberg056341c2013-01-27 00:31:30 +02002443 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002444 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2445 continue;
2446
2447 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002448 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002449 found++;
2450 }
2451
2452 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002453 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002454 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002455 goto unlock;
2456 }
2457
Johan Hedberg9246a862012-02-23 21:33:16 +02002458update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002459 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002460
Johan Hedberg890ea892013-03-15 17:06:52 -05002461 update_class(&req);
2462 update_eir(&req);
2463
Johan Hedberg92da6092013-03-15 17:06:55 -05002464 err = hci_req_run(&req, remove_uuid_complete);
2465 if (err < 0) {
2466 if (err != -ENODATA)
2467 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002468
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002469 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002470 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002471 goto unlock;
2472 }
2473
2474 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002475 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002476 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002477 goto unlock;
2478 }
2479
2480 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481
2482unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002483 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002484 return err;
2485}
2486
Johan Hedberg92da6092013-03-15 17:06:55 -05002487static void set_class_complete(struct hci_dev *hdev, u8 status)
2488{
2489 BT_DBG("status 0x%02x", status);
2490
2491 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2492}
2493
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002494static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002495 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002496{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002497 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002498 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002499 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002500 int err;
2501
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002502 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002503
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002504 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002505 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2506 MGMT_STATUS_NOT_SUPPORTED);
2507
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002508 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002509
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002510 if (pending_eir_or_class(hdev)) {
2511 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2512 MGMT_STATUS_BUSY);
2513 goto unlock;
2514 }
2515
2516 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2517 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2518 MGMT_STATUS_INVALID_PARAMS);
2519 goto unlock;
2520 }
2521
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002522 hdev->major_class = cp->major;
2523 hdev->minor_class = cp->minor;
2524
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002525 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002526 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002527 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002528 goto unlock;
2529 }
2530
Johan Hedberg890ea892013-03-15 17:06:52 -05002531 hci_req_init(&req, hdev);
2532
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002533 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002534 hci_dev_unlock(hdev);
2535 cancel_delayed_work_sync(&hdev->service_cache);
2536 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002537 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002538 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002539
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 update_class(&req);
2541
Johan Hedberg92da6092013-03-15 17:06:55 -05002542 err = hci_req_run(&req, set_class_complete);
2543 if (err < 0) {
2544 if (err != -ENODATA)
2545 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002547 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002548 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002549 goto unlock;
2550 }
2551
2552 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002553 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002554 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002555 goto unlock;
2556 }
2557
2558 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002559
Johan Hedbergb5235a62012-02-21 14:32:24 +02002560unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002561 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002562 return err;
2563}
2564
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002565static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002566 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002567{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002568 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002569 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2570 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002571 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002572 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002573 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002574
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002575 BT_DBG("request for %s", hdev->name);
2576
2577 if (!lmp_bredr_capable(hdev))
2578 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2579 MGMT_STATUS_NOT_SUPPORTED);
2580
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002581 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002582 if (key_count > max_key_count) {
2583 BT_ERR("load_link_keys: too big key_count value %u",
2584 key_count);
2585 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2586 MGMT_STATUS_INVALID_PARAMS);
2587 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002588
Johan Hedberg86742e12011-11-07 23:13:38 +02002589 expected_len = sizeof(*cp) + key_count *
2590 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002591 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002592 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002593 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002594 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002595 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002596 }
2597
Johan Hedberg4ae14302013-01-20 14:27:13 +02002598 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2599 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2600 MGMT_STATUS_INVALID_PARAMS);
2601
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002602 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002603 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002604
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002605 for (i = 0; i < key_count; i++) {
2606 struct mgmt_link_key_info *key = &cp->keys[i];
2607
Marcel Holtmann8e991132014-01-10 02:07:25 -08002608 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002609 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2610 MGMT_STATUS_INVALID_PARAMS);
2611 }
2612
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002613 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002614
2615 hci_link_keys_clear(hdev);
2616
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002617 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002618 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2619 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002620 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002621 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2622 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002623
2624 if (changed)
2625 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002626
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002627 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002628 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002629
Johan Hedberg58e92932014-06-24 14:00:26 +03002630 /* Always ignore debug keys and require a new pairing if
2631 * the user wants to use them.
2632 */
2633 if (key->type == HCI_LK_DEBUG_COMBINATION)
2634 continue;
2635
Johan Hedberg7652ff62014-06-24 13:15:49 +03002636 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2637 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002638 }
2639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002640 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002641
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002642 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002643
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002644 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002645}
2646
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002647static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002648 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002649{
2650 struct mgmt_ev_device_unpaired ev;
2651
2652 bacpy(&ev.addr.bdaddr, bdaddr);
2653 ev.addr.type = addr_type;
2654
2655 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002656 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002657}
2658
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002659static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002660 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002662 struct mgmt_cp_unpair_device *cp = data;
2663 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002664 struct hci_cp_disconnect dc;
2665 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002666 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002667 int err;
2668
Johan Hedberga8a1d192011-11-10 15:54:38 +02002669 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002670 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2671 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002672
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002673 if (!bdaddr_type_is_valid(cp->addr.type))
2674 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2675 MGMT_STATUS_INVALID_PARAMS,
2676 &rp, sizeof(rp));
2677
Johan Hedberg118da702013-01-20 14:27:20 +02002678 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2679 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2680 MGMT_STATUS_INVALID_PARAMS,
2681 &rp, sizeof(rp));
2682
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002683 hci_dev_lock(hdev);
2684
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002685 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002686 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002687 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002688 goto unlock;
2689 }
2690
Johan Hedberge0b2b272014-02-18 17:14:31 +02002691 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002692 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002693 } else {
2694 u8 addr_type;
2695
2696 if (cp->addr.type == BDADDR_LE_PUBLIC)
2697 addr_type = ADDR_LE_DEV_PUBLIC;
2698 else
2699 addr_type = ADDR_LE_DEV_RANDOM;
2700
Johan Hedberga7ec7332014-02-18 17:14:35 +02002701 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2702
Andre Guedesa9b0a042014-02-26 20:21:52 -03002703 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2704
Johan Hedberge0b2b272014-02-18 17:14:31 +02002705 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2706 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002707
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002708 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002709 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002710 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711 goto unlock;
2712 }
2713
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002714 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002715 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002716 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002717 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002718 else
2719 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002720 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002721 } else {
2722 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002723 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002724
Johan Hedberga8a1d192011-11-10 15:54:38 +02002725 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002726 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002727 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002728 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002729 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002730 }
2731
Johan Hedberg124f6e32012-02-09 13:50:12 +02002732 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002733 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002734 if (!cmd) {
2735 err = -ENOMEM;
2736 goto unlock;
2737 }
2738
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002739 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002740 dc.reason = 0x13; /* Remote User Terminated Connection */
2741 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2742 if (err < 0)
2743 mgmt_pending_remove(cmd);
2744
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002745unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002746 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002747 return err;
2748}
2749
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002750static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002751 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002752{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002753 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002754 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002755 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002756 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002757 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002758 int err;
2759
2760 BT_DBG("");
2761
Johan Hedberg06a63b12013-01-20 14:27:21 +02002762 memset(&rp, 0, sizeof(rp));
2763 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2764 rp.addr.type = cp->addr.type;
2765
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002766 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002767 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2768 MGMT_STATUS_INVALID_PARAMS,
2769 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002770
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002771 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002772
2773 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002774 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2775 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002776 goto failed;
2777 }
2778
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002779 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002780 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2781 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002782 goto failed;
2783 }
2784
Andre Guedes591f47f2012-04-24 21:02:49 -03002785 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002786 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2787 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002788 else
2789 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002790
Vishal Agarwalf9607272012-06-13 05:32:43 +05302791 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002792 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2793 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002794 goto failed;
2795 }
2796
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002797 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002798 if (!cmd) {
2799 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002800 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002801 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002802
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002803 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002804 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002805
2806 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2807 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002808 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002809
2810failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002811 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002812 return err;
2813}
2814
Andre Guedes57c14772012-04-24 21:02:50 -03002815static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002816{
2817 switch (link_type) {
2818 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002819 switch (addr_type) {
2820 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002821 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002822
Johan Hedberg48264f02011-11-09 13:58:58 +02002823 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002824 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002825 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002826 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002827
Johan Hedberg4c659c32011-11-07 23:13:39 +02002828 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002829 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002830 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002831 }
2832}
2833
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002834static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2835 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002836{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002837 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002838 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002839 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002840 int err;
2841 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002842
2843 BT_DBG("");
2844
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002845 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002846
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002847 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002848 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002849 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002850 goto unlock;
2851 }
2852
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002853 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002854 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2855 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002856 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002857 }
2858
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002859 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002860 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002861 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002862 err = -ENOMEM;
2863 goto unlock;
2864 }
2865
Johan Hedberg2784eb42011-01-21 13:56:35 +02002866 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002867 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002868 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2869 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002870 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002871 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002872 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002873 continue;
2874 i++;
2875 }
2876
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002877 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002878
Johan Hedberg4c659c32011-11-07 23:13:39 +02002879 /* Recalculate length in case of filtered SCO connections, etc */
2880 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002881
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002882 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002883 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002884
Johan Hedberga38528f2011-01-22 06:46:43 +02002885 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002886
2887unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002888 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002889 return err;
2890}
2891
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002892static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002893 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002894{
2895 struct pending_cmd *cmd;
2896 int err;
2897
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002898 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002899 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002900 if (!cmd)
2901 return -ENOMEM;
2902
Johan Hedbergd8457692012-02-17 14:24:57 +02002903 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002904 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002905 if (err < 0)
2906 mgmt_pending_remove(cmd);
2907
2908 return err;
2909}
2910
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002911static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002912 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002913{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002914 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002915 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002916 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002917 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002918 int err;
2919
2920 BT_DBG("");
2921
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002922 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002923
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002924 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002925 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002926 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002927 goto failed;
2928 }
2929
Johan Hedbergd8457692012-02-17 14:24:57 +02002930 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002931 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002932 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002933 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002934 goto failed;
2935 }
2936
2937 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002938 struct mgmt_cp_pin_code_neg_reply ncp;
2939
2940 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002941
2942 BT_ERR("PIN code is not 16 bytes long");
2943
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002944 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002945 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002946 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002947 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002948
2949 goto failed;
2950 }
2951
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002952 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002953 if (!cmd) {
2954 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002955 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002956 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002957
Johan Hedbergd8457692012-02-17 14:24:57 +02002958 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002959 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002960 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002961
2962 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2963 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002964 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002965
2966failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002967 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002968 return err;
2969}
2970
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002971static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2972 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002973{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002974 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002975
2976 BT_DBG("");
2977
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002978 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2979 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2980 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2981
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002982 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002983
2984 hdev->io_capability = cp->io_capability;
2985
2986 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002987 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002988
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002989 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002990
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002991 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2992 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002993}
2994
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002995static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002996{
2997 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002998 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002999
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003000 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003001 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3002 continue;
3003
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004 if (cmd->user_data != conn)
3005 continue;
3006
3007 return cmd;
3008 }
3009
3010 return NULL;
3011}
3012
3013static void pairing_complete(struct pending_cmd *cmd, u8 status)
3014{
3015 struct mgmt_rp_pair_device rp;
3016 struct hci_conn *conn = cmd->user_data;
3017
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003018 bacpy(&rp.addr.bdaddr, &conn->dst);
3019 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003020
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003021 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003022 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003023
3024 /* So we don't get further callbacks for this connection */
3025 conn->connect_cfm_cb = NULL;
3026 conn->security_cfm_cb = NULL;
3027 conn->disconn_cfm_cb = NULL;
3028
David Herrmann76a68ba2013-04-06 20:28:37 +02003029 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003030
Johan Hedberga664b5b2011-02-19 12:06:02 -03003031 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003032}
3033
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003034void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3035{
3036 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3037 struct pending_cmd *cmd;
3038
3039 cmd = find_pairing(conn);
3040 if (cmd)
3041 pairing_complete(cmd, status);
3042}
3043
Johan Hedberge9a416b2011-02-19 12:05:56 -03003044static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3045{
3046 struct pending_cmd *cmd;
3047
3048 BT_DBG("status %u", status);
3049
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003050 cmd = find_pairing(conn);
3051 if (!cmd)
3052 BT_DBG("Unable to find a pending command");
3053 else
Johan Hedberge2113262012-02-18 15:20:03 +02003054 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003055}
3056
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003057static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303058{
3059 struct pending_cmd *cmd;
3060
3061 BT_DBG("status %u", status);
3062
3063 if (!status)
3064 return;
3065
3066 cmd = find_pairing(conn);
3067 if (!cmd)
3068 BT_DBG("Unable to find a pending command");
3069 else
3070 pairing_complete(cmd, mgmt_status(status));
3071}
3072
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003073static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003074 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003075{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003076 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003077 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003078 struct pending_cmd *cmd;
3079 u8 sec_level, auth_type;
3080 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003081 int err;
3082
3083 BT_DBG("");
3084
Szymon Jancf950a30e2013-01-18 12:48:07 +01003085 memset(&rp, 0, sizeof(rp));
3086 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3087 rp.addr.type = cp->addr.type;
3088
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003089 if (!bdaddr_type_is_valid(cp->addr.type))
3090 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3091 MGMT_STATUS_INVALID_PARAMS,
3092 &rp, sizeof(rp));
3093
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003094 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3095 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3096 MGMT_STATUS_INVALID_PARAMS,
3097 &rp, sizeof(rp));
3098
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003099 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003100
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003101 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003102 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3103 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003104 goto unlock;
3105 }
3106
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003107 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003108 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003109
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003110 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003111 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3112 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003113 } else {
3114 u8 addr_type;
3115
3116 /* Convert from L2CAP channel address type to HCI address type
3117 */
3118 if (cp->addr.type == BDADDR_LE_PUBLIC)
3119 addr_type = ADDR_LE_DEV_PUBLIC;
3120 else
3121 addr_type = ADDR_LE_DEV_RANDOM;
3122
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003123 /* When pairing a new device, it is expected to remember
3124 * this device for future connections. Adding the connection
3125 * parameter information ahead of time allows tracking
3126 * of the slave preferred values and will speed up any
3127 * further connection establishment.
3128 *
3129 * If connection parameters already exist, then they
3130 * will be kept and this function does nothing.
3131 */
3132 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3133
Johan Hedbergcdd62752014-07-07 15:02:28 +03003134 /* Request a connection with master = true role */
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003135 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedbergcdd62752014-07-07 15:02:28 +03003136 sec_level, HCI_LE_CONN_TIMEOUT, true);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003137 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003138
Ville Tervo30e76272011-02-22 16:10:53 -03003139 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003140 int status;
3141
3142 if (PTR_ERR(conn) == -EBUSY)
3143 status = MGMT_STATUS_BUSY;
3144 else
3145 status = MGMT_STATUS_CONNECT_FAILED;
3146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003147 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003148 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003149 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003150 goto unlock;
3151 }
3152
3153 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003154 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003155 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003156 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003157 goto unlock;
3158 }
3159
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003160 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003161 if (!cmd) {
3162 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003163 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003164 goto unlock;
3165 }
3166
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003167 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003168 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003169 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003170 conn->security_cfm_cb = pairing_complete_cb;
3171 conn->disconn_cfm_cb = pairing_complete_cb;
3172 } else {
3173 conn->connect_cfm_cb = le_pairing_complete_cb;
3174 conn->security_cfm_cb = le_pairing_complete_cb;
3175 conn->disconn_cfm_cb = le_pairing_complete_cb;
3176 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003177
Johan Hedberge9a416b2011-02-19 12:05:56 -03003178 conn->io_capability = cp->io_cap;
3179 cmd->user_data = conn;
3180
3181 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003182 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003183 pairing_complete(cmd, 0);
3184
3185 err = 0;
3186
3187unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003188 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003189 return err;
3190}
3191
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003192static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3193 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003194{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003195 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003196 struct pending_cmd *cmd;
3197 struct hci_conn *conn;
3198 int err;
3199
3200 BT_DBG("");
3201
Johan Hedberg28424702012-02-02 04:02:29 +02003202 hci_dev_lock(hdev);
3203
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003204 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003205 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003206 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003207 goto unlock;
3208 }
3209
Johan Hedberg28424702012-02-02 04:02:29 +02003210 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3211 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003212 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003213 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003214 goto unlock;
3215 }
3216
3217 conn = cmd->user_data;
3218
3219 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003220 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003222 goto unlock;
3223 }
3224
3225 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3226
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003227 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003228 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003229unlock:
3230 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003231 return err;
3232}
3233
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003234static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003235 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003236 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003237{
Johan Hedberga5c29682011-02-19 12:05:57 -03003238 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003239 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003240 int err;
3241
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003242 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003243
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003244 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003245 err = cmd_complete(sk, hdev->id, mgmt_op,
3246 MGMT_STATUS_NOT_POWERED, addr,
3247 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003248 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003249 }
3250
Johan Hedberg1707c602013-03-15 17:07:15 -05003251 if (addr->type == BDADDR_BREDR)
3252 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003253 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003254 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003255
Johan Hedberg272d90d2012-02-09 15:26:12 +02003256 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003257 err = cmd_complete(sk, hdev->id, mgmt_op,
3258 MGMT_STATUS_NOT_CONNECTED, addr,
3259 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003260 goto done;
3261 }
3262
Johan Hedberg1707c602013-03-15 17:07:15 -05003263 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003264 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003265 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003266 err = cmd_complete(sk, hdev->id, mgmt_op,
3267 MGMT_STATUS_SUCCESS, addr,
3268 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003269 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003270 err = cmd_complete(sk, hdev->id, mgmt_op,
3271 MGMT_STATUS_FAILED, addr,
3272 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003273
Brian Gix47c15e22011-11-16 13:53:14 -08003274 goto done;
3275 }
3276
Johan Hedberg1707c602013-03-15 17:07:15 -05003277 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003278 if (!cmd) {
3279 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003280 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003281 }
3282
Brian Gix0df4c182011-11-16 13:53:13 -08003283 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003284 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3285 struct hci_cp_user_passkey_reply cp;
3286
Johan Hedberg1707c602013-03-15 17:07:15 -05003287 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003288 cp.passkey = passkey;
3289 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3290 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003291 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3292 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003293
Johan Hedberga664b5b2011-02-19 12:06:02 -03003294 if (err < 0)
3295 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003296
Brian Gix0df4c182011-11-16 13:53:13 -08003297done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003298 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003299 return err;
3300}
3301
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303302static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3303 void *data, u16 len)
3304{
3305 struct mgmt_cp_pin_code_neg_reply *cp = data;
3306
3307 BT_DBG("");
3308
Johan Hedberg1707c602013-03-15 17:07:15 -05003309 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303310 MGMT_OP_PIN_CODE_NEG_REPLY,
3311 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3312}
3313
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003314static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3315 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003316{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003317 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003318
3319 BT_DBG("");
3320
3321 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003322 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003323 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003324
Johan Hedberg1707c602013-03-15 17:07:15 -05003325 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003326 MGMT_OP_USER_CONFIRM_REPLY,
3327 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003328}
3329
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003330static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003331 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003332{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003333 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003334
3335 BT_DBG("");
3336
Johan Hedberg1707c602013-03-15 17:07:15 -05003337 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003338 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3339 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003340}
3341
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003342static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3343 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003344{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003345 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003346
3347 BT_DBG("");
3348
Johan Hedberg1707c602013-03-15 17:07:15 -05003349 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003350 MGMT_OP_USER_PASSKEY_REPLY,
3351 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003352}
3353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003354static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003355 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003356{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003357 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003358
3359 BT_DBG("");
3360
Johan Hedberg1707c602013-03-15 17:07:15 -05003361 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003362 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3363 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003364}
3365
Johan Hedberg13928972013-03-15 17:07:00 -05003366static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003367{
Johan Hedberg13928972013-03-15 17:07:00 -05003368 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003369 struct hci_cp_write_local_name cp;
3370
Johan Hedberg13928972013-03-15 17:07:00 -05003371 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003372
Johan Hedberg890ea892013-03-15 17:06:52 -05003373 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003374}
3375
Johan Hedberg13928972013-03-15 17:07:00 -05003376static void set_name_complete(struct hci_dev *hdev, u8 status)
3377{
3378 struct mgmt_cp_set_local_name *cp;
3379 struct pending_cmd *cmd;
3380
3381 BT_DBG("status 0x%02x", status);
3382
3383 hci_dev_lock(hdev);
3384
3385 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3386 if (!cmd)
3387 goto unlock;
3388
3389 cp = cmd->param;
3390
3391 if (status)
3392 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3393 mgmt_status(status));
3394 else
3395 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3396 cp, sizeof(*cp));
3397
3398 mgmt_pending_remove(cmd);
3399
3400unlock:
3401 hci_dev_unlock(hdev);
3402}
3403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003404static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003405 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003406{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003407 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003408 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003409 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003410 int err;
3411
3412 BT_DBG("");
3413
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003414 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003415
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003416 /* If the old values are the same as the new ones just return a
3417 * direct command complete event.
3418 */
3419 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3420 !memcmp(hdev->short_name, cp->short_name,
3421 sizeof(hdev->short_name))) {
3422 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3423 data, len);
3424 goto failed;
3425 }
3426
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003427 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003428
Johan Hedbergb5235a62012-02-21 14:32:24 +02003429 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003430 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003431
3432 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003433 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003434 if (err < 0)
3435 goto failed;
3436
3437 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003438 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003439
Johan Hedbergb5235a62012-02-21 14:32:24 +02003440 goto failed;
3441 }
3442
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003443 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003444 if (!cmd) {
3445 err = -ENOMEM;
3446 goto failed;
3447 }
3448
Johan Hedberg13928972013-03-15 17:07:00 -05003449 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3450
Johan Hedberg890ea892013-03-15 17:06:52 -05003451 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003452
3453 if (lmp_bredr_capable(hdev)) {
3454 update_name(&req);
3455 update_eir(&req);
3456 }
3457
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003458 /* The name is stored in the scan response data and so
3459 * no need to udpate the advertising data here.
3460 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003461 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003462 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003463
Johan Hedberg13928972013-03-15 17:07:00 -05003464 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003465 if (err < 0)
3466 mgmt_pending_remove(cmd);
3467
3468failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003469 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003470 return err;
3471}
3472
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003473static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003474 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003475{
Szymon Jancc35938b2011-03-22 13:12:21 +01003476 struct pending_cmd *cmd;
3477 int err;
3478
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003479 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003480
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003481 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003482
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003483 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003484 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003485 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003486 goto unlock;
3487 }
3488
Andre Guedes9a1a1992012-07-24 15:03:48 -03003489 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003490 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003491 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003492 goto unlock;
3493 }
3494
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003495 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003496 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003497 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003498 goto unlock;
3499 }
3500
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003501 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003502 if (!cmd) {
3503 err = -ENOMEM;
3504 goto unlock;
3505 }
3506
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003507 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3508 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3509 0, NULL);
3510 else
3511 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3512
Szymon Jancc35938b2011-03-22 13:12:21 +01003513 if (err < 0)
3514 mgmt_pending_remove(cmd);
3515
3516unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003517 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003518 return err;
3519}
3520
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003521static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003522 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003523{
Szymon Janc2763eda2011-03-22 13:12:22 +01003524 int err;
3525
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003526 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003527
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003528 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003529
Marcel Holtmannec109112014-01-10 02:07:30 -08003530 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3531 struct mgmt_cp_add_remote_oob_data *cp = data;
3532 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003533
Marcel Holtmannec109112014-01-10 02:07:30 -08003534 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3535 cp->hash, cp->randomizer);
3536 if (err < 0)
3537 status = MGMT_STATUS_FAILED;
3538 else
3539 status = MGMT_STATUS_SUCCESS;
3540
3541 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3542 status, &cp->addr, sizeof(cp->addr));
3543 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3544 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3545 u8 status;
3546
3547 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3548 cp->hash192,
3549 cp->randomizer192,
3550 cp->hash256,
3551 cp->randomizer256);
3552 if (err < 0)
3553 status = MGMT_STATUS_FAILED;
3554 else
3555 status = MGMT_STATUS_SUCCESS;
3556
3557 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3558 status, &cp->addr, sizeof(cp->addr));
3559 } else {
3560 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3561 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3562 MGMT_STATUS_INVALID_PARAMS);
3563 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003564
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003565 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003566 return err;
3567}
3568
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003569static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003570 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003571{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003572 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003573 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003574 int err;
3575
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003576 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003577
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003578 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003579
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003580 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003581 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003582 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003583 else
Szymon Janca6785be2012-12-13 15:11:21 +01003584 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003585
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003586 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003587 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003588
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003589 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003590 return err;
3591}
3592
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003593static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3594{
3595 struct pending_cmd *cmd;
3596 u8 type;
3597 int err;
3598
3599 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3600
3601 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3602 if (!cmd)
3603 return -ENOENT;
3604
3605 type = hdev->discovery.type;
3606
3607 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3608 &type, sizeof(type));
3609 mgmt_pending_remove(cmd);
3610
3611 return err;
3612}
3613
Andre Guedes7c307722013-04-30 15:29:28 -03003614static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3615{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003616 unsigned long timeout = 0;
3617
Andre Guedes7c307722013-04-30 15:29:28 -03003618 BT_DBG("status %d", status);
3619
3620 if (status) {
3621 hci_dev_lock(hdev);
3622 mgmt_start_discovery_failed(hdev, status);
3623 hci_dev_unlock(hdev);
3624 return;
3625 }
3626
3627 hci_dev_lock(hdev);
3628 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3629 hci_dev_unlock(hdev);
3630
3631 switch (hdev->discovery.type) {
3632 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003633 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003634 break;
3635
3636 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003637 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003638 break;
3639
3640 case DISCOV_TYPE_BREDR:
3641 break;
3642
3643 default:
3644 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3645 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003646
3647 if (!timeout)
3648 return;
3649
3650 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003651}
3652
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003653static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003654 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003655{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003656 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003657 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003658 struct hci_cp_le_set_scan_param param_cp;
3659 struct hci_cp_le_set_scan_enable enable_cp;
3660 struct hci_cp_inquiry inq_cp;
3661 struct hci_request req;
3662 /* General inquiry access code (GIAC) */
3663 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003664 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003665 int err;
3666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003667 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003668
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003669 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003670
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003671 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003672 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003673 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003674 goto failed;
3675 }
3676
Andre Guedes642be6c2012-03-21 00:03:37 -03003677 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3678 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3679 MGMT_STATUS_BUSY);
3680 goto failed;
3681 }
3682
Johan Hedbergff9ef572012-01-04 14:23:45 +02003683 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003684 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003685 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003686 goto failed;
3687 }
3688
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003689 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003690 if (!cmd) {
3691 err = -ENOMEM;
3692 goto failed;
3693 }
3694
Andre Guedes4aab14e2012-02-17 20:39:36 -03003695 hdev->discovery.type = cp->type;
3696
Andre Guedes7c307722013-04-30 15:29:28 -03003697 hci_req_init(&req, hdev);
3698
Andre Guedes4aab14e2012-02-17 20:39:36 -03003699 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003700 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003701 status = mgmt_bredr_support(hdev);
3702 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003703 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003704 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003705 mgmt_pending_remove(cmd);
3706 goto failed;
3707 }
3708
Andre Guedes7c307722013-04-30 15:29:28 -03003709 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3710 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3711 MGMT_STATUS_BUSY);
3712 mgmt_pending_remove(cmd);
3713 goto failed;
3714 }
3715
3716 hci_inquiry_cache_flush(hdev);
3717
3718 memset(&inq_cp, 0, sizeof(inq_cp));
3719 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003720 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003721 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003722 break;
3723
3724 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003725 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003726 status = mgmt_le_support(hdev);
3727 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003728 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003729 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003730 mgmt_pending_remove(cmd);
3731 goto failed;
3732 }
3733
Andre Guedes7c307722013-04-30 15:29:28 -03003734 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003735 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003736 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3737 MGMT_STATUS_NOT_SUPPORTED);
3738 mgmt_pending_remove(cmd);
3739 goto failed;
3740 }
3741
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003742 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3743 /* Don't let discovery abort an outgoing
3744 * connection attempt that's using directed
3745 * advertising.
3746 */
3747 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3748 BT_CONNECT)) {
3749 err = cmd_status(sk, hdev->id,
3750 MGMT_OP_START_DISCOVERY,
3751 MGMT_STATUS_REJECTED);
3752 mgmt_pending_remove(cmd);
3753 goto failed;
3754 }
3755
3756 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003757 }
3758
Andre Guedesc54c3862014-02-26 20:21:50 -03003759 /* If controller is scanning, it means the background scanning
3760 * is running. Thus, we should temporarily stop it in order to
3761 * set the discovery scanning parameters.
3762 */
3763 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3764 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003765
3766 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003767
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003768 /* All active scans will be done with either a resolvable
3769 * private address (when privacy feature has been enabled)
3770 * or unresolvable private address.
3771 */
3772 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003773 if (err < 0) {
3774 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3775 MGMT_STATUS_FAILED);
3776 mgmt_pending_remove(cmd);
3777 goto failed;
3778 }
3779
Andre Guedes7c307722013-04-30 15:29:28 -03003780 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003781 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3782 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003783 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003784 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3785 &param_cp);
3786
3787 memset(&enable_cp, 0, sizeof(enable_cp));
3788 enable_cp.enable = LE_SCAN_ENABLE;
3789 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3790 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3791 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003792 break;
3793
Andre Guedesf39799f2012-02-17 20:39:35 -03003794 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003795 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3796 MGMT_STATUS_INVALID_PARAMS);
3797 mgmt_pending_remove(cmd);
3798 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003799 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003800
Andre Guedes7c307722013-04-30 15:29:28 -03003801 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003802 if (err < 0)
3803 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003804 else
3805 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003806
3807failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003808 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003809 return err;
3810}
3811
Andre Guedes1183fdc2013-04-30 15:29:35 -03003812static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3813{
3814 struct pending_cmd *cmd;
3815 int err;
3816
3817 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3818 if (!cmd)
3819 return -ENOENT;
3820
3821 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3822 &hdev->discovery.type, sizeof(hdev->discovery.type));
3823 mgmt_pending_remove(cmd);
3824
3825 return err;
3826}
3827
Andre Guedes0e05bba2013-04-30 15:29:33 -03003828static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3829{
3830 BT_DBG("status %d", status);
3831
3832 hci_dev_lock(hdev);
3833
3834 if (status) {
3835 mgmt_stop_discovery_failed(hdev, status);
3836 goto unlock;
3837 }
3838
3839 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3840
3841unlock:
3842 hci_dev_unlock(hdev);
3843}
3844
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003845static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003846 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003847{
Johan Hedbergd9306502012-02-20 23:25:18 +02003848 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003849 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003850 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003851 int err;
3852
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003853 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003854
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003855 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003856
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003857 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003858 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003859 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3860 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003861 goto unlock;
3862 }
3863
3864 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003865 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003866 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3867 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003868 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003869 }
3870
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003871 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003872 if (!cmd) {
3873 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003874 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003875 }
3876
Andre Guedes0e05bba2013-04-30 15:29:33 -03003877 hci_req_init(&req, hdev);
3878
Johan Hedberg21a60d32014-06-10 14:05:58 +03003879 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003880
Johan Hedberg21a60d32014-06-10 14:05:58 +03003881 err = hci_req_run(&req, stop_discovery_complete);
3882 if (!err) {
3883 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003884 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003885 }
3886
Johan Hedberg21a60d32014-06-10 14:05:58 +03003887 mgmt_pending_remove(cmd);
3888
3889 /* If no HCI commands were sent we're done */
3890 if (err == -ENODATA) {
3891 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3892 &mgmt_cp->type, sizeof(mgmt_cp->type));
3893 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3894 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003895
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003896unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003897 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003898 return err;
3899}
3900
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003901static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003902 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003903{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003904 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003905 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003906 int err;
3907
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003908 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003909
Johan Hedberg561aafb2012-01-04 13:31:59 +02003910 hci_dev_lock(hdev);
3911
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003912 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003913 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3914 MGMT_STATUS_FAILED, &cp->addr,
3915 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003916 goto failed;
3917 }
3918
Johan Hedberga198e7b2012-02-17 14:27:06 +02003919 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003920 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003921 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3922 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3923 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003924 goto failed;
3925 }
3926
3927 if (cp->name_known) {
3928 e->name_state = NAME_KNOWN;
3929 list_del(&e->list);
3930 } else {
3931 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003932 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003933 }
3934
Johan Hedberge3846622013-01-09 15:29:33 +02003935 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3936 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003937
3938failed:
3939 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003940 return err;
3941}
3942
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003943static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003944 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003945{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003946 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003947 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003948 int err;
3949
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003950 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003951
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003952 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003953 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3954 MGMT_STATUS_INVALID_PARAMS,
3955 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003956
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003957 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003958
Johan Hedbergdcc36c12014-07-09 12:59:13 +03003959 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
3960 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003961 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003962 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003963 goto done;
3964 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003965
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003966 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3967 sk);
3968 status = MGMT_STATUS_SUCCESS;
3969
3970done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003971 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003972 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003973
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003974 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003975
3976 return err;
3977}
3978
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003979static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003980 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003981{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003982 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003983 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003984 int err;
3985
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003986 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003987
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003988 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003989 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3990 MGMT_STATUS_INVALID_PARAMS,
3991 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003992
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003993 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003994
Johan Hedbergdcc36c12014-07-09 12:59:13 +03003995 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
3996 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003997 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003998 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003999 goto done;
4000 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004001
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004002 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4003 sk);
4004 status = MGMT_STATUS_SUCCESS;
4005
4006done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004007 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004008 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004009
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004010 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004011
4012 return err;
4013}
4014
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004015static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4016 u16 len)
4017{
4018 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004019 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004020 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004021 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004022
4023 BT_DBG("%s", hdev->name);
4024
Szymon Jancc72d4b82012-03-16 16:02:57 +01004025 source = __le16_to_cpu(cp->source);
4026
4027 if (source > 0x0002)
4028 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4029 MGMT_STATUS_INVALID_PARAMS);
4030
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004031 hci_dev_lock(hdev);
4032
Szymon Jancc72d4b82012-03-16 16:02:57 +01004033 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004034 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4035 hdev->devid_product = __le16_to_cpu(cp->product);
4036 hdev->devid_version = __le16_to_cpu(cp->version);
4037
4038 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4039
Johan Hedberg890ea892013-03-15 17:06:52 -05004040 hci_req_init(&req, hdev);
4041 update_eir(&req);
4042 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004043
4044 hci_dev_unlock(hdev);
4045
4046 return err;
4047}
4048
Johan Hedberg4375f102013-09-25 13:26:10 +03004049static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4050{
4051 struct cmd_lookup match = { NULL, hdev };
4052
4053 if (status) {
4054 u8 mgmt_err = mgmt_status(status);
4055
4056 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4057 cmd_status_rsp, &mgmt_err);
4058 return;
4059 }
4060
Johan Hedbergc93bd152014-07-08 15:07:48 +03004061 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4062 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4063 else
4064 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4065
Johan Hedberg4375f102013-09-25 13:26:10 +03004066 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4067 &match);
4068
4069 new_settings(hdev, match.sk);
4070
4071 if (match.sk)
4072 sock_put(match.sk);
4073}
4074
Marcel Holtmann21b51872013-10-10 09:47:53 -07004075static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4076 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004077{
4078 struct mgmt_mode *cp = data;
4079 struct pending_cmd *cmd;
4080 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004081 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004082 int err;
4083
4084 BT_DBG("request for %s", hdev->name);
4085
Johan Hedberge6fe7982013-10-02 15:45:22 +03004086 status = mgmt_le_support(hdev);
4087 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004088 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004089 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004090
4091 if (cp->val != 0x00 && cp->val != 0x01)
4092 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4093 MGMT_STATUS_INVALID_PARAMS);
4094
4095 hci_dev_lock(hdev);
4096
4097 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004098 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004099
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004100 /* The following conditions are ones which mean that we should
4101 * not do any HCI communication but directly send a mgmt
4102 * response to user space (after toggling the flag if
4103 * necessary).
4104 */
4105 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004106 hci_conn_num(hdev, LE_LINK) > 0 ||
4107 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4108 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004109 bool changed = false;
4110
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004111 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4112 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004113 changed = true;
4114 }
4115
4116 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4117 if (err < 0)
4118 goto unlock;
4119
4120 if (changed)
4121 err = new_settings(hdev, sk);
4122
4123 goto unlock;
4124 }
4125
4126 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4127 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4128 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4129 MGMT_STATUS_BUSY);
4130 goto unlock;
4131 }
4132
4133 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4134 if (!cmd) {
4135 err = -ENOMEM;
4136 goto unlock;
4137 }
4138
4139 hci_req_init(&req, hdev);
4140
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004141 if (val)
4142 enable_advertising(&req);
4143 else
4144 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004145
4146 err = hci_req_run(&req, set_advertising_complete);
4147 if (err < 0)
4148 mgmt_pending_remove(cmd);
4149
4150unlock:
4151 hci_dev_unlock(hdev);
4152 return err;
4153}
4154
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004155static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4156 void *data, u16 len)
4157{
4158 struct mgmt_cp_set_static_address *cp = data;
4159 int err;
4160
4161 BT_DBG("%s", hdev->name);
4162
Marcel Holtmann62af4442013-10-02 22:10:32 -07004163 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004164 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004165 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004166
4167 if (hdev_is_powered(hdev))
4168 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4169 MGMT_STATUS_REJECTED);
4170
4171 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4172 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4173 return cmd_status(sk, hdev->id,
4174 MGMT_OP_SET_STATIC_ADDRESS,
4175 MGMT_STATUS_INVALID_PARAMS);
4176
4177 /* Two most significant bits shall be set */
4178 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4179 return cmd_status(sk, hdev->id,
4180 MGMT_OP_SET_STATIC_ADDRESS,
4181 MGMT_STATUS_INVALID_PARAMS);
4182 }
4183
4184 hci_dev_lock(hdev);
4185
4186 bacpy(&hdev->static_addr, &cp->bdaddr);
4187
4188 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4189
4190 hci_dev_unlock(hdev);
4191
4192 return err;
4193}
4194
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004195static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4196 void *data, u16 len)
4197{
4198 struct mgmt_cp_set_scan_params *cp = data;
4199 __u16 interval, window;
4200 int err;
4201
4202 BT_DBG("%s", hdev->name);
4203
4204 if (!lmp_le_capable(hdev))
4205 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4206 MGMT_STATUS_NOT_SUPPORTED);
4207
4208 interval = __le16_to_cpu(cp->interval);
4209
4210 if (interval < 0x0004 || interval > 0x4000)
4211 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4212 MGMT_STATUS_INVALID_PARAMS);
4213
4214 window = __le16_to_cpu(cp->window);
4215
4216 if (window < 0x0004 || window > 0x4000)
4217 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4218 MGMT_STATUS_INVALID_PARAMS);
4219
Marcel Holtmann899e1072013-10-14 09:55:32 -07004220 if (window > interval)
4221 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4222 MGMT_STATUS_INVALID_PARAMS);
4223
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004224 hci_dev_lock(hdev);
4225
4226 hdev->le_scan_interval = interval;
4227 hdev->le_scan_window = window;
4228
4229 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4230
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004231 /* If background scan is running, restart it so new parameters are
4232 * loaded.
4233 */
4234 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4235 hdev->discovery.state == DISCOVERY_STOPPED) {
4236 struct hci_request req;
4237
4238 hci_req_init(&req, hdev);
4239
4240 hci_req_add_le_scan_disable(&req);
4241 hci_req_add_le_passive_scan(&req);
4242
4243 hci_req_run(&req, NULL);
4244 }
4245
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004246 hci_dev_unlock(hdev);
4247
4248 return err;
4249}
4250
Johan Hedberg33e38b32013-03-15 17:07:05 -05004251static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4252{
4253 struct pending_cmd *cmd;
4254
4255 BT_DBG("status 0x%02x", status);
4256
4257 hci_dev_lock(hdev);
4258
4259 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4260 if (!cmd)
4261 goto unlock;
4262
4263 if (status) {
4264 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4265 mgmt_status(status));
4266 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004267 struct mgmt_mode *cp = cmd->param;
4268
4269 if (cp->val)
4270 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4271 else
4272 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4273
Johan Hedberg33e38b32013-03-15 17:07:05 -05004274 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4275 new_settings(hdev, cmd->sk);
4276 }
4277
4278 mgmt_pending_remove(cmd);
4279
4280unlock:
4281 hci_dev_unlock(hdev);
4282}
4283
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004284static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004285 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004286{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004287 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004288 struct pending_cmd *cmd;
4289 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004290 int err;
4291
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004292 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004293
Johan Hedberg56f87902013-10-02 13:43:13 +03004294 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4295 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004296 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4297 MGMT_STATUS_NOT_SUPPORTED);
4298
Johan Hedberga7e80f22013-01-09 16:05:19 +02004299 if (cp->val != 0x00 && cp->val != 0x01)
4300 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4301 MGMT_STATUS_INVALID_PARAMS);
4302
Johan Hedberg5400c042012-02-21 16:40:33 +02004303 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004304 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004305 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004306
4307 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004308 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004309 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004310
4311 hci_dev_lock(hdev);
4312
Johan Hedberg05cbf292013-03-15 17:07:07 -05004313 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4314 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4315 MGMT_STATUS_BUSY);
4316 goto unlock;
4317 }
4318
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004319 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4320 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4321 hdev);
4322 goto unlock;
4323 }
4324
Johan Hedberg33e38b32013-03-15 17:07:05 -05004325 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4326 data, len);
4327 if (!cmd) {
4328 err = -ENOMEM;
4329 goto unlock;
4330 }
4331
4332 hci_req_init(&req, hdev);
4333
Johan Hedberg406d7802013-03-15 17:07:09 -05004334 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004335
4336 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004337 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004338 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004339 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004340 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004341 }
4342
Johan Hedberg33e38b32013-03-15 17:07:05 -05004343unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004344 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004345
Antti Julkuf6422ec2011-06-22 13:11:56 +03004346 return err;
4347}
4348
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004349static void set_bredr_scan(struct hci_request *req)
4350{
4351 struct hci_dev *hdev = req->hdev;
4352 u8 scan = 0;
4353
4354 /* Ensure that fast connectable is disabled. This function will
4355 * not do anything if the page scan parameters are already what
4356 * they should be.
4357 */
4358 write_fast_connectable(req, false);
4359
4360 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4361 scan |= SCAN_PAGE;
4362 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4363 scan |= SCAN_INQUIRY;
4364
4365 if (scan)
4366 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4367}
4368
Johan Hedberg0663ca22013-10-02 13:43:14 +03004369static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4370{
4371 struct pending_cmd *cmd;
4372
4373 BT_DBG("status 0x%02x", status);
4374
4375 hci_dev_lock(hdev);
4376
4377 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4378 if (!cmd)
4379 goto unlock;
4380
4381 if (status) {
4382 u8 mgmt_err = mgmt_status(status);
4383
4384 /* We need to restore the flag if related HCI commands
4385 * failed.
4386 */
4387 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4388
4389 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4390 } else {
4391 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4392 new_settings(hdev, cmd->sk);
4393 }
4394
4395 mgmt_pending_remove(cmd);
4396
4397unlock:
4398 hci_dev_unlock(hdev);
4399}
4400
4401static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4402{
4403 struct mgmt_mode *cp = data;
4404 struct pending_cmd *cmd;
4405 struct hci_request req;
4406 int err;
4407
4408 BT_DBG("request for %s", hdev->name);
4409
4410 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4411 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4412 MGMT_STATUS_NOT_SUPPORTED);
4413
4414 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4415 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4416 MGMT_STATUS_REJECTED);
4417
4418 if (cp->val != 0x00 && cp->val != 0x01)
4419 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4420 MGMT_STATUS_INVALID_PARAMS);
4421
4422 hci_dev_lock(hdev);
4423
4424 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4425 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4426 goto unlock;
4427 }
4428
4429 if (!hdev_is_powered(hdev)) {
4430 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004431 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4432 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4433 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4434 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4435 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4436 }
4437
4438 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4439
4440 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4441 if (err < 0)
4442 goto unlock;
4443
4444 err = new_settings(hdev, sk);
4445 goto unlock;
4446 }
4447
4448 /* Reject disabling when powered on */
4449 if (!cp->val) {
4450 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4451 MGMT_STATUS_REJECTED);
4452 goto unlock;
4453 }
4454
4455 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4456 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4457 MGMT_STATUS_BUSY);
4458 goto unlock;
4459 }
4460
4461 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4462 if (!cmd) {
4463 err = -ENOMEM;
4464 goto unlock;
4465 }
4466
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004467 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004468 * generates the correct flags.
4469 */
4470 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4471
4472 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004473
4474 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4475 set_bredr_scan(&req);
4476
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004477 /* Since only the advertising data flags will change, there
4478 * is no need to update the scan response data.
4479 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004480 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004481
Johan Hedberg0663ca22013-10-02 13:43:14 +03004482 err = hci_req_run(&req, set_bredr_complete);
4483 if (err < 0)
4484 mgmt_pending_remove(cmd);
4485
4486unlock:
4487 hci_dev_unlock(hdev);
4488 return err;
4489}
4490
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004491static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4492 void *data, u16 len)
4493{
4494 struct mgmt_mode *cp = data;
4495 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004496 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004497 int err;
4498
4499 BT_DBG("request for %s", hdev->name);
4500
4501 status = mgmt_bredr_support(hdev);
4502 if (status)
4503 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4504 status);
4505
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004506 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004507 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004508 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4509 MGMT_STATUS_NOT_SUPPORTED);
4510
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004511 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004512 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4513 MGMT_STATUS_INVALID_PARAMS);
4514
4515 hci_dev_lock(hdev);
4516
4517 if (!hdev_is_powered(hdev)) {
4518 bool changed;
4519
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004520 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004521 changed = !test_and_set_bit(HCI_SC_ENABLED,
4522 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004523 if (cp->val == 0x02)
4524 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4525 else
4526 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4527 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004528 changed = test_and_clear_bit(HCI_SC_ENABLED,
4529 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004530 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4531 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004532
4533 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4534 if (err < 0)
4535 goto failed;
4536
4537 if (changed)
4538 err = new_settings(hdev, sk);
4539
4540 goto failed;
4541 }
4542
4543 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4544 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4545 MGMT_STATUS_BUSY);
4546 goto failed;
4547 }
4548
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004549 val = !!cp->val;
4550
4551 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4552 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004553 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4554 goto failed;
4555 }
4556
4557 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4558 if (!cmd) {
4559 err = -ENOMEM;
4560 goto failed;
4561 }
4562
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004563 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004564 if (err < 0) {
4565 mgmt_pending_remove(cmd);
4566 goto failed;
4567 }
4568
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004569 if (cp->val == 0x02)
4570 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4571 else
4572 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4573
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004574failed:
4575 hci_dev_unlock(hdev);
4576 return err;
4577}
4578
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004579static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4580 void *data, u16 len)
4581{
4582 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004583 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004584 int err;
4585
4586 BT_DBG("request for %s", hdev->name);
4587
Johan Hedbergb97109792014-06-24 14:00:28 +03004588 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004589 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4590 MGMT_STATUS_INVALID_PARAMS);
4591
4592 hci_dev_lock(hdev);
4593
4594 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004595 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4596 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004597 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004598 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4599 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004600
Johan Hedbergb97109792014-06-24 14:00:28 +03004601 if (cp->val == 0x02)
4602 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4603 &hdev->dev_flags);
4604 else
4605 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4606 &hdev->dev_flags);
4607
4608 if (hdev_is_powered(hdev) && use_changed &&
4609 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4610 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4611 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4612 sizeof(mode), &mode);
4613 }
4614
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004615 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4616 if (err < 0)
4617 goto unlock;
4618
4619 if (changed)
4620 err = new_settings(hdev, sk);
4621
4622unlock:
4623 hci_dev_unlock(hdev);
4624 return err;
4625}
4626
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004627static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4628 u16 len)
4629{
4630 struct mgmt_cp_set_privacy *cp = cp_data;
4631 bool changed;
4632 int err;
4633
4634 BT_DBG("request for %s", hdev->name);
4635
4636 if (!lmp_le_capable(hdev))
4637 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4638 MGMT_STATUS_NOT_SUPPORTED);
4639
4640 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4641 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4642 MGMT_STATUS_INVALID_PARAMS);
4643
4644 if (hdev_is_powered(hdev))
4645 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4646 MGMT_STATUS_REJECTED);
4647
4648 hci_dev_lock(hdev);
4649
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004650 /* If user space supports this command it is also expected to
4651 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4652 */
4653 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4654
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004655 if (cp->privacy) {
4656 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4657 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4658 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4659 } else {
4660 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4661 memset(hdev->irk, 0, sizeof(hdev->irk));
4662 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4663 }
4664
4665 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4666 if (err < 0)
4667 goto unlock;
4668
4669 if (changed)
4670 err = new_settings(hdev, sk);
4671
4672unlock:
4673 hci_dev_unlock(hdev);
4674 return err;
4675}
4676
Johan Hedberg41edf162014-02-18 10:19:35 +02004677static bool irk_is_valid(struct mgmt_irk_info *irk)
4678{
4679 switch (irk->addr.type) {
4680 case BDADDR_LE_PUBLIC:
4681 return true;
4682
4683 case BDADDR_LE_RANDOM:
4684 /* Two most significant bits shall be set */
4685 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4686 return false;
4687 return true;
4688 }
4689
4690 return false;
4691}
4692
4693static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4694 u16 len)
4695{
4696 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004697 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4698 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004699 u16 irk_count, expected_len;
4700 int i, err;
4701
4702 BT_DBG("request for %s", hdev->name);
4703
4704 if (!lmp_le_capable(hdev))
4705 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4706 MGMT_STATUS_NOT_SUPPORTED);
4707
4708 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004709 if (irk_count > max_irk_count) {
4710 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4711 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4712 MGMT_STATUS_INVALID_PARAMS);
4713 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004714
4715 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4716 if (expected_len != len) {
4717 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004718 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004719 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4720 MGMT_STATUS_INVALID_PARAMS);
4721 }
4722
4723 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4724
4725 for (i = 0; i < irk_count; i++) {
4726 struct mgmt_irk_info *key = &cp->irks[i];
4727
4728 if (!irk_is_valid(key))
4729 return cmd_status(sk, hdev->id,
4730 MGMT_OP_LOAD_IRKS,
4731 MGMT_STATUS_INVALID_PARAMS);
4732 }
4733
4734 hci_dev_lock(hdev);
4735
4736 hci_smp_irks_clear(hdev);
4737
4738 for (i = 0; i < irk_count; i++) {
4739 struct mgmt_irk_info *irk = &cp->irks[i];
4740 u8 addr_type;
4741
4742 if (irk->addr.type == BDADDR_LE_PUBLIC)
4743 addr_type = ADDR_LE_DEV_PUBLIC;
4744 else
4745 addr_type = ADDR_LE_DEV_RANDOM;
4746
4747 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4748 BDADDR_ANY);
4749 }
4750
4751 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4752
4753 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4754
4755 hci_dev_unlock(hdev);
4756
4757 return err;
4758}
4759
Johan Hedberg3f706b72013-01-20 14:27:16 +02004760static bool ltk_is_valid(struct mgmt_ltk_info *key)
4761{
4762 if (key->master != 0x00 && key->master != 0x01)
4763 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004764
4765 switch (key->addr.type) {
4766 case BDADDR_LE_PUBLIC:
4767 return true;
4768
4769 case BDADDR_LE_RANDOM:
4770 /* Two most significant bits shall be set */
4771 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4772 return false;
4773 return true;
4774 }
4775
4776 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004777}
4778
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004779static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004780 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004781{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004782 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004783 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4784 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004785 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004786 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004787
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004788 BT_DBG("request for %s", hdev->name);
4789
4790 if (!lmp_le_capable(hdev))
4791 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4792 MGMT_STATUS_NOT_SUPPORTED);
4793
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004794 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004795 if (key_count > max_key_count) {
4796 BT_ERR("load_ltks: too big key_count value %u", key_count);
4797 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4798 MGMT_STATUS_INVALID_PARAMS);
4799 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004800
4801 expected_len = sizeof(*cp) + key_count *
4802 sizeof(struct mgmt_ltk_info);
4803 if (expected_len != len) {
4804 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004805 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004806 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004807 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004808 }
4809
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004810 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004811
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004812 for (i = 0; i < key_count; i++) {
4813 struct mgmt_ltk_info *key = &cp->keys[i];
4814
Johan Hedberg3f706b72013-01-20 14:27:16 +02004815 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004816 return cmd_status(sk, hdev->id,
4817 MGMT_OP_LOAD_LONG_TERM_KEYS,
4818 MGMT_STATUS_INVALID_PARAMS);
4819 }
4820
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004821 hci_dev_lock(hdev);
4822
4823 hci_smp_ltks_clear(hdev);
4824
4825 for (i = 0; i < key_count; i++) {
4826 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004827 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004828
4829 if (key->addr.type == BDADDR_LE_PUBLIC)
4830 addr_type = ADDR_LE_DEV_PUBLIC;
4831 else
4832 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004833
4834 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004835 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004836 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004837 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004838
Johan Hedberg61b43352014-05-29 19:36:53 +03004839 switch (key->type) {
4840 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004841 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004842 break;
4843 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004844 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004845 break;
4846 default:
4847 continue;
4848 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004849
Johan Hedberg35d70272014-02-19 14:57:47 +02004850 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004851 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004852 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004853 }
4854
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004855 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4856 NULL, 0);
4857
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004858 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004859
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004860 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004861}
4862
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004863struct cmd_conn_lookup {
4864 struct hci_conn *conn;
4865 bool valid_tx_power;
4866 u8 mgmt_status;
4867};
4868
4869static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4870{
4871 struct cmd_conn_lookup *match = data;
4872 struct mgmt_cp_get_conn_info *cp;
4873 struct mgmt_rp_get_conn_info rp;
4874 struct hci_conn *conn = cmd->user_data;
4875
4876 if (conn != match->conn)
4877 return;
4878
4879 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4880
4881 memset(&rp, 0, sizeof(rp));
4882 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4883 rp.addr.type = cp->addr.type;
4884
4885 if (!match->mgmt_status) {
4886 rp.rssi = conn->rssi;
4887
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004888 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004889 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004890 rp.max_tx_power = conn->max_tx_power;
4891 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004892 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004893 rp.max_tx_power = HCI_TX_POWER_INVALID;
4894 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004895 }
4896
4897 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4898 match->mgmt_status, &rp, sizeof(rp));
4899
4900 hci_conn_drop(conn);
4901
4902 mgmt_pending_remove(cmd);
4903}
4904
4905static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4906{
4907 struct hci_cp_read_rssi *cp;
4908 struct hci_conn *conn;
4909 struct cmd_conn_lookup match;
4910 u16 handle;
4911
4912 BT_DBG("status 0x%02x", status);
4913
4914 hci_dev_lock(hdev);
4915
4916 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004917 * otherwise we assume it's not valid. At the moment we assume that
4918 * either both or none of current and max values are valid to keep code
4919 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004920 */
4921 match.valid_tx_power = !status;
4922
4923 /* Commands sent in request are either Read RSSI or Read Transmit Power
4924 * Level so we check which one was last sent to retrieve connection
4925 * handle. Both commands have handle as first parameter so it's safe to
4926 * cast data on the same command struct.
4927 *
4928 * First command sent is always Read RSSI and we fail only if it fails.
4929 * In other case we simply override error to indicate success as we
4930 * already remembered if TX power value is actually valid.
4931 */
4932 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4933 if (!cp) {
4934 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4935 status = 0;
4936 }
4937
4938 if (!cp) {
4939 BT_ERR("invalid sent_cmd in response");
4940 goto unlock;
4941 }
4942
4943 handle = __le16_to_cpu(cp->handle);
4944 conn = hci_conn_hash_lookup_handle(hdev, handle);
4945 if (!conn) {
4946 BT_ERR("unknown handle (%d) in response", handle);
4947 goto unlock;
4948 }
4949
4950 match.conn = conn;
4951 match.mgmt_status = mgmt_status(status);
4952
4953 /* Cache refresh is complete, now reply for mgmt request for given
4954 * connection only.
4955 */
4956 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4957 get_conn_info_complete, &match);
4958
4959unlock:
4960 hci_dev_unlock(hdev);
4961}
4962
4963static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4964 u16 len)
4965{
4966 struct mgmt_cp_get_conn_info *cp = data;
4967 struct mgmt_rp_get_conn_info rp;
4968 struct hci_conn *conn;
4969 unsigned long conn_info_age;
4970 int err = 0;
4971
4972 BT_DBG("%s", hdev->name);
4973
4974 memset(&rp, 0, sizeof(rp));
4975 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4976 rp.addr.type = cp->addr.type;
4977
4978 if (!bdaddr_type_is_valid(cp->addr.type))
4979 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4980 MGMT_STATUS_INVALID_PARAMS,
4981 &rp, sizeof(rp));
4982
4983 hci_dev_lock(hdev);
4984
4985 if (!hdev_is_powered(hdev)) {
4986 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4987 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4988 goto unlock;
4989 }
4990
4991 if (cp->addr.type == BDADDR_BREDR)
4992 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4993 &cp->addr.bdaddr);
4994 else
4995 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4996
4997 if (!conn || conn->state != BT_CONNECTED) {
4998 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4999 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5000 goto unlock;
5001 }
5002
5003 /* To avoid client trying to guess when to poll again for information we
5004 * calculate conn info age as random value between min/max set in hdev.
5005 */
5006 conn_info_age = hdev->conn_info_min_age +
5007 prandom_u32_max(hdev->conn_info_max_age -
5008 hdev->conn_info_min_age);
5009
5010 /* Query controller to refresh cached values if they are too old or were
5011 * never read.
5012 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005013 if (time_after(jiffies, conn->conn_info_timestamp +
5014 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005015 !conn->conn_info_timestamp) {
5016 struct hci_request req;
5017 struct hci_cp_read_tx_power req_txp_cp;
5018 struct hci_cp_read_rssi req_rssi_cp;
5019 struct pending_cmd *cmd;
5020
5021 hci_req_init(&req, hdev);
5022 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5023 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5024 &req_rssi_cp);
5025
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005026 /* For LE links TX power does not change thus we don't need to
5027 * query for it once value is known.
5028 */
5029 if (!bdaddr_type_is_le(cp->addr.type) ||
5030 conn->tx_power == HCI_TX_POWER_INVALID) {
5031 req_txp_cp.handle = cpu_to_le16(conn->handle);
5032 req_txp_cp.type = 0x00;
5033 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5034 sizeof(req_txp_cp), &req_txp_cp);
5035 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005036
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005037 /* Max TX power needs to be read only once per connection */
5038 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5039 req_txp_cp.handle = cpu_to_le16(conn->handle);
5040 req_txp_cp.type = 0x01;
5041 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5042 sizeof(req_txp_cp), &req_txp_cp);
5043 }
5044
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005045 err = hci_req_run(&req, conn_info_refresh_complete);
5046 if (err < 0)
5047 goto unlock;
5048
5049 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5050 data, len);
5051 if (!cmd) {
5052 err = -ENOMEM;
5053 goto unlock;
5054 }
5055
5056 hci_conn_hold(conn);
5057 cmd->user_data = conn;
5058
5059 conn->conn_info_timestamp = jiffies;
5060 } else {
5061 /* Cache is valid, just reply with values cached in hci_conn */
5062 rp.rssi = conn->rssi;
5063 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005064 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005065
5066 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5067 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5068 }
5069
5070unlock:
5071 hci_dev_unlock(hdev);
5072 return err;
5073}
5074
Johan Hedberg95868422014-06-28 17:54:07 +03005075static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5076{
5077 struct mgmt_cp_get_clock_info *cp;
5078 struct mgmt_rp_get_clock_info rp;
5079 struct hci_cp_read_clock *hci_cp;
5080 struct pending_cmd *cmd;
5081 struct hci_conn *conn;
5082
5083 BT_DBG("%s status %u", hdev->name, status);
5084
5085 hci_dev_lock(hdev);
5086
5087 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5088 if (!hci_cp)
5089 goto unlock;
5090
5091 if (hci_cp->which) {
5092 u16 handle = __le16_to_cpu(hci_cp->handle);
5093 conn = hci_conn_hash_lookup_handle(hdev, handle);
5094 } else {
5095 conn = NULL;
5096 }
5097
5098 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5099 if (!cmd)
5100 goto unlock;
5101
5102 cp = cmd->param;
5103
5104 memset(&rp, 0, sizeof(rp));
5105 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5106
5107 if (status)
5108 goto send_rsp;
5109
5110 rp.local_clock = cpu_to_le32(hdev->clock);
5111
5112 if (conn) {
5113 rp.piconet_clock = cpu_to_le32(conn->clock);
5114 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5115 }
5116
5117send_rsp:
5118 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5119 &rp, sizeof(rp));
5120 mgmt_pending_remove(cmd);
5121 if (conn)
5122 hci_conn_drop(conn);
5123
5124unlock:
5125 hci_dev_unlock(hdev);
5126}
5127
5128static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5129 u16 len)
5130{
5131 struct mgmt_cp_get_clock_info *cp = data;
5132 struct mgmt_rp_get_clock_info rp;
5133 struct hci_cp_read_clock hci_cp;
5134 struct pending_cmd *cmd;
5135 struct hci_request req;
5136 struct hci_conn *conn;
5137 int err;
5138
5139 BT_DBG("%s", hdev->name);
5140
5141 memset(&rp, 0, sizeof(rp));
5142 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5143 rp.addr.type = cp->addr.type;
5144
5145 if (cp->addr.type != BDADDR_BREDR)
5146 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5147 MGMT_STATUS_INVALID_PARAMS,
5148 &rp, sizeof(rp));
5149
5150 hci_dev_lock(hdev);
5151
5152 if (!hdev_is_powered(hdev)) {
5153 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5154 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5155 goto unlock;
5156 }
5157
5158 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5159 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5160 &cp->addr.bdaddr);
5161 if (!conn || conn->state != BT_CONNECTED) {
5162 err = cmd_complete(sk, hdev->id,
5163 MGMT_OP_GET_CLOCK_INFO,
5164 MGMT_STATUS_NOT_CONNECTED,
5165 &rp, sizeof(rp));
5166 goto unlock;
5167 }
5168 } else {
5169 conn = NULL;
5170 }
5171
5172 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5173 if (!cmd) {
5174 err = -ENOMEM;
5175 goto unlock;
5176 }
5177
5178 hci_req_init(&req, hdev);
5179
5180 memset(&hci_cp, 0, sizeof(hci_cp));
5181 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5182
5183 if (conn) {
5184 hci_conn_hold(conn);
5185 cmd->user_data = conn;
5186
5187 hci_cp.handle = cpu_to_le16(conn->handle);
5188 hci_cp.which = 0x01; /* Piconet clock */
5189 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5190 }
5191
5192 err = hci_req_run(&req, get_clock_info_complete);
5193 if (err < 0)
5194 mgmt_pending_remove(cmd);
5195
5196unlock:
5197 hci_dev_unlock(hdev);
5198 return err;
5199}
5200
Marcel Holtmann8afef092014-06-29 22:28:34 +02005201static void device_added(struct sock *sk, struct hci_dev *hdev,
5202 bdaddr_t *bdaddr, u8 type, u8 action)
5203{
5204 struct mgmt_ev_device_added ev;
5205
5206 bacpy(&ev.addr.bdaddr, bdaddr);
5207 ev.addr.type = type;
5208 ev.action = action;
5209
5210 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5211}
5212
Marcel Holtmann2faade52014-06-29 19:44:03 +02005213static int add_device(struct sock *sk, struct hci_dev *hdev,
5214 void *data, u16 len)
5215{
5216 struct mgmt_cp_add_device *cp = data;
5217 u8 auto_conn, addr_type;
5218 int err;
5219
5220 BT_DBG("%s", hdev->name);
5221
Johan Hedberg66593582014-07-09 12:59:14 +03005222 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005223 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5224 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5225 MGMT_STATUS_INVALID_PARAMS,
5226 &cp->addr, sizeof(cp->addr));
5227
5228 if (cp->action != 0x00 && cp->action != 0x01)
5229 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5230 MGMT_STATUS_INVALID_PARAMS,
5231 &cp->addr, sizeof(cp->addr));
5232
5233 hci_dev_lock(hdev);
5234
Johan Hedberg66593582014-07-09 12:59:14 +03005235 if (cp->addr.type == BDADDR_BREDR) {
5236 /* Only "connect" action supported for now */
5237 if (cp->action != 0x01) {
5238 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5239 MGMT_STATUS_INVALID_PARAMS,
5240 &cp->addr, sizeof(cp->addr));
5241 goto unlock;
5242 }
5243
5244 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5245 cp->addr.type);
5246 if (err)
5247 goto unlock;
5248 goto added;
5249 }
5250
Marcel Holtmann2faade52014-06-29 19:44:03 +02005251 if (cp->addr.type == BDADDR_LE_PUBLIC)
5252 addr_type = ADDR_LE_DEV_PUBLIC;
5253 else
5254 addr_type = ADDR_LE_DEV_RANDOM;
5255
5256 if (cp->action)
5257 auto_conn = HCI_AUTO_CONN_ALWAYS;
5258 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005259 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005260
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005261 /* If the connection parameters don't exist for this device,
5262 * they will be created and configured with defaults.
5263 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005264 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5265 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005266 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5267 MGMT_STATUS_FAILED,
5268 &cp->addr, sizeof(cp->addr));
5269 goto unlock;
5270 }
5271
Johan Hedberg66593582014-07-09 12:59:14 +03005272added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005273 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5274
Marcel Holtmann2faade52014-06-29 19:44:03 +02005275 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5276 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5277
5278unlock:
5279 hci_dev_unlock(hdev);
5280 return err;
5281}
5282
Marcel Holtmann8afef092014-06-29 22:28:34 +02005283static void device_removed(struct sock *sk, struct hci_dev *hdev,
5284 bdaddr_t *bdaddr, u8 type)
5285{
5286 struct mgmt_ev_device_removed ev;
5287
5288 bacpy(&ev.addr.bdaddr, bdaddr);
5289 ev.addr.type = type;
5290
5291 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5292}
5293
Marcel Holtmann2faade52014-06-29 19:44:03 +02005294static int remove_device(struct sock *sk, struct hci_dev *hdev,
5295 void *data, u16 len)
5296{
5297 struct mgmt_cp_remove_device *cp = data;
5298 int err;
5299
5300 BT_DBG("%s", hdev->name);
5301
5302 hci_dev_lock(hdev);
5303
5304 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005305 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005306 u8 addr_type;
5307
Johan Hedberg66593582014-07-09 12:59:14 +03005308 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005309 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5310 MGMT_STATUS_INVALID_PARAMS,
5311 &cp->addr, sizeof(cp->addr));
5312 goto unlock;
5313 }
5314
Johan Hedberg66593582014-07-09 12:59:14 +03005315 if (cp->addr.type == BDADDR_BREDR) {
5316 err = hci_bdaddr_list_del(&hdev->whitelist,
5317 &cp->addr.bdaddr,
5318 cp->addr.type);
5319 if (err) {
5320 err = cmd_complete(sk, hdev->id,
5321 MGMT_OP_REMOVE_DEVICE,
5322 MGMT_STATUS_INVALID_PARAMS,
5323 &cp->addr, sizeof(cp->addr));
5324 goto unlock;
5325 }
5326
5327 device_removed(sk, hdev, &cp->addr.bdaddr,
5328 cp->addr.type);
5329 goto complete;
5330 }
5331
Marcel Holtmann2faade52014-06-29 19:44:03 +02005332 if (cp->addr.type == BDADDR_LE_PUBLIC)
5333 addr_type = ADDR_LE_DEV_PUBLIC;
5334 else
5335 addr_type = ADDR_LE_DEV_RANDOM;
5336
Johan Hedbergc71593d2014-07-02 17:37:28 +03005337 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5338 addr_type);
5339 if (!params) {
5340 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5341 MGMT_STATUS_INVALID_PARAMS,
5342 &cp->addr, sizeof(cp->addr));
5343 goto unlock;
5344 }
5345
5346 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5347 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5348 MGMT_STATUS_INVALID_PARAMS,
5349 &cp->addr, sizeof(cp->addr));
5350 goto unlock;
5351 }
5352
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005353 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005354 list_del(&params->list);
5355 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005356 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005357
5358 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005359 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005360 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005361 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005362
Marcel Holtmann2faade52014-06-29 19:44:03 +02005363 if (cp->addr.type) {
5364 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5365 MGMT_STATUS_INVALID_PARAMS,
5366 &cp->addr, sizeof(cp->addr));
5367 goto unlock;
5368 }
5369
Johan Hedberg66593582014-07-09 12:59:14 +03005370 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5371 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5372 list_del(&b->list);
5373 kfree(b);
5374 }
5375
Johan Hedberg19de0822014-07-06 13:06:51 +03005376 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5377 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5378 continue;
5379 device_removed(sk, hdev, &p->addr, p->addr_type);
5380 list_del(&p->action);
5381 list_del(&p->list);
5382 kfree(p);
5383 }
5384
5385 BT_DBG("All LE connection parameters were removed");
5386
5387 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005388 }
5389
Johan Hedberg66593582014-07-09 12:59:14 +03005390complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005391 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5392 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5393
5394unlock:
5395 hci_dev_unlock(hdev);
5396 return err;
5397}
5398
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005399static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5400 u16 len)
5401{
5402 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005403 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5404 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005405 u16 param_count, expected_len;
5406 int i;
5407
5408 if (!lmp_le_capable(hdev))
5409 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5410 MGMT_STATUS_NOT_SUPPORTED);
5411
5412 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005413 if (param_count > max_param_count) {
5414 BT_ERR("load_conn_param: too big param_count value %u",
5415 param_count);
5416 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5417 MGMT_STATUS_INVALID_PARAMS);
5418 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005419
5420 expected_len = sizeof(*cp) + param_count *
5421 sizeof(struct mgmt_conn_param);
5422 if (expected_len != len) {
5423 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5424 expected_len, len);
5425 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5426 MGMT_STATUS_INVALID_PARAMS);
5427 }
5428
5429 BT_DBG("%s param_count %u", hdev->name, param_count);
5430
5431 hci_dev_lock(hdev);
5432
5433 hci_conn_params_clear_disabled(hdev);
5434
5435 for (i = 0; i < param_count; i++) {
5436 struct mgmt_conn_param *param = &cp->params[i];
5437 struct hci_conn_params *hci_param;
5438 u16 min, max, latency, timeout;
5439 u8 addr_type;
5440
5441 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5442 param->addr.type);
5443
5444 if (param->addr.type == BDADDR_LE_PUBLIC) {
5445 addr_type = ADDR_LE_DEV_PUBLIC;
5446 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5447 addr_type = ADDR_LE_DEV_RANDOM;
5448 } else {
5449 BT_ERR("Ignoring invalid connection parameters");
5450 continue;
5451 }
5452
5453 min = le16_to_cpu(param->min_interval);
5454 max = le16_to_cpu(param->max_interval);
5455 latency = le16_to_cpu(param->latency);
5456 timeout = le16_to_cpu(param->timeout);
5457
5458 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5459 min, max, latency, timeout);
5460
5461 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5462 BT_ERR("Ignoring invalid connection parameters");
5463 continue;
5464 }
5465
5466 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5467 addr_type);
5468 if (!hci_param) {
5469 BT_ERR("Failed to add connection parameters");
5470 continue;
5471 }
5472
5473 hci_param->conn_min_interval = min;
5474 hci_param->conn_max_interval = max;
5475 hci_param->conn_latency = latency;
5476 hci_param->supervision_timeout = timeout;
5477 }
5478
5479 hci_dev_unlock(hdev);
5480
5481 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5482}
5483
Marcel Holtmanndbece372014-07-04 18:11:55 +02005484static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5485 void *data, u16 len)
5486{
5487 struct mgmt_cp_set_external_config *cp = data;
5488 bool changed;
5489 int err;
5490
5491 BT_DBG("%s", hdev->name);
5492
5493 if (hdev_is_powered(hdev))
5494 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5495 MGMT_STATUS_REJECTED);
5496
5497 if (cp->config != 0x00 && cp->config != 0x01)
5498 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5499 MGMT_STATUS_INVALID_PARAMS);
5500
5501 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5502 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5503 MGMT_STATUS_NOT_SUPPORTED);
5504
5505 hci_dev_lock(hdev);
5506
5507 if (cp->config)
5508 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5509 &hdev->dev_flags);
5510 else
5511 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5512 &hdev->dev_flags);
5513
5514 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5515 if (err < 0)
5516 goto unlock;
5517
5518 if (!changed)
5519 goto unlock;
5520
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005521 err = new_options(hdev, sk);
5522
Marcel Holtmanndbece372014-07-04 18:11:55 +02005523 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5524 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005525
5526 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5527 set_bit(HCI_CONFIG, &hdev->dev_flags);
5528 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5529
5530 queue_work(hdev->req_workqueue, &hdev->power_on);
5531 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005532 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005533 mgmt_index_added(hdev);
5534 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005535 }
5536
5537unlock:
5538 hci_dev_unlock(hdev);
5539 return err;
5540}
5541
Marcel Holtmann9713c172014-07-06 12:11:15 +02005542static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5543 void *data, u16 len)
5544{
5545 struct mgmt_cp_set_public_address *cp = data;
5546 bool changed;
5547 int err;
5548
5549 BT_DBG("%s", hdev->name);
5550
5551 if (hdev_is_powered(hdev))
5552 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5553 MGMT_STATUS_REJECTED);
5554
5555 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5556 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5557 MGMT_STATUS_INVALID_PARAMS);
5558
5559 if (!hdev->set_bdaddr)
5560 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5561 MGMT_STATUS_NOT_SUPPORTED);
5562
5563 hci_dev_lock(hdev);
5564
5565 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5566 bacpy(&hdev->public_addr, &cp->bdaddr);
5567
5568 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5569 if (err < 0)
5570 goto unlock;
5571
5572 if (!changed)
5573 goto unlock;
5574
5575 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5576 err = new_options(hdev, sk);
5577
5578 if (is_configured(hdev)) {
5579 mgmt_index_removed(hdev);
5580
5581 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5582
5583 set_bit(HCI_CONFIG, &hdev->dev_flags);
5584 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5585
5586 queue_work(hdev->req_workqueue, &hdev->power_on);
5587 }
5588
5589unlock:
5590 hci_dev_unlock(hdev);
5591 return err;
5592}
5593
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005594static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005595 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5596 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005597 bool var_len;
5598 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005599} mgmt_handlers[] = {
5600 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005601 { read_version, false, MGMT_READ_VERSION_SIZE },
5602 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5603 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5604 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5605 { set_powered, false, MGMT_SETTING_SIZE },
5606 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5607 { set_connectable, false, MGMT_SETTING_SIZE },
5608 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5609 { set_pairable, false, MGMT_SETTING_SIZE },
5610 { set_link_security, false, MGMT_SETTING_SIZE },
5611 { set_ssp, false, MGMT_SETTING_SIZE },
5612 { set_hs, false, MGMT_SETTING_SIZE },
5613 { set_le, false, MGMT_SETTING_SIZE },
5614 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5615 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5616 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5617 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5618 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5619 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5620 { disconnect, false, MGMT_DISCONNECT_SIZE },
5621 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5622 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5623 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5624 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5625 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5626 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5627 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5628 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5629 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5630 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5631 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5632 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005633 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005634 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5635 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5636 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5637 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5638 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5639 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005640 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005641 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005642 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005643 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005644 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005645 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005646 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005647 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005648 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005649 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005650 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005651 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5652 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005653 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5654 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005655 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005656 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005657 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005658};
5659
Johan Hedberg03811012010-12-08 00:21:06 +02005660int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5661{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005662 void *buf;
5663 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005664 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005665 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005666 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005667 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005668 int err;
5669
5670 BT_DBG("got %zu bytes", msglen);
5671
5672 if (msglen < sizeof(*hdr))
5673 return -EINVAL;
5674
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005675 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005676 if (!buf)
5677 return -ENOMEM;
5678
5679 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5680 err = -EFAULT;
5681 goto done;
5682 }
5683
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005684 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005685 opcode = __le16_to_cpu(hdr->opcode);
5686 index = __le16_to_cpu(hdr->index);
5687 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005688
5689 if (len != msglen - sizeof(*hdr)) {
5690 err = -EINVAL;
5691 goto done;
5692 }
5693
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005694 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005695 hdev = hci_dev_get(index);
5696 if (!hdev) {
5697 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005698 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005699 goto done;
5700 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005701
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005702 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005703 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005704 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005705 err = cmd_status(sk, index, opcode,
5706 MGMT_STATUS_INVALID_INDEX);
5707 goto done;
5708 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005709
5710 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005711 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005712 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5713 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005714 err = cmd_status(sk, index, opcode,
5715 MGMT_STATUS_INVALID_INDEX);
5716 goto done;
5717 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005718 }
5719
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005720 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005721 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005722 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005723 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005724 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005725 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005726 }
5727
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005728 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5729 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5730 err = cmd_status(sk, index, opcode,
5731 MGMT_STATUS_INVALID_INDEX);
5732 goto done;
5733 }
5734
5735 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5736 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005737 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005738 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005739 goto done;
5740 }
5741
Johan Hedbergbe22b542012-03-01 22:24:41 +02005742 handler = &mgmt_handlers[opcode];
5743
5744 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005745 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005746 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005747 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005748 goto done;
5749 }
5750
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005751 if (hdev)
5752 mgmt_init_hdev(sk, hdev);
5753
5754 cp = buf + sizeof(*hdr);
5755
Johan Hedbergbe22b542012-03-01 22:24:41 +02005756 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005757 if (err < 0)
5758 goto done;
5759
Johan Hedberg03811012010-12-08 00:21:06 +02005760 err = msglen;
5761
5762done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005763 if (hdev)
5764 hci_dev_put(hdev);
5765
Johan Hedberg03811012010-12-08 00:21:06 +02005766 kfree(buf);
5767 return err;
5768}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005769
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005770void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005771{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005772 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005773 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005774
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005775 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5776 return;
5777
5778 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5779 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5780 else
5781 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005782}
5783
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005784void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005785{
Johan Hedberg5f159032012-03-02 03:13:19 +02005786 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005787
Marcel Holtmann1514b892013-10-06 08:25:01 -07005788 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005789 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005790
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005791 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5792 return;
5793
Johan Hedberg744cf192011-11-08 20:40:14 +02005794 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005795
Marcel Holtmannedd38962014-07-02 21:30:55 +02005796 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5797 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5798 else
5799 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005800}
5801
Andre Guedes6046dc32014-02-26 20:21:51 -03005802/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005803static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005804{
5805 struct hci_conn_params *p;
5806
5807 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005808 /* Needed for AUTO_OFF case where might not "really"
5809 * have been powered off.
5810 */
5811 list_del_init(&p->action);
5812
5813 switch (p->auto_connect) {
5814 case HCI_AUTO_CONN_ALWAYS:
5815 list_add(&p->action, &hdev->pend_le_conns);
5816 break;
5817 case HCI_AUTO_CONN_REPORT:
5818 list_add(&p->action, &hdev->pend_le_reports);
5819 break;
5820 default:
5821 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005822 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005823 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005824
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005825 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005826}
5827
Johan Hedberg229ab392013-03-15 17:06:53 -05005828static void powered_complete(struct hci_dev *hdev, u8 status)
5829{
5830 struct cmd_lookup match = { NULL, hdev };
5831
5832 BT_DBG("status 0x%02x", status);
5833
5834 hci_dev_lock(hdev);
5835
Johan Hedbergd7347f32014-07-04 12:37:23 +03005836 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005837
Johan Hedberg229ab392013-03-15 17:06:53 -05005838 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5839
5840 new_settings(hdev, match.sk);
5841
5842 hci_dev_unlock(hdev);
5843
5844 if (match.sk)
5845 sock_put(match.sk);
5846}
5847
Johan Hedberg70da6242013-03-15 17:06:51 -05005848static int powered_update_hci(struct hci_dev *hdev)
5849{
Johan Hedberg890ea892013-03-15 17:06:52 -05005850 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005851 u8 link_sec;
5852
Johan Hedberg890ea892013-03-15 17:06:52 -05005853 hci_req_init(&req, hdev);
5854
Johan Hedberg70da6242013-03-15 17:06:51 -05005855 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5856 !lmp_host_ssp_capable(hdev)) {
5857 u8 ssp = 1;
5858
Johan Hedberg890ea892013-03-15 17:06:52 -05005859 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005860 }
5861
Johan Hedbergc73eee92013-04-19 18:35:21 +03005862 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5863 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005864 struct hci_cp_write_le_host_supported cp;
5865
5866 cp.le = 1;
5867 cp.simul = lmp_le_br_capable(hdev);
5868
5869 /* Check first if we already have the right
5870 * host state (host features set)
5871 */
5872 if (cp.le != lmp_host_le_capable(hdev) ||
5873 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005874 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5875 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005876 }
5877
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005878 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005879 /* Make sure the controller has a good default for
5880 * advertising data. This also applies to the case
5881 * where BR/EDR was toggled during the AUTO_OFF phase.
5882 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005883 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005884 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005885 update_scan_rsp_data(&req);
5886 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005887
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005888 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5889 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005890 }
5891
Johan Hedberg70da6242013-03-15 17:06:51 -05005892 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5893 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005894 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5895 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005896
5897 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005898 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5899 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005900 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005901 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005902 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005903 }
5904
Johan Hedberg229ab392013-03-15 17:06:53 -05005905 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005906}
5907
Johan Hedberg744cf192011-11-08 20:40:14 +02005908int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005909{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005910 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005911 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5912 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005913 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005914
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005915 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5916 return 0;
5917
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005918 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005919 if (powered_update_hci(hdev) == 0)
5920 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005921
Johan Hedberg229ab392013-03-15 17:06:53 -05005922 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5923 &match);
5924 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005925 }
5926
Johan Hedberg229ab392013-03-15 17:06:53 -05005927 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5928 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5929
5930 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5931 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5932 zero_cod, sizeof(zero_cod), NULL);
5933
5934new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005935 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005936
5937 if (match.sk)
5938 sock_put(match.sk);
5939
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005940 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005941}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005942
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005943void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005944{
5945 struct pending_cmd *cmd;
5946 u8 status;
5947
5948 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5949 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005950 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005951
5952 if (err == -ERFKILL)
5953 status = MGMT_STATUS_RFKILLED;
5954 else
5955 status = MGMT_STATUS_FAILED;
5956
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005957 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005958
5959 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005960}
5961
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005962void mgmt_discoverable_timeout(struct hci_dev *hdev)
5963{
5964 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005965
5966 hci_dev_lock(hdev);
5967
5968 /* When discoverable timeout triggers, then just make sure
5969 * the limited discoverable flag is cleared. Even in the case
5970 * of a timeout triggered from general discoverable, it is
5971 * safe to unconditionally clear the flag.
5972 */
5973 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005974 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005975
5976 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005977 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5978 u8 scan = SCAN_PAGE;
5979 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5980 sizeof(scan), &scan);
5981 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005982 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005983 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005984 hci_req_run(&req, NULL);
5985
5986 hdev->discov_timeout = 0;
5987
Johan Hedberg9a43e252013-10-20 19:00:07 +03005988 new_settings(hdev, NULL);
5989
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005990 hci_dev_unlock(hdev);
5991}
5992
Marcel Holtmann86a75642013-10-15 06:33:54 -07005993void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005994{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005995 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005996
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005997 /* Nothing needed here if there's a pending command since that
5998 * commands request completion callback takes care of everything
5999 * necessary.
6000 */
6001 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07006002 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03006003
Johan Hedbergbd107992014-02-24 14:52:19 +02006004 /* Powering off may clear the scan mode - don't let that interfere */
6005 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
6006 return;
6007
Johan Hedberg9a43e252013-10-20 19:00:07 +03006008 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07006009 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006010 } else {
6011 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07006012 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006013 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02006014
Johan Hedberg9a43e252013-10-20 19:00:07 +03006015 if (changed) {
6016 struct hci_request req;
6017
6018 /* In case this change in discoverable was triggered by
6019 * a disabling of connectable there could be a need to
6020 * update the advertising flags.
6021 */
6022 hci_req_init(&req, hdev);
6023 update_adv_data(&req);
6024 hci_req_run(&req, NULL);
6025
Marcel Holtmann86a75642013-10-15 06:33:54 -07006026 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006027 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02006028}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006029
Marcel Holtmanna3309162013-10-15 06:33:55 -07006030void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006031{
Marcel Holtmanna3309162013-10-15 06:33:55 -07006032 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006033
Johan Hedbergd7b856f2013-10-14 16:20:04 +03006034 /* Nothing needed here if there's a pending command since that
6035 * commands request completion callback takes care of everything
6036 * necessary.
6037 */
6038 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07006039 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03006040
Johan Hedbergce3f24c2014-02-24 14:52:20 +02006041 /* Powering off may clear the scan mode - don't let that interfere */
6042 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
6043 return;
6044
Marcel Holtmanna3309162013-10-15 06:33:55 -07006045 if (connectable)
6046 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
6047 else
6048 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006049
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006050 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07006051 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006052}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006053
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07006054void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006055{
Johan Hedbergca69b792011-11-11 18:10:00 +02006056 u8 mgmt_err = mgmt_status(status);
6057
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006058 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02006059 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006060 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006061
6062 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02006063 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006064 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006065}
6066
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006067void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6068 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006069{
Johan Hedberg86742e12011-11-07 23:13:38 +02006070 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006071
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006072 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006073
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006074 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006075 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006076 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006077 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006078 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006079 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006080
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006081 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006082}
Johan Hedbergf7520542011-01-20 12:34:39 +02006083
Johan Hedbergd7b25452014-05-23 13:19:53 +03006084static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6085{
6086 if (ltk->authenticated)
6087 return MGMT_LTK_AUTHENTICATED;
6088
6089 return MGMT_LTK_UNAUTHENTICATED;
6090}
6091
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006092void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006093{
6094 struct mgmt_ev_new_long_term_key ev;
6095
6096 memset(&ev, 0, sizeof(ev));
6097
Marcel Holtmann5192d302014-02-19 17:11:58 -08006098 /* Devices using resolvable or non-resolvable random addresses
6099 * without providing an indentity resolving key don't require
6100 * to store long term keys. Their addresses will change the
6101 * next time around.
6102 *
6103 * Only when a remote device provides an identity address
6104 * make sure the long term key is stored. If the remote
6105 * identity is known, the long term keys are internally
6106 * mapped to the identity address. So allow static random
6107 * and public addresses here.
6108 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006109 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6110 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6111 ev.store_hint = 0x00;
6112 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006113 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006114
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006115 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006116 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006117 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006118 ev.key.enc_size = key->enc_size;
6119 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006120 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006121
Johan Hedberg2ceba532014-06-16 19:25:16 +03006122 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006123 ev.key.master = 1;
6124
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006125 memcpy(ev.key.val, key->val, sizeof(key->val));
6126
Marcel Holtmann083368f2013-10-15 14:26:29 -07006127 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006128}
6129
Johan Hedberg95fbac82014-02-19 15:18:31 +02006130void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6131{
6132 struct mgmt_ev_new_irk ev;
6133
6134 memset(&ev, 0, sizeof(ev));
6135
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006136 /* For identity resolving keys from devices that are already
6137 * using a public address or static random address, do not
6138 * ask for storing this key. The identity resolving key really
6139 * is only mandatory for devices using resovlable random
6140 * addresses.
6141 *
6142 * Storing all identity resolving keys has the downside that
6143 * they will be also loaded on next boot of they system. More
6144 * identity resolving keys, means more time during scanning is
6145 * needed to actually resolve these addresses.
6146 */
6147 if (bacmp(&irk->rpa, BDADDR_ANY))
6148 ev.store_hint = 0x01;
6149 else
6150 ev.store_hint = 0x00;
6151
Johan Hedberg95fbac82014-02-19 15:18:31 +02006152 bacpy(&ev.rpa, &irk->rpa);
6153 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6154 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6155 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6156
6157 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6158}
6159
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006160void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6161 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006162{
6163 struct mgmt_ev_new_csrk ev;
6164
6165 memset(&ev, 0, sizeof(ev));
6166
6167 /* Devices using resolvable or non-resolvable random addresses
6168 * without providing an indentity resolving key don't require
6169 * to store signature resolving keys. Their addresses will change
6170 * the next time around.
6171 *
6172 * Only when a remote device provides an identity address
6173 * make sure the signature resolving key is stored. So allow
6174 * static random and public addresses here.
6175 */
6176 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6177 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6178 ev.store_hint = 0x00;
6179 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006180 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006181
6182 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6183 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6184 ev.key.master = csrk->master;
6185 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6186
6187 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6188}
6189
Andre Guedesffb5a8272014-07-01 18:10:11 -03006190void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006191 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6192 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006193{
6194 struct mgmt_ev_new_conn_param ev;
6195
Johan Hedbergc103aea2014-07-02 17:37:34 +03006196 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6197 return;
6198
Andre Guedesffb5a8272014-07-01 18:10:11 -03006199 memset(&ev, 0, sizeof(ev));
6200 bacpy(&ev.addr.bdaddr, bdaddr);
6201 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006202 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006203 ev.min_interval = cpu_to_le16(min_interval);
6204 ev.max_interval = cpu_to_le16(max_interval);
6205 ev.latency = cpu_to_le16(latency);
6206 ev.timeout = cpu_to_le16(timeout);
6207
6208 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6209}
6210
Marcel Holtmann94933992013-10-15 10:26:39 -07006211static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6212 u8 data_len)
6213{
6214 eir[eir_len++] = sizeof(type) + data_len;
6215 eir[eir_len++] = type;
6216 memcpy(&eir[eir_len], data, data_len);
6217 eir_len += data_len;
6218
6219 return eir_len;
6220}
6221
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006222void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6223 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6224 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006225{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006226 char buf[512];
6227 struct mgmt_ev_device_connected *ev = (void *) buf;
6228 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006229
Johan Hedbergb644ba32012-01-17 21:48:47 +02006230 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006231 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006232
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006233 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006234
Johan Hedbergb644ba32012-01-17 21:48:47 +02006235 if (name_len > 0)
6236 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006237 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006238
6239 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006240 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006241 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006242
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006243 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006244
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006245 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6246 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006247}
6248
Johan Hedberg8962ee72011-01-20 12:40:27 +02006249static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6250{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006251 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006252 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006253 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006254
Johan Hedberg88c3df12012-02-09 14:27:38 +02006255 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6256 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006257
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006258 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006259 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006260
6261 *sk = cmd->sk;
6262 sock_hold(*sk);
6263
Johan Hedberga664b5b2011-02-19 12:06:02 -03006264 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006265}
6266
Johan Hedberg124f6e32012-02-09 13:50:12 +02006267static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006268{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006269 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006270 struct mgmt_cp_unpair_device *cp = cmd->param;
6271 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006272
6273 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006274 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6275 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006276
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006277 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6278
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006279 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006280
6281 mgmt_pending_remove(cmd);
6282}
6283
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006284void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006285 u8 link_type, u8 addr_type, u8 reason,
6286 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006287{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006288 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006289 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006290 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006291
Johan Hedberg8b064a32014-02-24 14:52:22 +02006292 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6293 if (power_off) {
6294 struct mgmt_mode *cp = power_off->param;
6295
6296 /* The connection is still in hci_conn_hash so test for 1
6297 * instead of 0 to know if this is the last one.
6298 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006299 if (!cp->val && hci_conn_count(hdev) == 1) {
6300 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006301 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006302 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006303 }
6304
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006305 if (!mgmt_connected)
6306 return;
6307
Andre Guedes57eb7762013-10-30 19:01:41 -03006308 if (link_type != ACL_LINK && link_type != LE_LINK)
6309 return;
6310
Johan Hedberg744cf192011-11-08 20:40:14 +02006311 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006312
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006313 bacpy(&ev.addr.bdaddr, bdaddr);
6314 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6315 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006316
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006317 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006318
6319 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006320 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006321
Johan Hedberg124f6e32012-02-09 13:50:12 +02006322 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006323 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006324}
6325
Marcel Holtmann78929242013-10-06 23:55:47 -07006326void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6327 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006328{
Andre Guedes3655bba2013-10-30 19:01:40 -03006329 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6330 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006331 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006332 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006333
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006334 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6335 hdev);
6336
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006337 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006338 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006339 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006340
Andre Guedes3655bba2013-10-30 19:01:40 -03006341 cp = cmd->param;
6342
6343 if (bacmp(bdaddr, &cp->addr.bdaddr))
6344 return;
6345
6346 if (cp->addr.type != bdaddr_type)
6347 return;
6348
Johan Hedberg88c3df12012-02-09 14:27:38 +02006349 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006350 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006351
Marcel Holtmann78929242013-10-06 23:55:47 -07006352 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6353 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006354
Johan Hedberga664b5b2011-02-19 12:06:02 -03006355 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006356}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006357
Marcel Holtmann445608d2013-10-06 23:55:48 -07006358void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6359 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006360{
6361 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006362 struct pending_cmd *power_off;
6363
6364 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6365 if (power_off) {
6366 struct mgmt_mode *cp = power_off->param;
6367
6368 /* The connection is still in hci_conn_hash so test for 1
6369 * instead of 0 to know if this is the last one.
6370 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006371 if (!cp->val && hci_conn_count(hdev) == 1) {
6372 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006373 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006374 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006375 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006376
Johan Hedberg4c659c32011-11-07 23:13:39 +02006377 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006378 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006379 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006380
Marcel Holtmann445608d2013-10-06 23:55:48 -07006381 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006382}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006383
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006384void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006385{
6386 struct mgmt_ev_pin_code_request ev;
6387
Johan Hedbergd8457692012-02-17 14:24:57 +02006388 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006389 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006390 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006391
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006392 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006393}
6394
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006395void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6396 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006397{
6398 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006399 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006400
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006401 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006402 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006403 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006404
Johan Hedbergd8457692012-02-17 14:24:57 +02006405 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006406 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006407
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006408 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6409 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006410
Johan Hedberga664b5b2011-02-19 12:06:02 -03006411 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006412}
6413
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006414void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6415 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006416{
6417 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006418 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006419
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006420 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006421 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006422 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006423
Johan Hedbergd8457692012-02-17 14:24:57 +02006424 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006425 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006426
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006427 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6428 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006429
Johan Hedberga664b5b2011-02-19 12:06:02 -03006430 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006431}
Johan Hedberga5c29682011-02-19 12:05:57 -03006432
Johan Hedberg744cf192011-11-08 20:40:14 +02006433int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006434 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006435 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006436{
6437 struct mgmt_ev_user_confirm_request ev;
6438
Johan Hedberg744cf192011-11-08 20:40:14 +02006439 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006440
Johan Hedberg272d90d2012-02-09 15:26:12 +02006441 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006442 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006443 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006444 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006445
Johan Hedberg744cf192011-11-08 20:40:14 +02006446 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006447 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006448}
6449
Johan Hedberg272d90d2012-02-09 15:26:12 +02006450int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006451 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006452{
6453 struct mgmt_ev_user_passkey_request ev;
6454
6455 BT_DBG("%s", hdev->name);
6456
Johan Hedberg272d90d2012-02-09 15:26:12 +02006457 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006458 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006459
6460 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006461 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006462}
6463
Brian Gix0df4c182011-11-16 13:53:13 -08006464static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006465 u8 link_type, u8 addr_type, u8 status,
6466 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006467{
6468 struct pending_cmd *cmd;
6469 struct mgmt_rp_user_confirm_reply rp;
6470 int err;
6471
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006472 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006473 if (!cmd)
6474 return -ENOENT;
6475
Johan Hedberg272d90d2012-02-09 15:26:12 +02006476 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006477 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006478 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006479 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006480
Johan Hedberga664b5b2011-02-19 12:06:02 -03006481 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006482
6483 return err;
6484}
6485
Johan Hedberg744cf192011-11-08 20:40:14 +02006486int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006487 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006488{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006489 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006490 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006491}
6492
Johan Hedberg272d90d2012-02-09 15:26:12 +02006493int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006494 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006495{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006496 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006497 status,
6498 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006499}
Johan Hedberg2a611692011-02-19 12:06:00 -03006500
Brian Gix604086b2011-11-23 08:28:33 -08006501int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006502 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006503{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006504 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006505 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006506}
6507
Johan Hedberg272d90d2012-02-09 15:26:12 +02006508int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006509 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006510{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006511 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006512 status,
6513 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006514}
6515
Johan Hedberg92a25252012-09-06 18:39:26 +03006516int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6517 u8 link_type, u8 addr_type, u32 passkey,
6518 u8 entered)
6519{
6520 struct mgmt_ev_passkey_notify ev;
6521
6522 BT_DBG("%s", hdev->name);
6523
6524 bacpy(&ev.addr.bdaddr, bdaddr);
6525 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6526 ev.passkey = __cpu_to_le32(passkey);
6527 ev.entered = entered;
6528
6529 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6530}
6531
Marcel Holtmanne5460992013-10-15 14:26:23 -07006532void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6533 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006534{
6535 struct mgmt_ev_auth_failed ev;
6536
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006537 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006538 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006539 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006540
Marcel Holtmanne5460992013-10-15 14:26:23 -07006541 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006542}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006543
Marcel Holtmann464996a2013-10-15 14:26:24 -07006544void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006545{
6546 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006547 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006548
6549 if (status) {
6550 u8 mgmt_err = mgmt_status(status);
6551 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006552 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006553 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006554 }
6555
Marcel Holtmann464996a2013-10-15 14:26:24 -07006556 if (test_bit(HCI_AUTH, &hdev->flags))
6557 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6558 &hdev->dev_flags);
6559 else
6560 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6561 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006562
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006563 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006564 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006565
Johan Hedberg47990ea2012-02-22 11:58:37 +02006566 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006567 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006568
6569 if (match.sk)
6570 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006571}
6572
Johan Hedberg890ea892013-03-15 17:06:52 -05006573static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006574{
Johan Hedberg890ea892013-03-15 17:06:52 -05006575 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006576 struct hci_cp_write_eir cp;
6577
Johan Hedberg976eb202012-10-24 21:12:01 +03006578 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006579 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006580
Johan Hedbergc80da272012-02-22 15:38:48 +02006581 memset(hdev->eir, 0, sizeof(hdev->eir));
6582
Johan Hedbergcacaf522012-02-21 00:52:42 +02006583 memset(&cp, 0, sizeof(cp));
6584
Johan Hedberg890ea892013-03-15 17:06:52 -05006585 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006586}
6587
Marcel Holtmann3e248562013-10-15 14:26:25 -07006588void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006589{
6590 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006591 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006592 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006593
6594 if (status) {
6595 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006596
6597 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006598 &hdev->dev_flags)) {
6599 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006600 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006601 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006602
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006603 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6604 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006605 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006606 }
6607
6608 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006609 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006610 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006611 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6612 if (!changed)
6613 changed = test_and_clear_bit(HCI_HS_ENABLED,
6614 &hdev->dev_flags);
6615 else
6616 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006617 }
6618
6619 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6620
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006621 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006622 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006623
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006624 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006625 sock_put(match.sk);
6626
Johan Hedberg890ea892013-03-15 17:06:52 -05006627 hci_req_init(&req, hdev);
6628
Johan Hedberg37699722014-06-24 14:00:27 +03006629 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6630 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6631 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6632 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006633 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006634 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006635 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006636 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006637
6638 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006639}
6640
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006641void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6642{
6643 struct cmd_lookup match = { NULL, hdev };
6644 bool changed = false;
6645
6646 if (status) {
6647 u8 mgmt_err = mgmt_status(status);
6648
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006649 if (enable) {
6650 if (test_and_clear_bit(HCI_SC_ENABLED,
6651 &hdev->dev_flags))
6652 new_settings(hdev, NULL);
6653 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6654 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006655
6656 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6657 cmd_status_rsp, &mgmt_err);
6658 return;
6659 }
6660
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006661 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006662 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006663 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006664 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006665 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6666 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006667
6668 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6669 settings_rsp, &match);
6670
6671 if (changed)
6672 new_settings(hdev, match.sk);
6673
6674 if (match.sk)
6675 sock_put(match.sk);
6676}
6677
Johan Hedberg92da6092013-03-15 17:06:55 -05006678static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006679{
6680 struct cmd_lookup *match = data;
6681
Johan Hedberg90e70452012-02-23 23:09:40 +02006682 if (match->sk == NULL) {
6683 match->sk = cmd->sk;
6684 sock_hold(match->sk);
6685 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006686}
6687
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006688void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6689 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006690{
Johan Hedberg90e70452012-02-23 23:09:40 +02006691 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006692
Johan Hedberg92da6092013-03-15 17:06:55 -05006693 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6694 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6695 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006696
6697 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006698 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6699 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006700
6701 if (match.sk)
6702 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006703}
6704
Marcel Holtmann7667da32013-10-15 14:26:27 -07006705void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006706{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006707 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006708 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006709
Johan Hedberg13928972013-03-15 17:07:00 -05006710 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006711 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006712
6713 memset(&ev, 0, sizeof(ev));
6714 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006715 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006716
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006717 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006718 if (!cmd) {
6719 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006720
Johan Hedberg13928972013-03-15 17:07:00 -05006721 /* If this is a HCI command related to powering on the
6722 * HCI dev don't send any mgmt signals.
6723 */
6724 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006725 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006726 }
6727
Marcel Holtmann7667da32013-10-15 14:26:27 -07006728 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6729 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006730}
Szymon Jancc35938b2011-03-22 13:12:21 +01006731
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006732void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6733 u8 *randomizer192, u8 *hash256,
6734 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006735{
6736 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006737
Johan Hedberg744cf192011-11-08 20:40:14 +02006738 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006739
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006740 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006741 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006742 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006743
6744 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006745 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6746 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006747 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006748 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6749 hash256 && randomizer256) {
6750 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006751
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006752 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6753 memcpy(rp.randomizer192, randomizer192,
6754 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006755
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006756 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6757 memcpy(rp.randomizer256, randomizer256,
6758 sizeof(rp.randomizer256));
6759
6760 cmd_complete(cmd->sk, hdev->id,
6761 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6762 &rp, sizeof(rp));
6763 } else {
6764 struct mgmt_rp_read_local_oob_data rp;
6765
6766 memcpy(rp.hash, hash192, sizeof(rp.hash));
6767 memcpy(rp.randomizer, randomizer192,
6768 sizeof(rp.randomizer));
6769
6770 cmd_complete(cmd->sk, hdev->id,
6771 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6772 &rp, sizeof(rp));
6773 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006774 }
6775
6776 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006777}
Johan Hedberge17acd42011-03-30 23:57:16 +03006778
Marcel Holtmann901801b2013-10-06 23:55:51 -07006779void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006780 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6781 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006782{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006783 char buf[512];
6784 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006785 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006786
Johan Hedberg75ce2082014-07-02 22:42:01 +03006787 /* Don't send events for a non-kernel initiated discovery. With
6788 * LE one exception is if we have pend_le_reports > 0 in which
6789 * case we're doing passive scanning and want these events.
6790 */
6791 if (!hci_discovery_active(hdev)) {
6792 if (link_type == ACL_LINK)
6793 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006794 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006795 return;
6796 }
Andre Guedes12602d02013-04-30 15:29:40 -03006797
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006798 /* Make sure that the buffer is big enough. The 5 extra bytes
6799 * are for the potential CoD field.
6800 */
6801 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006802 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006803
Johan Hedberg1dc06092012-01-15 21:01:23 +02006804 memset(buf, 0, sizeof(buf));
6805
Johan Hedberg841c5642014-07-07 12:45:54 +03006806 bacpy(&ev->addr.bdaddr, bdaddr);
6807 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006808 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006809 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006810
Johan Hedberg1dc06092012-01-15 21:01:23 +02006811 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006812 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006813
Johan Hedberg1dc06092012-01-15 21:01:23 +02006814 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6815 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006816 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006817
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006818 if (scan_rsp_len > 0)
6819 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6820
6821 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6822 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006823
Marcel Holtmann901801b2013-10-06 23:55:51 -07006824 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006825}
Johan Hedberga88a9652011-03-30 13:18:12 +03006826
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006827void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6828 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006829{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006830 struct mgmt_ev_device_found *ev;
6831 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6832 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006833
Johan Hedbergb644ba32012-01-17 21:48:47 +02006834 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006835
Johan Hedbergb644ba32012-01-17 21:48:47 +02006836 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006837
Johan Hedbergb644ba32012-01-17 21:48:47 +02006838 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006839 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006840 ev->rssi = rssi;
6841
6842 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006843 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006844
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006845 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006846
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006847 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006848}
Johan Hedberg314b2382011-04-27 10:29:57 -04006849
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006850void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006851{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006852 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006853 struct pending_cmd *cmd;
6854
Andre Guedes343fb142011-11-22 17:14:19 -03006855 BT_DBG("%s discovering %u", hdev->name, discovering);
6856
Johan Hedberg164a6e72011-11-01 17:06:44 +02006857 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006858 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006859 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006860 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006861
6862 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006863 u8 type = hdev->discovery.type;
6864
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006865 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6866 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006867 mgmt_pending_remove(cmd);
6868 }
6869
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006870 memset(&ev, 0, sizeof(ev));
6871 ev.type = hdev->discovery.type;
6872 ev.discovering = discovering;
6873
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006874 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006875}
Antti Julku5e762442011-08-25 16:48:02 +03006876
Marcel Holtmann5976e602013-10-06 04:08:14 -07006877static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6878{
6879 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006880}
6881
6882void mgmt_reenable_advertising(struct hci_dev *hdev)
6883{
6884 struct hci_request req;
6885
Marcel Holtmann5976e602013-10-06 04:08:14 -07006886 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6887 return;
6888
6889 hci_req_init(&req, hdev);
6890 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006891 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006892}