blob: 9cc7108f4c45f95a2dee5f2f5ce980dfdde5a9db [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 Holtmannedd3896b2014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200132#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
133 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
134
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135struct pending_cmd {
136 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200137 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100139 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b212012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b212012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b212012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b212012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200558
Andre Guedesed3fa312012-07-24 15:03:46 -0300559 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300560 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500561 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
562 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300563 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200580 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200582
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200583 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
584 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585 settings |= MGMT_SETTING_CONFIGURATION;
586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587 return settings;
588}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200589
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200590static u32 get_current_settings(struct hci_dev *hdev)
591{
592 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200593
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200594 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100595 settings |= MGMT_SETTING_POWERED;
596
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200597 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200598 settings |= MGMT_SETTING_CONNECTABLE;
599
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500600 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
601 settings |= MGMT_SETTING_FAST_CONNECTABLE;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_DISCOVERABLE;
605
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200606 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_PAIRABLE;
608
Johan Hedberg56f87902013-10-02 13:43:13 +0300609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_BREDR;
611
Johan Hedberg06199cf2012-02-22 16:37:11 +0200612 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200614
Johan Hedberg47990ea2012-02-22 11:58:37 +0200615 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200617
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200618 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200620
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200621 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
622 settings |= MGMT_SETTING_HS;
623
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200624 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300625 settings |= MGMT_SETTING_ADVERTISING;
626
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_SECURE_CONN;
629
Johan Hedberg0663b292014-06-24 13:15:50 +0300630 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800631 settings |= MGMT_SETTING_DEBUG_KEYS;
632
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200633 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
634 settings |= MGMT_SETTING_PRIVACY;
635
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200636 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200637}
638
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300639#define PNP_INFO_SVCLASS_ID 0x1200
640
Johan Hedberg213202e2013-01-27 00:31:33 +0200641static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
642{
643 u8 *ptr = data, *uuids_start = NULL;
644 struct bt_uuid *uuid;
645
646 if (len < 4)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 u16 uuid16;
651
652 if (uuid->size != 16)
653 continue;
654
655 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
656 if (uuid16 < 0x1100)
657 continue;
658
659 if (uuid16 == PNP_INFO_SVCLASS_ID)
660 continue;
661
662 if (!uuids_start) {
663 uuids_start = ptr;
664 uuids_start[0] = 1;
665 uuids_start[1] = EIR_UUID16_ALL;
666 ptr += 2;
667 }
668
669 /* Stop if not enough space to put next UUID */
670 if ((ptr - data) + sizeof(u16) > len) {
671 uuids_start[1] = EIR_UUID16_SOME;
672 break;
673 }
674
675 *ptr++ = (uuid16 & 0x00ff);
676 *ptr++ = (uuid16 & 0xff00) >> 8;
677 uuids_start[0] += sizeof(uuid16);
678 }
679
680 return ptr;
681}
682
Johan Hedbergcdf19632013-01-27 00:31:34 +0200683static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
684{
685 u8 *ptr = data, *uuids_start = NULL;
686 struct bt_uuid *uuid;
687
688 if (len < 6)
689 return ptr;
690
691 list_for_each_entry(uuid, &hdev->uuids, list) {
692 if (uuid->size != 32)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID32_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u32) > len) {
704 uuids_start[1] = EIR_UUID32_SOME;
705 break;
706 }
707
708 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
709 ptr += sizeof(u32);
710 uuids_start[0] += sizeof(u32);
711 }
712
713 return ptr;
714}
715
Johan Hedbergc00d5752013-01-27 00:31:35 +0200716static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 18)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 128)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID128_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + 16 > len) {
737 uuids_start[1] = EIR_UUID128_SOME;
738 break;
739 }
740
741 memcpy(ptr, uuid->uuid, 16);
742 ptr += 16;
743 uuids_start[0] += 16;
744 }
745
746 return ptr;
747}
748
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300749static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
750{
751 struct pending_cmd *cmd;
752
753 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
754 if (cmd->opcode == opcode)
755 return cmd;
756 }
757
758 return NULL;
759}
760
Johan Hedberg95868422014-06-28 17:54:07 +0300761static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
762 struct hci_dev *hdev,
763 const void *data)
764{
765 struct pending_cmd *cmd;
766
767 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
768 if (cmd->user_data != data)
769 continue;
770 if (cmd->opcode == opcode)
771 return cmd;
772 }
773
774 return NULL;
775}
776
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700777static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
778{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700779 u8 ad_len = 0;
780 size_t name_len;
781
782 name_len = strlen(hdev->dev_name);
783 if (name_len > 0) {
784 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
785
786 if (name_len > max_len) {
787 name_len = max_len;
788 ptr[1] = EIR_NAME_SHORT;
789 } else
790 ptr[1] = EIR_NAME_COMPLETE;
791
792 ptr[0] = name_len + 1;
793
794 memcpy(ptr + 2, hdev->dev_name, name_len);
795
796 ad_len += (name_len + 2);
797 ptr += (name_len + 2);
798 }
799
800 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700801}
802
803static void update_scan_rsp_data(struct hci_request *req)
804{
805 struct hci_dev *hdev = req->hdev;
806 struct hci_cp_le_set_scan_rsp_data cp;
807 u8 len;
808
Johan Hedberg7751ef12013-10-19 23:38:15 +0300809 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700810 return;
811
812 memset(&cp, 0, sizeof(cp));
813
814 len = create_scan_rsp_data(hdev, cp.data);
815
Johan Hedbergeb438b52013-10-16 15:31:07 +0300816 if (hdev->scan_rsp_data_len == len &&
817 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700818 return;
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
821 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822
823 cp.length = len;
824
825 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
826}
827
Johan Hedberg9a43e252013-10-20 19:00:07 +0300828static u8 get_adv_discov_flags(struct hci_dev *hdev)
829{
830 struct pending_cmd *cmd;
831
832 /* If there's a pending mgmt command the flags will not yet have
833 * their final values, so check for this first.
834 */
835 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
836 if (cmd) {
837 struct mgmt_mode *cp = cmd->param;
838 if (cp->val == 0x01)
839 return LE_AD_GENERAL;
840 else if (cp->val == 0x02)
841 return LE_AD_LIMITED;
842 } else {
843 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_LIMITED;
845 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_GENERAL;
847 }
848
849 return 0;
850}
851
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700852static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853{
854 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberg9a43e252013-10-20 19:00:07 +0300856 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberge8340042014-01-30 11:16:50 -0800858 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
861 if (flags) {
862 BT_DBG("adv flags 0x%02x", flags);
863
864 ptr[0] = 2;
865 ptr[1] = EIR_FLAGS;
866 ptr[2] = flags;
867
868 ad_len += 3;
869 ptr += 3;
870 }
871
872 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
873 ptr[0] = 2;
874 ptr[1] = EIR_TX_POWER;
875 ptr[2] = (u8) hdev->adv_tx_power;
876
877 ad_len += 3;
878 ptr += 3;
879 }
880
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700881 return ad_len;
882}
883
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700884static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885{
886 struct hci_dev *hdev = req->hdev;
887 struct hci_cp_le_set_adv_data cp;
888 u8 len;
889
Johan Hedberg10994ce2013-10-19 23:38:16 +0300890 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891 return;
892
893 memset(&cp, 0, sizeof(cp));
894
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700895 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896
897 if (hdev->adv_data_len == len &&
898 memcmp(cp.data, hdev->adv_data, len) == 0)
899 return;
900
901 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
902 hdev->adv_data_len = len;
903
904 cp.length = len;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
907}
908
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300909static void create_eir(struct hci_dev *hdev, u8 *data)
910{
911 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300912 size_t name_len;
913
914 name_len = strlen(hdev->dev_name);
915
916 if (name_len > 0) {
917 /* EIR Data type */
918 if (name_len > 48) {
919 name_len = 48;
920 ptr[1] = EIR_NAME_SHORT;
921 } else
922 ptr[1] = EIR_NAME_COMPLETE;
923
924 /* EIR Data length */
925 ptr[0] = name_len + 1;
926
927 memcpy(ptr + 2, hdev->dev_name, name_len);
928
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300929 ptr += (name_len + 2);
930 }
931
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100932 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700933 ptr[0] = 2;
934 ptr[1] = EIR_TX_POWER;
935 ptr[2] = (u8) hdev->inq_tx_power;
936
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700937 ptr += 3;
938 }
939
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700940 if (hdev->devid_source > 0) {
941 ptr[0] = 9;
942 ptr[1] = EIR_DEVICE_ID;
943
944 put_unaligned_le16(hdev->devid_source, ptr + 2);
945 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
946 put_unaligned_le16(hdev->devid_product, ptr + 6);
947 put_unaligned_le16(hdev->devid_version, ptr + 8);
948
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700949 ptr += 10;
950 }
951
Johan Hedberg213202e2013-01-27 00:31:33 +0200952 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200953 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200954 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300955}
956
Johan Hedberg890ea892013-03-15 17:06:52 -0500957static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300958{
Johan Hedberg890ea892013-03-15 17:06:52 -0500959 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300960 struct hci_cp_write_eir cp;
961
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200962 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500963 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200964
Johan Hedberg976eb202012-10-24 21:12:01 +0300965 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500966 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200968 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200971 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500972 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973
974 memset(&cp, 0, sizeof(cp));
975
976 create_eir(hdev, cp.data);
977
978 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
981 memcpy(hdev->eir, cp.data, sizeof(cp.data));
982
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984}
985
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200986static u8 get_service_classes(struct hci_dev *hdev)
987{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300988 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200989 u8 val = 0;
990
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300991 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200992 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200993
994 return val;
995}
996
Johan Hedberg890ea892013-03-15 17:06:52 -0500997static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200998{
Johan Hedberg890ea892013-03-15 17:06:52 -0500999 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 cod[3];
1001
1002 BT_DBG("%s", hdev->name);
1003
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001004 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001005 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001006
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001007 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1008 return;
1009
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001010 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001011 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001012
1013 cod[0] = hdev->minor_class;
1014 cod[1] = hdev->major_class;
1015 cod[2] = get_service_classes(hdev);
1016
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001017 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1018 cod[1] |= 0x20;
1019
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001020 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001024}
1025
Johan Hedberga4858cb2014-02-25 19:56:31 +02001026static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001027{
1028 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001029
1030 /* If there's a pending mgmt command the flag will not yet have
1031 * it's final value, so check for this first.
1032 */
1033 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1034 if (cmd) {
1035 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037 }
1038
Johan Hedberga4858cb2014-02-25 19:56:31 +02001039 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040}
1041
1042static void enable_advertising(struct hci_request *req)
1043{
1044 struct hci_dev *hdev = req->hdev;
1045 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001046 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048
Johan Hedberg8d972502014-02-28 12:54:14 +02001049 /* Clear the HCI_ADVERTISING bit temporarily so that the
1050 * hci_update_random_address knows that it's safe to go ahead
1051 * and write a new random address. The flag will be set back on
1052 * as soon as the SET_ADV_ENABLE HCI command completes.
1053 */
1054 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1055
Johan Hedberga4858cb2014-02-25 19:56:31 +02001056 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001057
Johan Hedberga4858cb2014-02-25 19:56:31 +02001058 /* Set require_privacy to true only when non-connectable
1059 * advertising is used. In that case it is fine to use a
1060 * non-resolvable private address.
1061 */
1062 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001063 return;
1064
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001065 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001066 cp.min_interval = cpu_to_le16(0x0800);
1067 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001068 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001069 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001070 cp.channel_map = hdev->le_adv_channel_map;
1071
1072 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1073
1074 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1075}
1076
1077static void disable_advertising(struct hci_request *req)
1078{
1079 u8 enable = 0x00;
1080
1081 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1082}
1083
Johan Hedberg7d785252011-12-15 00:47:39 +02001084static void service_cache_off(struct work_struct *work)
1085{
1086 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001087 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001088 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001089
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001090 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001091 return;
1092
Johan Hedberg890ea892013-03-15 17:06:52 -05001093 hci_req_init(&req, hdev);
1094
Johan Hedberg7d785252011-12-15 00:47:39 +02001095 hci_dev_lock(hdev);
1096
Johan Hedberg890ea892013-03-15 17:06:52 -05001097 update_eir(&req);
1098 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001099
1100 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001101
1102 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001103}
1104
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001105static void rpa_expired(struct work_struct *work)
1106{
1107 struct hci_dev *hdev = container_of(work, struct hci_dev,
1108 rpa_expired.work);
1109 struct hci_request req;
1110
1111 BT_DBG("");
1112
1113 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1114
1115 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
1116 hci_conn_num(hdev, LE_LINK) > 0)
1117 return;
1118
1119 /* The generation of a new RPA and programming it into the
1120 * controller happens in the enable_advertising() function.
1121 */
1122
1123 hci_req_init(&req, hdev);
1124
1125 disable_advertising(&req);
1126 enable_advertising(&req);
1127
1128 hci_req_run(&req, NULL);
1129}
1130
Johan Hedberg6a919082012-02-28 06:17:26 +02001131static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001132{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001133 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001134 return;
1135
Johan Hedberg4f87da82012-03-02 19:55:56 +02001136 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001138
Johan Hedberg4f87da82012-03-02 19:55:56 +02001139 /* Non-mgmt controlled devices get this bit set
1140 * implicitly so that pairing works for them, however
1141 * for mgmt we require user-space to explicitly enable
1142 * it
1143 */
1144 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001145}
1146
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001147static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001148 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001149{
1150 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001151
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001152 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001153
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001154 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001155
Johan Hedberg03811012010-12-08 00:21:06 +02001156 memset(&rp, 0, sizeof(rp));
1157
Johan Hedberg03811012010-12-08 00:21:06 +02001158 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001159
1160 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001161 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001162
1163 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1164 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1165
1166 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001167
1168 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001169 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001170
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001171 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001173 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001174 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001175}
1176
1177static void mgmt_pending_free(struct pending_cmd *cmd)
1178{
1179 sock_put(cmd->sk);
1180 kfree(cmd->param);
1181 kfree(cmd);
1182}
1183
1184static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001185 struct hci_dev *hdev, void *data,
1186 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001187{
1188 struct pending_cmd *cmd;
1189
Johan Hedbergfca20012014-06-28 17:54:05 +03001190 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001191 if (!cmd)
1192 return NULL;
1193
1194 cmd->opcode = opcode;
1195 cmd->index = hdev->id;
1196
Andre Guedes12b94562012-06-07 19:05:45 -03001197 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001198 if (!cmd->param) {
1199 kfree(cmd);
1200 return NULL;
1201 }
1202
1203 if (data)
1204 memcpy(cmd->param, data, len);
1205
1206 cmd->sk = sk;
1207 sock_hold(sk);
1208
1209 list_add(&cmd->list, &hdev->mgmt_pending);
1210
1211 return cmd;
1212}
1213
1214static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001215 void (*cb)(struct pending_cmd *cmd,
1216 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001217 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001218{
Andre Guedesa3d09352013-02-01 11:21:30 -03001219 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001220
Andre Guedesa3d09352013-02-01 11:21:30 -03001221 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001222 if (opcode > 0 && cmd->opcode != opcode)
1223 continue;
1224
1225 cb(cmd, data);
1226 }
1227}
1228
Johan Hedberg03811012010-12-08 00:21:06 +02001229static void mgmt_pending_remove(struct pending_cmd *cmd)
1230{
1231 list_del(&cmd->list);
1232 mgmt_pending_free(cmd);
1233}
1234
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001235static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001236{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001237 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001238
Johan Hedbergaee9b212012-02-18 15:07:59 +02001239 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001240 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001241}
1242
Johan Hedberg8b064a32014-02-24 14:52:22 +02001243static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1244{
1245 BT_DBG("%s status 0x%02x", hdev->name, status);
1246
Johan Hedberga3172b72014-02-28 09:33:44 +02001247 if (hci_conn_count(hdev) == 0) {
1248 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001249 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001250 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001251}
1252
Johan Hedberg21a60d32014-06-10 14:05:58 +03001253static void hci_stop_discovery(struct hci_request *req)
1254{
1255 struct hci_dev *hdev = req->hdev;
1256 struct hci_cp_remote_name_req_cancel cp;
1257 struct inquiry_entry *e;
1258
1259 switch (hdev->discovery.state) {
1260 case DISCOVERY_FINDING:
1261 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1262 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1263 } else {
1264 cancel_delayed_work(&hdev->le_scan_disable);
1265 hci_req_add_le_scan_disable(req);
1266 }
1267
1268 break;
1269
1270 case DISCOVERY_RESOLVING:
1271 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1272 NAME_PENDING);
1273 if (!e)
1274 return;
1275
1276 bacpy(&cp.bdaddr, &e->data.bdaddr);
1277 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1278 &cp);
1279
1280 break;
1281
1282 default:
1283 /* Passive scanning */
1284 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1285 hci_req_add_le_scan_disable(req);
1286 break;
1287 }
1288}
1289
Johan Hedberg8b064a32014-02-24 14:52:22 +02001290static int clean_up_hci_state(struct hci_dev *hdev)
1291{
1292 struct hci_request req;
1293 struct hci_conn *conn;
1294
1295 hci_req_init(&req, hdev);
1296
1297 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1298 test_bit(HCI_PSCAN, &hdev->flags)) {
1299 u8 scan = 0x00;
1300 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1301 }
1302
1303 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1304 disable_advertising(&req);
1305
Johan Hedbergf8680f12014-06-10 14:05:59 +03001306 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001307
1308 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1309 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001310 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001311
Johan Hedbergc9910d02014-02-27 14:35:12 +02001312 switch (conn->state) {
1313 case BT_CONNECTED:
1314 case BT_CONFIG:
1315 dc.handle = cpu_to_le16(conn->handle);
1316 dc.reason = 0x15; /* Terminated due to Power Off */
1317 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1318 break;
1319 case BT_CONNECT:
1320 if (conn->type == LE_LINK)
1321 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1322 0, NULL);
1323 else if (conn->type == ACL_LINK)
1324 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1325 6, &conn->dst);
1326 break;
1327 case BT_CONNECT2:
1328 bacpy(&rej.bdaddr, &conn->dst);
1329 rej.reason = 0x15; /* Terminated due to Power Off */
1330 if (conn->type == ACL_LINK)
1331 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1332 sizeof(rej), &rej);
1333 else if (conn->type == SCO_LINK)
1334 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1335 sizeof(rej), &rej);
1336 break;
1337 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001338 }
1339
1340 return hci_req_run(&req, clean_up_hci_complete);
1341}
1342
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001343static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001344 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001345{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001346 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001347 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001348 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001350 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001351
Johan Hedberga7e80f22013-01-09 16:05:19 +02001352 if (cp->val != 0x00 && cp->val != 0x01)
1353 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1354 MGMT_STATUS_INVALID_PARAMS);
1355
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001356 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001357
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001358 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1359 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1360 MGMT_STATUS_BUSY);
1361 goto failed;
1362 }
1363
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001364 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1365 cancel_delayed_work(&hdev->power_off);
1366
1367 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001368 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1369 data, len);
1370 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001371 goto failed;
1372 }
1373 }
1374
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001375 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001376 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001377 goto failed;
1378 }
1379
Johan Hedberg03811012010-12-08 00:21:06 +02001380 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1381 if (!cmd) {
1382 err = -ENOMEM;
1383 goto failed;
1384 }
1385
Johan Hedberg8b064a32014-02-24 14:52:22 +02001386 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001387 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001388 err = 0;
1389 } else {
1390 /* Disconnect connections, stop scans, etc */
1391 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001392 if (!err)
1393 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1394 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001395
Johan Hedberg8b064a32014-02-24 14:52:22 +02001396 /* ENODATA means there were no HCI commands queued */
1397 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001398 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001399 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1400 err = 0;
1401 }
1402 }
Johan Hedberg03811012010-12-08 00:21:06 +02001403
1404failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001405 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001406 return err;
1407}
1408
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001409static int new_settings(struct hci_dev *hdev, struct sock *skip)
1410{
1411 __le32 ev;
1412
1413 ev = cpu_to_le32(get_current_settings(hdev));
1414
1415 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1416}
1417
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001418struct cmd_lookup {
1419 struct sock *sk;
1420 struct hci_dev *hdev;
1421 u8 mgmt_status;
1422};
1423
1424static void settings_rsp(struct pending_cmd *cmd, void *data)
1425{
1426 struct cmd_lookup *match = data;
1427
1428 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1429
1430 list_del(&cmd->list);
1431
1432 if (match->sk == NULL) {
1433 match->sk = cmd->sk;
1434 sock_hold(match->sk);
1435 }
1436
1437 mgmt_pending_free(cmd);
1438}
1439
1440static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1441{
1442 u8 *status = data;
1443
1444 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1445 mgmt_pending_remove(cmd);
1446}
1447
Johan Hedberge6fe7982013-10-02 15:45:22 +03001448static u8 mgmt_bredr_support(struct hci_dev *hdev)
1449{
1450 if (!lmp_bredr_capable(hdev))
1451 return MGMT_STATUS_NOT_SUPPORTED;
1452 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1453 return MGMT_STATUS_REJECTED;
1454 else
1455 return MGMT_STATUS_SUCCESS;
1456}
1457
1458static u8 mgmt_le_support(struct hci_dev *hdev)
1459{
1460 if (!lmp_le_capable(hdev))
1461 return MGMT_STATUS_NOT_SUPPORTED;
1462 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1463 return MGMT_STATUS_REJECTED;
1464 else
1465 return MGMT_STATUS_SUCCESS;
1466}
1467
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001468static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1469{
1470 struct pending_cmd *cmd;
1471 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001472 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001473 bool changed;
1474
1475 BT_DBG("status 0x%02x", status);
1476
1477 hci_dev_lock(hdev);
1478
1479 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1480 if (!cmd)
1481 goto unlock;
1482
1483 if (status) {
1484 u8 mgmt_err = mgmt_status(status);
1485 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001486 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001487 goto remove_cmd;
1488 }
1489
1490 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001491 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001492 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1493 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001494
1495 if (hdev->discov_timeout > 0) {
1496 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1497 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1498 to);
1499 }
1500 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001501 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1502 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001503 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504
1505 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1506
1507 if (changed)
1508 new_settings(hdev, cmd->sk);
1509
Marcel Holtmann970ba522013-10-15 06:33:57 -07001510 /* When the discoverable mode gets changed, make sure
1511 * that class of device has the limited discoverable
1512 * bit correctly set.
1513 */
1514 hci_req_init(&req, hdev);
1515 update_class(&req);
1516 hci_req_run(&req, NULL);
1517
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001518remove_cmd:
1519 mgmt_pending_remove(cmd);
1520
1521unlock:
1522 hci_dev_unlock(hdev);
1523}
1524
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001525static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001526 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001527{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001528 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001529 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001530 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001531 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001532 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001533 int err;
1534
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001535 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001536
Johan Hedberg9a43e252013-10-20 19:00:07 +03001537 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1538 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001539 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001540 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001541
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001542 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001543 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1544 MGMT_STATUS_INVALID_PARAMS);
1545
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001546 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001547
1548 /* Disabling discoverable requires that no timeout is set,
1549 * and enabling limited discoverable requires a timeout.
1550 */
1551 if ((cp->val == 0x00 && timeout > 0) ||
1552 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001553 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001554 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001555
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001556 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001557
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001558 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001559 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001560 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001561 goto failed;
1562 }
1563
1564 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001565 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001566 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001567 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001568 goto failed;
1569 }
1570
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001571 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001572 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001573 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001574 goto failed;
1575 }
1576
1577 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001578 bool changed = false;
1579
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001580 /* Setting limited discoverable when powered off is
1581 * not a valid operation since it requires a timeout
1582 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1583 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001584 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1585 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1586 changed = true;
1587 }
1588
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001589 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001590 if (err < 0)
1591 goto failed;
1592
1593 if (changed)
1594 err = new_settings(hdev, sk);
1595
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001596 goto failed;
1597 }
1598
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001599 /* If the current mode is the same, then just update the timeout
1600 * value with the new value. And if only the timeout gets updated,
1601 * then no need for any HCI transactions.
1602 */
1603 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1604 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1605 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001606 cancel_delayed_work(&hdev->discov_off);
1607 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001608
Marcel Holtmann36261542013-10-15 08:28:51 -07001609 if (cp->val && hdev->discov_timeout > 0) {
1610 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001611 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001612 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001613 }
1614
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001615 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1620 if (!cmd) {
1621 err = -ENOMEM;
1622 goto failed;
1623 }
1624
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001625 /* Cancel any potential discoverable timeout that might be
1626 * still active and store new timeout value. The arming of
1627 * the timeout happens in the complete handler.
1628 */
1629 cancel_delayed_work(&hdev->discov_off);
1630 hdev->discov_timeout = timeout;
1631
Johan Hedbergb456f872013-10-19 23:38:22 +03001632 /* Limited discoverable mode */
1633 if (cp->val == 0x02)
1634 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1635 else
1636 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1637
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001638 hci_req_init(&req, hdev);
1639
Johan Hedberg9a43e252013-10-20 19:00:07 +03001640 /* The procedure for LE-only controllers is much simpler - just
1641 * update the advertising data.
1642 */
1643 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1644 goto update_ad;
1645
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001646 scan = SCAN_PAGE;
1647
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001648 if (cp->val) {
1649 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001650
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001651 if (cp->val == 0x02) {
1652 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001653 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1655 hci_cp.iac_lap[1] = 0x8b;
1656 hci_cp.iac_lap[2] = 0x9e;
1657 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1658 hci_cp.iac_lap[4] = 0x8b;
1659 hci_cp.iac_lap[5] = 0x9e;
1660 } else {
1661 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001662 hci_cp.num_iac = 1;
1663 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1664 hci_cp.iac_lap[1] = 0x8b;
1665 hci_cp.iac_lap[2] = 0x9e;
1666 }
1667
1668 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1669 (hci_cp.num_iac * 3) + 1, &hci_cp);
1670
1671 scan |= SCAN_INQUIRY;
1672 } else {
1673 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1674 }
1675
1676 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001677
Johan Hedberg9a43e252013-10-20 19:00:07 +03001678update_ad:
1679 update_adv_data(&req);
1680
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001681 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001682 if (err < 0)
1683 mgmt_pending_remove(cmd);
1684
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001685failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001686 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001687 return err;
1688}
1689
Johan Hedberg406d7802013-03-15 17:07:09 -05001690static void write_fast_connectable(struct hci_request *req, bool enable)
1691{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001692 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001693 struct hci_cp_write_page_scan_activity acp;
1694 u8 type;
1695
Johan Hedberg547003b2013-10-21 16:51:53 +03001696 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1697 return;
1698
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001699 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1700 return;
1701
Johan Hedberg406d7802013-03-15 17:07:09 -05001702 if (enable) {
1703 type = PAGE_SCAN_TYPE_INTERLACED;
1704
1705 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001706 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001707 } else {
1708 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1709
1710 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001711 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001712 }
1713
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001714 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001715
Johan Hedbergbd98b992013-03-15 17:07:13 -05001716 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1717 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1718 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1719 sizeof(acp), &acp);
1720
1721 if (hdev->page_scan_type != type)
1722 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001723}
1724
Johan Hedberg2b76f452013-03-15 17:07:04 -05001725static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1726{
1727 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001728 struct mgmt_mode *cp;
1729 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001730
1731 BT_DBG("status 0x%02x", status);
1732
1733 hci_dev_lock(hdev);
1734
1735 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1736 if (!cmd)
1737 goto unlock;
1738
Johan Hedberg37438c12013-10-14 16:20:05 +03001739 if (status) {
1740 u8 mgmt_err = mgmt_status(status);
1741 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1742 goto remove_cmd;
1743 }
1744
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001745 cp = cmd->param;
1746 if (cp->val)
1747 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1748 else
1749 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1750
Johan Hedberg2b76f452013-03-15 17:07:04 -05001751 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1752
Johan Hedberg2b7be332014-07-07 14:40:22 +03001753 if (changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001754 new_settings(hdev, cmd->sk);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001755 hci_update_background_scan(hdev);
1756 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001757
Johan Hedberg37438c12013-10-14 16:20:05 +03001758remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001759 mgmt_pending_remove(cmd);
1760
1761unlock:
1762 hci_dev_unlock(hdev);
1763}
1764
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001765static int set_connectable_update_settings(struct hci_dev *hdev,
1766 struct sock *sk, u8 val)
1767{
1768 bool changed = false;
1769 int err;
1770
1771 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1772 changed = true;
1773
1774 if (val) {
1775 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1776 } else {
1777 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1778 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1779 }
1780
1781 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1782 if (err < 0)
1783 return err;
1784
1785 if (changed)
1786 return new_settings(hdev, sk);
1787
1788 return 0;
1789}
1790
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001791static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001792 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001793{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001794 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001795 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001796 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001797 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001798 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001799
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001800 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001801
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001802 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1803 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001804 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001805 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001806
Johan Hedberga7e80f22013-01-09 16:05:19 +02001807 if (cp->val != 0x00 && cp->val != 0x01)
1808 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1809 MGMT_STATUS_INVALID_PARAMS);
1810
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001811 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001812
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001813 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001814 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001815 goto failed;
1816 }
1817
1818 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001819 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001820 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001821 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001822 goto failed;
1823 }
1824
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001825 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1826 if (!cmd) {
1827 err = -ENOMEM;
1828 goto failed;
1829 }
1830
Johan Hedberg2b76f452013-03-15 17:07:04 -05001831 hci_req_init(&req, hdev);
1832
Johan Hedberg9a43e252013-10-20 19:00:07 +03001833 /* If BR/EDR is not enabled and we disable advertising as a
1834 * by-product of disabling connectable, we need to update the
1835 * advertising flags.
1836 */
1837 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1838 if (!cp->val) {
1839 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1840 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1841 }
1842 update_adv_data(&req);
1843 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001844 if (cp->val) {
1845 scan = SCAN_PAGE;
1846 } else {
1847 scan = 0;
1848
1849 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001850 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001851 cancel_delayed_work(&hdev->discov_off);
1852 }
1853
1854 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1855 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001856
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001857 /* If we're going from non-connectable to connectable or
1858 * vice-versa when fast connectable is enabled ensure that fast
1859 * connectable gets disabled. write_fast_connectable won't do
1860 * anything if the page scan parameters are already what they
1861 * should be.
1862 */
1863 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001864 write_fast_connectable(&req, false);
1865
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001866 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1867 hci_conn_num(hdev, LE_LINK) == 0) {
1868 disable_advertising(&req);
1869 enable_advertising(&req);
1870 }
1871
Johan Hedberg2b76f452013-03-15 17:07:04 -05001872 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001873 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001874 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001875 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001876 err = set_connectable_update_settings(hdev, sk,
1877 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001878 goto failed;
1879 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001880
1881failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001882 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001883 return err;
1884}
1885
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001886static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001887 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001888{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001889 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001890 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001891 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001893 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001894
Johan Hedberga7e80f22013-01-09 16:05:19 +02001895 if (cp->val != 0x00 && cp->val != 0x01)
1896 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1897 MGMT_STATUS_INVALID_PARAMS);
1898
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001899 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001900
1901 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001902 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001903 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001904 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001905
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001906 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001907 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001908 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001909
Marcel Holtmann55594352013-10-06 16:11:57 -07001910 if (changed)
1911 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001912
Marcel Holtmann55594352013-10-06 16:11:57 -07001913unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001914 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001915 return err;
1916}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001917
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001918static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1919 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001920{
1921 struct mgmt_mode *cp = data;
1922 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001923 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001924 int err;
1925
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001926 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001927
Johan Hedberge6fe7982013-10-02 15:45:22 +03001928 status = mgmt_bredr_support(hdev);
1929 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001930 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001931 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001932
Johan Hedberga7e80f22013-01-09 16:05:19 +02001933 if (cp->val != 0x00 && cp->val != 0x01)
1934 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1935 MGMT_STATUS_INVALID_PARAMS);
1936
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001937 hci_dev_lock(hdev);
1938
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001939 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001940 bool changed = false;
1941
1942 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001943 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001944 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1945 changed = true;
1946 }
1947
1948 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1949 if (err < 0)
1950 goto failed;
1951
1952 if (changed)
1953 err = new_settings(hdev, sk);
1954
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001955 goto failed;
1956 }
1957
1958 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001959 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001960 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001961 goto failed;
1962 }
1963
1964 val = !!cp->val;
1965
1966 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1967 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1968 goto failed;
1969 }
1970
1971 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1972 if (!cmd) {
1973 err = -ENOMEM;
1974 goto failed;
1975 }
1976
1977 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1978 if (err < 0) {
1979 mgmt_pending_remove(cmd);
1980 goto failed;
1981 }
1982
1983failed:
1984 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001985 return err;
1986}
1987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001988static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001989{
1990 struct mgmt_mode *cp = data;
1991 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001992 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001993 int err;
1994
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001995 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001996
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001997 status = mgmt_bredr_support(hdev);
1998 if (status)
1999 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2000
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002001 if (!lmp_ssp_capable(hdev))
2002 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2003 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002004
Johan Hedberga7e80f22013-01-09 16:05:19 +02002005 if (cp->val != 0x00 && cp->val != 0x01)
2006 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2007 MGMT_STATUS_INVALID_PARAMS);
2008
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002009 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002010
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002011 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002012 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002013
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002014 if (cp->val) {
2015 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2016 &hdev->dev_flags);
2017 } else {
2018 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2019 &hdev->dev_flags);
2020 if (!changed)
2021 changed = test_and_clear_bit(HCI_HS_ENABLED,
2022 &hdev->dev_flags);
2023 else
2024 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002025 }
2026
2027 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2028 if (err < 0)
2029 goto failed;
2030
2031 if (changed)
2032 err = new_settings(hdev, sk);
2033
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002034 goto failed;
2035 }
2036
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002037 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2038 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002039 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2040 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002041 goto failed;
2042 }
2043
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002044 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002045 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2046 goto failed;
2047 }
2048
2049 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2050 if (!cmd) {
2051 err = -ENOMEM;
2052 goto failed;
2053 }
2054
Johan Hedberg37699722014-06-24 14:00:27 +03002055 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2056 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2057 sizeof(cp->val), &cp->val);
2058
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002059 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002060 if (err < 0) {
2061 mgmt_pending_remove(cmd);
2062 goto failed;
2063 }
2064
2065failed:
2066 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002067 return err;
2068}
2069
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002070static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002071{
2072 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002073 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002074 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002075 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002076
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002077 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002078
Johan Hedberge6fe7982013-10-02 15:45:22 +03002079 status = mgmt_bredr_support(hdev);
2080 if (status)
2081 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002082
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002083 if (!lmp_ssp_capable(hdev))
2084 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2085 MGMT_STATUS_NOT_SUPPORTED);
2086
2087 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2088 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2089 MGMT_STATUS_REJECTED);
2090
Johan Hedberga7e80f22013-01-09 16:05:19 +02002091 if (cp->val != 0x00 && cp->val != 0x01)
2092 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2093 MGMT_STATUS_INVALID_PARAMS);
2094
Marcel Holtmannee392692013-10-01 22:59:23 -07002095 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002096
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002097 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002098 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002099 } else {
2100 if (hdev_is_powered(hdev)) {
2101 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2102 MGMT_STATUS_REJECTED);
2103 goto unlock;
2104 }
2105
Marcel Holtmannee392692013-10-01 22:59:23 -07002106 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002107 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002108
2109 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2110 if (err < 0)
2111 goto unlock;
2112
2113 if (changed)
2114 err = new_settings(hdev, sk);
2115
2116unlock:
2117 hci_dev_unlock(hdev);
2118 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002119}
2120
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002121static void le_enable_complete(struct hci_dev *hdev, u8 status)
2122{
2123 struct cmd_lookup match = { NULL, hdev };
2124
2125 if (status) {
2126 u8 mgmt_err = mgmt_status(status);
2127
2128 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2129 &mgmt_err);
2130 return;
2131 }
2132
2133 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2134
2135 new_settings(hdev, match.sk);
2136
2137 if (match.sk)
2138 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002139
2140 /* Make sure the controller has a good default for
2141 * advertising data. Restrict the update to when LE
2142 * has actually been enabled. During power on, the
2143 * update in powered_update_hci will take care of it.
2144 */
2145 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2146 struct hci_request req;
2147
2148 hci_dev_lock(hdev);
2149
2150 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002151 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002152 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002153 hci_req_run(&req, NULL);
2154
Johan Hedberga70f4b52014-07-07 15:19:50 +03002155 hci_update_background_scan(hdev);
2156
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002157 hci_dev_unlock(hdev);
2158 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002159}
2160
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002161static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002162{
2163 struct mgmt_mode *cp = data;
2164 struct hci_cp_write_le_host_supported hci_cp;
2165 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002166 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002167 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002168 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002169
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002170 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002171
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002172 if (!lmp_le_capable(hdev))
2173 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2174 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002175
Johan Hedberga7e80f22013-01-09 16:05:19 +02002176 if (cp->val != 0x00 && cp->val != 0x01)
2177 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2178 MGMT_STATUS_INVALID_PARAMS);
2179
Johan Hedbergc73eee92013-04-19 18:35:21 +03002180 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002181 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002182 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2183 MGMT_STATUS_REJECTED);
2184
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002185 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002186
2187 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002188 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002189
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002190 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002191 bool changed = false;
2192
2193 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2194 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2195 changed = true;
2196 }
2197
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002198 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2199 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002200 changed = true;
2201 }
2202
Johan Hedberg06199cf2012-02-22 16:37:11 +02002203 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2204 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002205 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002206
2207 if (changed)
2208 err = new_settings(hdev, sk);
2209
Johan Hedberg1de028c2012-02-29 19:55:35 -08002210 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002211 }
2212
Johan Hedberg4375f102013-09-25 13:26:10 +03002213 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2214 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002215 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002216 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002217 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002218 }
2219
2220 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2221 if (!cmd) {
2222 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002223 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002224 }
2225
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002226 hci_req_init(&req, hdev);
2227
Johan Hedberg06199cf2012-02-22 16:37:11 +02002228 memset(&hci_cp, 0, sizeof(hci_cp));
2229
2230 if (val) {
2231 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002232 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002233 } else {
2234 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2235 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002236 }
2237
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002238 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2239 &hci_cp);
2240
2241 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302242 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002243 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002244
Johan Hedberg1de028c2012-02-29 19:55:35 -08002245unlock:
2246 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002247 return err;
2248}
2249
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002250/* This is a helper function to test for pending mgmt commands that can
2251 * cause CoD or EIR HCI commands. We can only allow one such pending
2252 * mgmt command at a time since otherwise we cannot easily track what
2253 * the current values are, will be, and based on that calculate if a new
2254 * HCI command needs to be sent and if yes with what value.
2255 */
2256static bool pending_eir_or_class(struct hci_dev *hdev)
2257{
2258 struct pending_cmd *cmd;
2259
2260 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2261 switch (cmd->opcode) {
2262 case MGMT_OP_ADD_UUID:
2263 case MGMT_OP_REMOVE_UUID:
2264 case MGMT_OP_SET_DEV_CLASS:
2265 case MGMT_OP_SET_POWERED:
2266 return true;
2267 }
2268 }
2269
2270 return false;
2271}
2272
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002273static const u8 bluetooth_base_uuid[] = {
2274 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2275 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2276};
2277
2278static u8 get_uuid_size(const u8 *uuid)
2279{
2280 u32 val;
2281
2282 if (memcmp(uuid, bluetooth_base_uuid, 12))
2283 return 128;
2284
2285 val = get_unaligned_le32(&uuid[12]);
2286 if (val > 0xffff)
2287 return 32;
2288
2289 return 16;
2290}
2291
Johan Hedberg92da6092013-03-15 17:06:55 -05002292static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2293{
2294 struct pending_cmd *cmd;
2295
2296 hci_dev_lock(hdev);
2297
2298 cmd = mgmt_pending_find(mgmt_op, hdev);
2299 if (!cmd)
2300 goto unlock;
2301
2302 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2303 hdev->dev_class, 3);
2304
2305 mgmt_pending_remove(cmd);
2306
2307unlock:
2308 hci_dev_unlock(hdev);
2309}
2310
2311static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2312{
2313 BT_DBG("status 0x%02x", status);
2314
2315 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2316}
2317
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002318static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002319{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002320 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002321 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002322 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002323 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002324 int err;
2325
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002326 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002327
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002328 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002329
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002330 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002331 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002332 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002333 goto failed;
2334 }
2335
Andre Guedes92c4c202012-06-07 19:05:44 -03002336 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002337 if (!uuid) {
2338 err = -ENOMEM;
2339 goto failed;
2340 }
2341
2342 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002343 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002344 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002345
Johan Hedbergde66aa62013-01-27 00:31:27 +02002346 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002347
Johan Hedberg890ea892013-03-15 17:06:52 -05002348 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002349
Johan Hedberg890ea892013-03-15 17:06:52 -05002350 update_class(&req);
2351 update_eir(&req);
2352
Johan Hedberg92da6092013-03-15 17:06:55 -05002353 err = hci_req_run(&req, add_uuid_complete);
2354 if (err < 0) {
2355 if (err != -ENODATA)
2356 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002357
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002358 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002359 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002360 goto failed;
2361 }
2362
2363 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002364 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002365 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002366 goto failed;
2367 }
2368
2369 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002370
2371failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002372 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002373 return err;
2374}
2375
Johan Hedberg24b78d02012-02-23 23:24:30 +02002376static bool enable_service_cache(struct hci_dev *hdev)
2377{
2378 if (!hdev_is_powered(hdev))
2379 return false;
2380
2381 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002382 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2383 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002384 return true;
2385 }
2386
2387 return false;
2388}
2389
Johan Hedberg92da6092013-03-15 17:06:55 -05002390static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2391{
2392 BT_DBG("status 0x%02x", status);
2393
2394 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2395}
2396
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002397static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002398 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002399{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002400 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002401 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002402 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002403 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 -05002404 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002405 int err, found;
2406
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002407 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002408
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002409 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002410
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002411 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002412 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002413 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002414 goto unlock;
2415 }
2416
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002417 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002418 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002419
Johan Hedberg24b78d02012-02-23 23:24:30 +02002420 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002421 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002422 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002423 goto unlock;
2424 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002425
Johan Hedberg9246a862012-02-23 21:33:16 +02002426 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002427 }
2428
2429 found = 0;
2430
Johan Hedberg056341c2013-01-27 00:31:30 +02002431 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002432 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2433 continue;
2434
2435 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002436 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002437 found++;
2438 }
2439
2440 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002441 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002442 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002443 goto unlock;
2444 }
2445
Johan Hedberg9246a862012-02-23 21:33:16 +02002446update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002447 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002448
Johan Hedberg890ea892013-03-15 17:06:52 -05002449 update_class(&req);
2450 update_eir(&req);
2451
Johan Hedberg92da6092013-03-15 17:06:55 -05002452 err = hci_req_run(&req, remove_uuid_complete);
2453 if (err < 0) {
2454 if (err != -ENODATA)
2455 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002456
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002457 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002458 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002459 goto unlock;
2460 }
2461
2462 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002463 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002464 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002465 goto unlock;
2466 }
2467
2468 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002469
2470unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002471 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002472 return err;
2473}
2474
Johan Hedberg92da6092013-03-15 17:06:55 -05002475static void set_class_complete(struct hci_dev *hdev, u8 status)
2476{
2477 BT_DBG("status 0x%02x", status);
2478
2479 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2480}
2481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002482static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002483 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002484{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002485 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002486 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002487 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002488 int err;
2489
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002490 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002491
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002492 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002493 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2494 MGMT_STATUS_NOT_SUPPORTED);
2495
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002496 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002497
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002498 if (pending_eir_or_class(hdev)) {
2499 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2500 MGMT_STATUS_BUSY);
2501 goto unlock;
2502 }
2503
2504 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2505 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2506 MGMT_STATUS_INVALID_PARAMS);
2507 goto unlock;
2508 }
2509
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002510 hdev->major_class = cp->major;
2511 hdev->minor_class = cp->minor;
2512
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002513 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002514 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002515 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002516 goto unlock;
2517 }
2518
Johan Hedberg890ea892013-03-15 17:06:52 -05002519 hci_req_init(&req, hdev);
2520
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002521 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002522 hci_dev_unlock(hdev);
2523 cancel_delayed_work_sync(&hdev->service_cache);
2524 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002525 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002526 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002527
Johan Hedberg890ea892013-03-15 17:06:52 -05002528 update_class(&req);
2529
Johan Hedberg92da6092013-03-15 17:06:55 -05002530 err = hci_req_run(&req, set_class_complete);
2531 if (err < 0) {
2532 if (err != -ENODATA)
2533 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002534
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002535 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002536 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002537 goto unlock;
2538 }
2539
2540 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002541 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002542 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002543 goto unlock;
2544 }
2545
2546 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002547
Johan Hedbergb5235a62012-02-21 14:32:24 +02002548unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002549 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002550 return err;
2551}
2552
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002553static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002554 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002555{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002556 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002557 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2558 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002559 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002560 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002561 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002562
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002563 BT_DBG("request for %s", hdev->name);
2564
2565 if (!lmp_bredr_capable(hdev))
2566 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2567 MGMT_STATUS_NOT_SUPPORTED);
2568
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002569 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002570 if (key_count > max_key_count) {
2571 BT_ERR("load_link_keys: too big key_count value %u",
2572 key_count);
2573 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2574 MGMT_STATUS_INVALID_PARAMS);
2575 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002576
Johan Hedberg86742e12011-11-07 23:13:38 +02002577 expected_len = sizeof(*cp) + key_count *
2578 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002579 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002580 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002581 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002582 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002583 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002584 }
2585
Johan Hedberg4ae14302013-01-20 14:27:13 +02002586 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2587 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2588 MGMT_STATUS_INVALID_PARAMS);
2589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002590 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002591 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002592
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002593 for (i = 0; i < key_count; i++) {
2594 struct mgmt_link_key_info *key = &cp->keys[i];
2595
Marcel Holtmann8e991132014-01-10 02:07:25 -08002596 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002597 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2598 MGMT_STATUS_INVALID_PARAMS);
2599 }
2600
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002601 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002602
2603 hci_link_keys_clear(hdev);
2604
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002605 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002606 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2607 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002608 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002609 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2610 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002611
2612 if (changed)
2613 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002614
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002615 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002616 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002617
Johan Hedberg58e92932014-06-24 14:00:26 +03002618 /* Always ignore debug keys and require a new pairing if
2619 * the user wants to use them.
2620 */
2621 if (key->type == HCI_LK_DEBUG_COMBINATION)
2622 continue;
2623
Johan Hedberg7652ff62014-06-24 13:15:49 +03002624 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2625 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002626 }
2627
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002628 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002629
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002630 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002631
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002632 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002633}
2634
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002635static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002636 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002637{
2638 struct mgmt_ev_device_unpaired ev;
2639
2640 bacpy(&ev.addr.bdaddr, bdaddr);
2641 ev.addr.type = addr_type;
2642
2643 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002644 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002645}
2646
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002647static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002648 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002649{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002650 struct mgmt_cp_unpair_device *cp = data;
2651 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002652 struct hci_cp_disconnect dc;
2653 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002654 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002655 int err;
2656
Johan Hedberga8a1d192011-11-10 15:54:38 +02002657 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002658 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2659 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002660
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002661 if (!bdaddr_type_is_valid(cp->addr.type))
2662 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2663 MGMT_STATUS_INVALID_PARAMS,
2664 &rp, sizeof(rp));
2665
Johan Hedberg118da702013-01-20 14:27:20 +02002666 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2667 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2668 MGMT_STATUS_INVALID_PARAMS,
2669 &rp, sizeof(rp));
2670
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002671 hci_dev_lock(hdev);
2672
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002673 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002674 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002675 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002676 goto unlock;
2677 }
2678
Johan Hedberge0b2b272014-02-18 17:14:31 +02002679 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002680 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002681 } else {
2682 u8 addr_type;
2683
2684 if (cp->addr.type == BDADDR_LE_PUBLIC)
2685 addr_type = ADDR_LE_DEV_PUBLIC;
2686 else
2687 addr_type = ADDR_LE_DEV_RANDOM;
2688
Johan Hedberga7ec7332014-02-18 17:14:35 +02002689 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2690
Andre Guedesa9b0a042014-02-26 20:21:52 -03002691 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2692
Johan Hedberge0b2b272014-02-18 17:14:31 +02002693 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2694 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002695
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002696 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002697 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002698 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002699 goto unlock;
2700 }
2701
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002702 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002703 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002704 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002705 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002706 else
2707 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002708 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002709 } else {
2710 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002712
Johan Hedberga8a1d192011-11-10 15:54:38 +02002713 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002714 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002715 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002716 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002717 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002718 }
2719
Johan Hedberg124f6e32012-02-09 13:50:12 +02002720 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002721 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002722 if (!cmd) {
2723 err = -ENOMEM;
2724 goto unlock;
2725 }
2726
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002727 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002728 dc.reason = 0x13; /* Remote User Terminated Connection */
2729 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2730 if (err < 0)
2731 mgmt_pending_remove(cmd);
2732
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002733unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002734 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002735 return err;
2736}
2737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002738static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002739 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002740{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002741 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002742 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002743 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002744 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002745 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002746 int err;
2747
2748 BT_DBG("");
2749
Johan Hedberg06a63b12013-01-20 14:27:21 +02002750 memset(&rp, 0, sizeof(rp));
2751 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2752 rp.addr.type = cp->addr.type;
2753
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002754 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002755 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2756 MGMT_STATUS_INVALID_PARAMS,
2757 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002758
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002759 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002760
2761 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002762 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2763 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002764 goto failed;
2765 }
2766
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002767 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002768 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2769 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002770 goto failed;
2771 }
2772
Andre Guedes591f47f2012-04-24 21:02:49 -03002773 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002774 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2775 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002776 else
2777 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002778
Vishal Agarwalf9607272012-06-13 05:32:43 +05302779 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002780 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2781 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002782 goto failed;
2783 }
2784
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002785 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002786 if (!cmd) {
2787 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002788 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002789 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002790
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002791 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002792 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002793
2794 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2795 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002796 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002797
2798failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002799 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002800 return err;
2801}
2802
Andre Guedes57c14772012-04-24 21:02:50 -03002803static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002804{
2805 switch (link_type) {
2806 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002807 switch (addr_type) {
2808 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002809 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002810
Johan Hedberg48264f02011-11-09 13:58:58 +02002811 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002812 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002813 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002814 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002815
Johan Hedberg4c659c32011-11-07 23:13:39 +02002816 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002817 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002818 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002819 }
2820}
2821
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002822static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2823 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002824{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002825 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002826 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002827 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002828 int err;
2829 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002830
2831 BT_DBG("");
2832
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002833 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002834
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002835 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002836 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002837 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002838 goto unlock;
2839 }
2840
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002841 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002842 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2843 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002844 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002845 }
2846
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002847 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002848 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002849 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002850 err = -ENOMEM;
2851 goto unlock;
2852 }
2853
Johan Hedberg2784eb42011-01-21 13:56:35 +02002854 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002855 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002856 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2857 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002858 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002859 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002860 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002861 continue;
2862 i++;
2863 }
2864
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002865 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002866
Johan Hedberg4c659c32011-11-07 23:13:39 +02002867 /* Recalculate length in case of filtered SCO connections, etc */
2868 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002869
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002870 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002871 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002872
Johan Hedberga38528f2011-01-22 06:46:43 +02002873 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002874
2875unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002876 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002877 return err;
2878}
2879
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002880static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002881 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002882{
2883 struct pending_cmd *cmd;
2884 int err;
2885
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002886 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002887 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002888 if (!cmd)
2889 return -ENOMEM;
2890
Johan Hedbergd8457692012-02-17 14:24:57 +02002891 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002892 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002893 if (err < 0)
2894 mgmt_pending_remove(cmd);
2895
2896 return err;
2897}
2898
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002899static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002900 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002901{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002902 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002903 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002904 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002905 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002906 int err;
2907
2908 BT_DBG("");
2909
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002910 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002911
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002912 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002913 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002914 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002915 goto failed;
2916 }
2917
Johan Hedbergd8457692012-02-17 14:24:57 +02002918 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002919 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002920 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002921 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002922 goto failed;
2923 }
2924
2925 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002926 struct mgmt_cp_pin_code_neg_reply ncp;
2927
2928 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002929
2930 BT_ERR("PIN code is not 16 bytes long");
2931
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002932 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002933 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002934 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002935 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002936
2937 goto failed;
2938 }
2939
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002940 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002941 if (!cmd) {
2942 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002943 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002944 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002945
Johan Hedbergd8457692012-02-17 14:24:57 +02002946 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002947 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002948 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002949
2950 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2951 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002952 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002953
2954failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002955 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002956 return err;
2957}
2958
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002959static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2960 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002961{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002962 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002963
2964 BT_DBG("");
2965
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002966 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2967 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2968 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2969
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002970 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002971
2972 hdev->io_capability = cp->io_capability;
2973
2974 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002975 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002976
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002977 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002978
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2980 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002981}
2982
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002983static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002984{
2985 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002986 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002987
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002988 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002989 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2990 continue;
2991
Johan Hedberge9a416b2011-02-19 12:05:56 -03002992 if (cmd->user_data != conn)
2993 continue;
2994
2995 return cmd;
2996 }
2997
2998 return NULL;
2999}
3000
3001static void pairing_complete(struct pending_cmd *cmd, u8 status)
3002{
3003 struct mgmt_rp_pair_device rp;
3004 struct hci_conn *conn = cmd->user_data;
3005
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003006 bacpy(&rp.addr.bdaddr, &conn->dst);
3007 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003008
Johan Hedbergaee9b212012-02-18 15:07:59 +02003009 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003010 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003011
3012 /* So we don't get further callbacks for this connection */
3013 conn->connect_cfm_cb = NULL;
3014 conn->security_cfm_cb = NULL;
3015 conn->disconn_cfm_cb = NULL;
3016
David Herrmann76a68ba2013-04-06 20:28:37 +02003017 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003018
Johan Hedberga664b5b2011-02-19 12:06:02 -03003019 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003020}
3021
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003022void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3023{
3024 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3025 struct pending_cmd *cmd;
3026
3027 cmd = find_pairing(conn);
3028 if (cmd)
3029 pairing_complete(cmd, status);
3030}
3031
Johan Hedberge9a416b2011-02-19 12:05:56 -03003032static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3033{
3034 struct pending_cmd *cmd;
3035
3036 BT_DBG("status %u", status);
3037
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003038 cmd = find_pairing(conn);
3039 if (!cmd)
3040 BT_DBG("Unable to find a pending command");
3041 else
Johan Hedberge2113262012-02-18 15:20:03 +02003042 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003043}
3044
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003045static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303046{
3047 struct pending_cmd *cmd;
3048
3049 BT_DBG("status %u", status);
3050
3051 if (!status)
3052 return;
3053
3054 cmd = find_pairing(conn);
3055 if (!cmd)
3056 BT_DBG("Unable to find a pending command");
3057 else
3058 pairing_complete(cmd, mgmt_status(status));
3059}
3060
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003061static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003062 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003063{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003064 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003065 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003066 struct pending_cmd *cmd;
3067 u8 sec_level, auth_type;
3068 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003069 int err;
3070
3071 BT_DBG("");
3072
Szymon Jancf950a30e2013-01-18 12:48:07 +01003073 memset(&rp, 0, sizeof(rp));
3074 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3075 rp.addr.type = cp->addr.type;
3076
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003077 if (!bdaddr_type_is_valid(cp->addr.type))
3078 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3079 MGMT_STATUS_INVALID_PARAMS,
3080 &rp, sizeof(rp));
3081
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003082 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3083 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3084 MGMT_STATUS_INVALID_PARAMS,
3085 &rp, sizeof(rp));
3086
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003087 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003088
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003089 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003090 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3091 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003092 goto unlock;
3093 }
3094
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003095 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003096 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003097
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003098 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003099 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3100 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003101 } else {
3102 u8 addr_type;
3103
3104 /* Convert from L2CAP channel address type to HCI address type
3105 */
3106 if (cp->addr.type == BDADDR_LE_PUBLIC)
3107 addr_type = ADDR_LE_DEV_PUBLIC;
3108 else
3109 addr_type = ADDR_LE_DEV_RANDOM;
3110
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003111 /* When pairing a new device, it is expected to remember
3112 * this device for future connections. Adding the connection
3113 * parameter information ahead of time allows tracking
3114 * of the slave preferred values and will speed up any
3115 * further connection establishment.
3116 *
3117 * If connection parameters already exist, then they
3118 * will be kept and this function does nothing.
3119 */
3120 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3121
Johan Hedbergcdd62752014-07-07 15:02:28 +03003122 /* Request a connection with master = true role */
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003123 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedbergcdd62752014-07-07 15:02:28 +03003124 sec_level, HCI_LE_CONN_TIMEOUT, true);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003125 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003126
Ville Tervo30e76272011-02-22 16:10:53 -03003127 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003128 int status;
3129
3130 if (PTR_ERR(conn) == -EBUSY)
3131 status = MGMT_STATUS_BUSY;
3132 else
3133 status = MGMT_STATUS_CONNECT_FAILED;
3134
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003135 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003136 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003137 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003138 goto unlock;
3139 }
3140
3141 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003142 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003143 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003144 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003145 goto unlock;
3146 }
3147
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003148 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003149 if (!cmd) {
3150 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003151 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003152 goto unlock;
3153 }
3154
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003155 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003156 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003157 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003158 conn->security_cfm_cb = pairing_complete_cb;
3159 conn->disconn_cfm_cb = pairing_complete_cb;
3160 } else {
3161 conn->connect_cfm_cb = le_pairing_complete_cb;
3162 conn->security_cfm_cb = le_pairing_complete_cb;
3163 conn->disconn_cfm_cb = le_pairing_complete_cb;
3164 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003165
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166 conn->io_capability = cp->io_cap;
3167 cmd->user_data = conn;
3168
3169 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003170 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003171 pairing_complete(cmd, 0);
3172
3173 err = 0;
3174
3175unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003176 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003177 return err;
3178}
3179
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003180static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3181 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003182{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003183 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003184 struct pending_cmd *cmd;
3185 struct hci_conn *conn;
3186 int err;
3187
3188 BT_DBG("");
3189
Johan Hedberg28424702012-02-02 04:02:29 +02003190 hci_dev_lock(hdev);
3191
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003192 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003193 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003194 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003195 goto unlock;
3196 }
3197
Johan Hedberg28424702012-02-02 04:02:29 +02003198 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3199 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003200 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003201 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003202 goto unlock;
3203 }
3204
3205 conn = cmd->user_data;
3206
3207 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003208 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003209 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003210 goto unlock;
3211 }
3212
3213 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003215 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003216 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003217unlock:
3218 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003219 return err;
3220}
3221
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003222static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003223 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003224 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003225{
Johan Hedberga5c29682011-02-19 12:05:57 -03003226 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003227 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003228 int err;
3229
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003230 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003231
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003232 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003233 err = cmd_complete(sk, hdev->id, mgmt_op,
3234 MGMT_STATUS_NOT_POWERED, addr,
3235 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003236 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003237 }
3238
Johan Hedberg1707c602013-03-15 17:07:15 -05003239 if (addr->type == BDADDR_BREDR)
3240 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003241 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003242 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003243
Johan Hedberg272d90d2012-02-09 15:26:12 +02003244 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003245 err = cmd_complete(sk, hdev->id, mgmt_op,
3246 MGMT_STATUS_NOT_CONNECTED, addr,
3247 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003248 goto done;
3249 }
3250
Johan Hedberg1707c602013-03-15 17:07:15 -05003251 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003252 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003253 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003254 err = cmd_complete(sk, hdev->id, mgmt_op,
3255 MGMT_STATUS_SUCCESS, addr,
3256 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003257 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003258 err = cmd_complete(sk, hdev->id, mgmt_op,
3259 MGMT_STATUS_FAILED, addr,
3260 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003261
Brian Gix47c15e22011-11-16 13:53:14 -08003262 goto done;
3263 }
3264
Johan Hedberg1707c602013-03-15 17:07:15 -05003265 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003266 if (!cmd) {
3267 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003268 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003269 }
3270
Brian Gix0df4c182011-11-16 13:53:13 -08003271 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003272 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3273 struct hci_cp_user_passkey_reply cp;
3274
Johan Hedberg1707c602013-03-15 17:07:15 -05003275 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003276 cp.passkey = passkey;
3277 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3278 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003279 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3280 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003281
Johan Hedberga664b5b2011-02-19 12:06:02 -03003282 if (err < 0)
3283 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003284
Brian Gix0df4c182011-11-16 13:53:13 -08003285done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003286 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003287 return err;
3288}
3289
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303290static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3291 void *data, u16 len)
3292{
3293 struct mgmt_cp_pin_code_neg_reply *cp = data;
3294
3295 BT_DBG("");
3296
Johan Hedberg1707c602013-03-15 17:07:15 -05003297 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303298 MGMT_OP_PIN_CODE_NEG_REPLY,
3299 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3300}
3301
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003302static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3303 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003304{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003305 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003306
3307 BT_DBG("");
3308
3309 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003310 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003311 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003312
Johan Hedberg1707c602013-03-15 17:07:15 -05003313 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003314 MGMT_OP_USER_CONFIRM_REPLY,
3315 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003316}
3317
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003318static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003319 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003320{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003321 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003322
3323 BT_DBG("");
3324
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_NEG_REPLY,
3327 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003328}
3329
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003330static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3331 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003332{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003333 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -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_PASSKEY_REPLY,
3339 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003340}
3341
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003342static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003343 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003344{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003345 struct mgmt_cp_user_passkey_neg_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_NEG_REPLY,
3351 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003352}
3353
Johan Hedberg13928972013-03-15 17:07:00 -05003354static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003355{
Johan Hedberg13928972013-03-15 17:07:00 -05003356 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003357 struct hci_cp_write_local_name cp;
3358
Johan Hedberg13928972013-03-15 17:07:00 -05003359 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003360
Johan Hedberg890ea892013-03-15 17:06:52 -05003361 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003362}
3363
Johan Hedberg13928972013-03-15 17:07:00 -05003364static void set_name_complete(struct hci_dev *hdev, u8 status)
3365{
3366 struct mgmt_cp_set_local_name *cp;
3367 struct pending_cmd *cmd;
3368
3369 BT_DBG("status 0x%02x", status);
3370
3371 hci_dev_lock(hdev);
3372
3373 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3374 if (!cmd)
3375 goto unlock;
3376
3377 cp = cmd->param;
3378
3379 if (status)
3380 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3381 mgmt_status(status));
3382 else
3383 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3384 cp, sizeof(*cp));
3385
3386 mgmt_pending_remove(cmd);
3387
3388unlock:
3389 hci_dev_unlock(hdev);
3390}
3391
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003392static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003393 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003394{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003395 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003396 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003397 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003398 int err;
3399
3400 BT_DBG("");
3401
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003402 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003403
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003404 /* If the old values are the same as the new ones just return a
3405 * direct command complete event.
3406 */
3407 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3408 !memcmp(hdev->short_name, cp->short_name,
3409 sizeof(hdev->short_name))) {
3410 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3411 data, len);
3412 goto failed;
3413 }
3414
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003415 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003416
Johan Hedbergb5235a62012-02-21 14:32:24 +02003417 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003418 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003419
3420 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003421 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003422 if (err < 0)
3423 goto failed;
3424
3425 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003426 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003427
Johan Hedbergb5235a62012-02-21 14:32:24 +02003428 goto failed;
3429 }
3430
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003431 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003432 if (!cmd) {
3433 err = -ENOMEM;
3434 goto failed;
3435 }
3436
Johan Hedberg13928972013-03-15 17:07:00 -05003437 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3438
Johan Hedberg890ea892013-03-15 17:06:52 -05003439 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003440
3441 if (lmp_bredr_capable(hdev)) {
3442 update_name(&req);
3443 update_eir(&req);
3444 }
3445
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003446 /* The name is stored in the scan response data and so
3447 * no need to udpate the advertising data here.
3448 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003449 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003450 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003451
Johan Hedberg13928972013-03-15 17:07:00 -05003452 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003453 if (err < 0)
3454 mgmt_pending_remove(cmd);
3455
3456failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003457 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003458 return err;
3459}
3460
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003461static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003462 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003463{
Szymon Jancc35938b2011-03-22 13:12:21 +01003464 struct pending_cmd *cmd;
3465 int err;
3466
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003467 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003468
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003469 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003470
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003471 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003472 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003473 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003474 goto unlock;
3475 }
3476
Andre Guedes9a1a1992012-07-24 15:03:48 -03003477 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003478 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003479 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003480 goto unlock;
3481 }
3482
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003483 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, 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_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003486 goto unlock;
3487 }
3488
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003489 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003490 if (!cmd) {
3491 err = -ENOMEM;
3492 goto unlock;
3493 }
3494
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003495 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3496 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3497 0, NULL);
3498 else
3499 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3500
Szymon Jancc35938b2011-03-22 13:12:21 +01003501 if (err < 0)
3502 mgmt_pending_remove(cmd);
3503
3504unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003505 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003506 return err;
3507}
3508
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003509static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003510 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003511{
Szymon Janc2763eda2011-03-22 13:12:22 +01003512 int err;
3513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003515
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003516 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003517
Marcel Holtmannec109112014-01-10 02:07:30 -08003518 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3519 struct mgmt_cp_add_remote_oob_data *cp = data;
3520 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003521
Marcel Holtmannec109112014-01-10 02:07:30 -08003522 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3523 cp->hash, cp->randomizer);
3524 if (err < 0)
3525 status = MGMT_STATUS_FAILED;
3526 else
3527 status = MGMT_STATUS_SUCCESS;
3528
3529 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3530 status, &cp->addr, sizeof(cp->addr));
3531 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3532 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3533 u8 status;
3534
3535 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3536 cp->hash192,
3537 cp->randomizer192,
3538 cp->hash256,
3539 cp->randomizer256);
3540 if (err < 0)
3541 status = MGMT_STATUS_FAILED;
3542 else
3543 status = MGMT_STATUS_SUCCESS;
3544
3545 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3546 status, &cp->addr, sizeof(cp->addr));
3547 } else {
3548 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3549 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3550 MGMT_STATUS_INVALID_PARAMS);
3551 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003552
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003553 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003554 return err;
3555}
3556
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003557static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003558 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003559{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003560 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003561 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003562 int err;
3563
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003564 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003565
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003566 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003567
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003568 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003569 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003570 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003571 else
Szymon Janca6785be2012-12-13 15:11:21 +01003572 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003574 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003575 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003576
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003577 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003578 return err;
3579}
3580
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003581static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3582{
3583 struct pending_cmd *cmd;
3584 u8 type;
3585 int err;
3586
3587 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3588
3589 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3590 if (!cmd)
3591 return -ENOENT;
3592
3593 type = hdev->discovery.type;
3594
3595 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3596 &type, sizeof(type));
3597 mgmt_pending_remove(cmd);
3598
3599 return err;
3600}
3601
Andre Guedes7c307722013-04-30 15:29:28 -03003602static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3603{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003604 unsigned long timeout = 0;
3605
Andre Guedes7c307722013-04-30 15:29:28 -03003606 BT_DBG("status %d", status);
3607
3608 if (status) {
3609 hci_dev_lock(hdev);
3610 mgmt_start_discovery_failed(hdev, status);
3611 hci_dev_unlock(hdev);
3612 return;
3613 }
3614
3615 hci_dev_lock(hdev);
3616 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3617 hci_dev_unlock(hdev);
3618
3619 switch (hdev->discovery.type) {
3620 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003621 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003622 break;
3623
3624 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003625 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003626 break;
3627
3628 case DISCOV_TYPE_BREDR:
3629 break;
3630
3631 default:
3632 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3633 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003634
3635 if (!timeout)
3636 return;
3637
3638 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003639}
3640
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003641static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003642 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003643{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003644 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003645 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003646 struct hci_cp_le_set_scan_param param_cp;
3647 struct hci_cp_le_set_scan_enable enable_cp;
3648 struct hci_cp_inquiry inq_cp;
3649 struct hci_request req;
3650 /* General inquiry access code (GIAC) */
3651 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003652 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003653 int err;
3654
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003655 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003656
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003657 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003658
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003659 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003660 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003661 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003662 goto failed;
3663 }
3664
Andre Guedes642be6c2012-03-21 00:03:37 -03003665 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3666 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3667 MGMT_STATUS_BUSY);
3668 goto failed;
3669 }
3670
Johan Hedbergff9ef572012-01-04 14:23:45 +02003671 if (hdev->discovery.state != DISCOVERY_STOPPED) {
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_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003674 goto failed;
3675 }
3676
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003677 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003678 if (!cmd) {
3679 err = -ENOMEM;
3680 goto failed;
3681 }
3682
Andre Guedes4aab14e2012-02-17 20:39:36 -03003683 hdev->discovery.type = cp->type;
3684
Andre Guedes7c307722013-04-30 15:29:28 -03003685 hci_req_init(&req, hdev);
3686
Andre Guedes4aab14e2012-02-17 20:39:36 -03003687 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003688 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003689 status = mgmt_bredr_support(hdev);
3690 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003691 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003692 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003693 mgmt_pending_remove(cmd);
3694 goto failed;
3695 }
3696
Andre Guedes7c307722013-04-30 15:29:28 -03003697 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3698 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3699 MGMT_STATUS_BUSY);
3700 mgmt_pending_remove(cmd);
3701 goto failed;
3702 }
3703
3704 hci_inquiry_cache_flush(hdev);
3705
3706 memset(&inq_cp, 0, sizeof(inq_cp));
3707 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003708 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003709 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003710 break;
3711
3712 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003713 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003714 status = mgmt_le_support(hdev);
3715 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003716 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003717 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003718 mgmt_pending_remove(cmd);
3719 goto failed;
3720 }
3721
Andre Guedes7c307722013-04-30 15:29:28 -03003722 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003723 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003724 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3725 MGMT_STATUS_NOT_SUPPORTED);
3726 mgmt_pending_remove(cmd);
3727 goto failed;
3728 }
3729
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003730 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003731 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3732 MGMT_STATUS_REJECTED);
3733 mgmt_pending_remove(cmd);
3734 goto failed;
3735 }
3736
Andre Guedesc54c3862014-02-26 20:21:50 -03003737 /* If controller is scanning, it means the background scanning
3738 * is running. Thus, we should temporarily stop it in order to
3739 * set the discovery scanning parameters.
3740 */
3741 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3742 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003743
3744 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003745
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003746 /* All active scans will be done with either a resolvable
3747 * private address (when privacy feature has been enabled)
3748 * or unresolvable private address.
3749 */
3750 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003751 if (err < 0) {
3752 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3753 MGMT_STATUS_FAILED);
3754 mgmt_pending_remove(cmd);
3755 goto failed;
3756 }
3757
Andre Guedes7c307722013-04-30 15:29:28 -03003758 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003759 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3760 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003761 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003762 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3763 &param_cp);
3764
3765 memset(&enable_cp, 0, sizeof(enable_cp));
3766 enable_cp.enable = LE_SCAN_ENABLE;
3767 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3768 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3769 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003770 break;
3771
Andre Guedesf39799f2012-02-17 20:39:35 -03003772 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003773 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3774 MGMT_STATUS_INVALID_PARAMS);
3775 mgmt_pending_remove(cmd);
3776 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003777 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003778
Andre Guedes7c307722013-04-30 15:29:28 -03003779 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003780 if (err < 0)
3781 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003782 else
3783 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003784
3785failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003786 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003787 return err;
3788}
3789
Andre Guedes1183fdc2013-04-30 15:29:35 -03003790static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3791{
3792 struct pending_cmd *cmd;
3793 int err;
3794
3795 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3796 if (!cmd)
3797 return -ENOENT;
3798
3799 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3800 &hdev->discovery.type, sizeof(hdev->discovery.type));
3801 mgmt_pending_remove(cmd);
3802
3803 return err;
3804}
3805
Andre Guedes0e05bba2013-04-30 15:29:33 -03003806static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3807{
3808 BT_DBG("status %d", status);
3809
3810 hci_dev_lock(hdev);
3811
3812 if (status) {
3813 mgmt_stop_discovery_failed(hdev, status);
3814 goto unlock;
3815 }
3816
3817 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3818
3819unlock:
3820 hci_dev_unlock(hdev);
3821}
3822
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003823static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003824 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003825{
Johan Hedbergd9306502012-02-20 23:25:18 +02003826 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003827 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003828 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003829 int err;
3830
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003831 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003832
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003833 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003834
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003835 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003836 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003837 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3838 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003839 goto unlock;
3840 }
3841
3842 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003843 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003844 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3845 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003846 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003847 }
3848
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003849 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003850 if (!cmd) {
3851 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003852 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003853 }
3854
Andre Guedes0e05bba2013-04-30 15:29:33 -03003855 hci_req_init(&req, hdev);
3856
Johan Hedberg21a60d32014-06-10 14:05:58 +03003857 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003858
Johan Hedberg21a60d32014-06-10 14:05:58 +03003859 err = hci_req_run(&req, stop_discovery_complete);
3860 if (!err) {
3861 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003862 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003863 }
3864
Johan Hedberg21a60d32014-06-10 14:05:58 +03003865 mgmt_pending_remove(cmd);
3866
3867 /* If no HCI commands were sent we're done */
3868 if (err == -ENODATA) {
3869 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3870 &mgmt_cp->type, sizeof(mgmt_cp->type));
3871 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3872 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003873
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003874unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003875 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003876 return err;
3877}
3878
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003879static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003880 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003881{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003882 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003883 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003884 int err;
3885
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003886 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003887
Johan Hedberg561aafb2012-01-04 13:31:59 +02003888 hci_dev_lock(hdev);
3889
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003890 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003891 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3892 MGMT_STATUS_FAILED, &cp->addr,
3893 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003894 goto failed;
3895 }
3896
Johan Hedberga198e7b2012-02-17 14:27:06 +02003897 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003898 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003899 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3900 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3901 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003902 goto failed;
3903 }
3904
3905 if (cp->name_known) {
3906 e->name_state = NAME_KNOWN;
3907 list_del(&e->list);
3908 } else {
3909 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02003910 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003911 }
3912
Johan Hedberge3846622013-01-09 15:29:33 +02003913 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3914 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003915
3916failed:
3917 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003918 return err;
3919}
3920
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003921static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003922 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003923{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003924 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003925 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003926 int err;
3927
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003928 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003929
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003930 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003931 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3932 MGMT_STATUS_INVALID_PARAMS,
3933 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003934
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003935 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003936
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003937 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003938 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003939 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003940 goto done;
3941 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003942
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003943 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3944 sk);
3945 status = MGMT_STATUS_SUCCESS;
3946
3947done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003948 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003949 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003950
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003951 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003952
3953 return err;
3954}
3955
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003956static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003957 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003958{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003959 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003960 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003961 int err;
3962
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003963 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003964
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003965 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003966 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3967 MGMT_STATUS_INVALID_PARAMS,
3968 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003969
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003970 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003971
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003972 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003973 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003974 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003975 goto done;
3976 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003977
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003978 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3979 sk);
3980 status = MGMT_STATUS_SUCCESS;
3981
3982done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003983 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003984 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003985
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003986 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003987
3988 return err;
3989}
3990
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003991static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3992 u16 len)
3993{
3994 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003995 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003996 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003997 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003998
3999 BT_DBG("%s", hdev->name);
4000
Szymon Jancc72d4b82012-03-16 16:02:57 +01004001 source = __le16_to_cpu(cp->source);
4002
4003 if (source > 0x0002)
4004 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4005 MGMT_STATUS_INVALID_PARAMS);
4006
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004007 hci_dev_lock(hdev);
4008
Szymon Jancc72d4b82012-03-16 16:02:57 +01004009 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004010 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4011 hdev->devid_product = __le16_to_cpu(cp->product);
4012 hdev->devid_version = __le16_to_cpu(cp->version);
4013
4014 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4015
Johan Hedberg890ea892013-03-15 17:06:52 -05004016 hci_req_init(&req, hdev);
4017 update_eir(&req);
4018 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004019
4020 hci_dev_unlock(hdev);
4021
4022 return err;
4023}
4024
Johan Hedberg4375f102013-09-25 13:26:10 +03004025static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4026{
4027 struct cmd_lookup match = { NULL, hdev };
4028
4029 if (status) {
4030 u8 mgmt_err = mgmt_status(status);
4031
4032 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4033 cmd_status_rsp, &mgmt_err);
4034 return;
4035 }
4036
4037 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4038 &match);
4039
4040 new_settings(hdev, match.sk);
4041
4042 if (match.sk)
4043 sock_put(match.sk);
4044}
4045
Marcel Holtmann21b51872013-10-10 09:47:53 -07004046static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4047 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004048{
4049 struct mgmt_mode *cp = data;
4050 struct pending_cmd *cmd;
4051 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004052 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004053 int err;
4054
4055 BT_DBG("request for %s", hdev->name);
4056
Johan Hedberge6fe7982013-10-02 15:45:22 +03004057 status = mgmt_le_support(hdev);
4058 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004059 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004060 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004061
4062 if (cp->val != 0x00 && cp->val != 0x01)
4063 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4064 MGMT_STATUS_INVALID_PARAMS);
4065
4066 hci_dev_lock(hdev);
4067
4068 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004069 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004070
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004071 /* The following conditions are ones which mean that we should
4072 * not do any HCI communication but directly send a mgmt
4073 * response to user space (after toggling the flag if
4074 * necessary).
4075 */
4076 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004077 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004078 bool changed = false;
4079
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004080 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4081 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004082 changed = true;
4083 }
4084
4085 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4086 if (err < 0)
4087 goto unlock;
4088
4089 if (changed)
4090 err = new_settings(hdev, sk);
4091
4092 goto unlock;
4093 }
4094
4095 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4096 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4097 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4098 MGMT_STATUS_BUSY);
4099 goto unlock;
4100 }
4101
4102 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4103 if (!cmd) {
4104 err = -ENOMEM;
4105 goto unlock;
4106 }
4107
4108 hci_req_init(&req, hdev);
4109
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004110 if (val)
4111 enable_advertising(&req);
4112 else
4113 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004114
4115 err = hci_req_run(&req, set_advertising_complete);
4116 if (err < 0)
4117 mgmt_pending_remove(cmd);
4118
4119unlock:
4120 hci_dev_unlock(hdev);
4121 return err;
4122}
4123
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004124static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4125 void *data, u16 len)
4126{
4127 struct mgmt_cp_set_static_address *cp = data;
4128 int err;
4129
4130 BT_DBG("%s", hdev->name);
4131
Marcel Holtmann62af4442013-10-02 22:10:32 -07004132 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004133 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004134 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004135
4136 if (hdev_is_powered(hdev))
4137 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4138 MGMT_STATUS_REJECTED);
4139
4140 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4141 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4142 return cmd_status(sk, hdev->id,
4143 MGMT_OP_SET_STATIC_ADDRESS,
4144 MGMT_STATUS_INVALID_PARAMS);
4145
4146 /* Two most significant bits shall be set */
4147 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4148 return cmd_status(sk, hdev->id,
4149 MGMT_OP_SET_STATIC_ADDRESS,
4150 MGMT_STATUS_INVALID_PARAMS);
4151 }
4152
4153 hci_dev_lock(hdev);
4154
4155 bacpy(&hdev->static_addr, &cp->bdaddr);
4156
4157 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4158
4159 hci_dev_unlock(hdev);
4160
4161 return err;
4162}
4163
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004164static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4165 void *data, u16 len)
4166{
4167 struct mgmt_cp_set_scan_params *cp = data;
4168 __u16 interval, window;
4169 int err;
4170
4171 BT_DBG("%s", hdev->name);
4172
4173 if (!lmp_le_capable(hdev))
4174 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4175 MGMT_STATUS_NOT_SUPPORTED);
4176
4177 interval = __le16_to_cpu(cp->interval);
4178
4179 if (interval < 0x0004 || interval > 0x4000)
4180 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4181 MGMT_STATUS_INVALID_PARAMS);
4182
4183 window = __le16_to_cpu(cp->window);
4184
4185 if (window < 0x0004 || window > 0x4000)
4186 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4187 MGMT_STATUS_INVALID_PARAMS);
4188
Marcel Holtmann899e1072013-10-14 09:55:32 -07004189 if (window > interval)
4190 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4191 MGMT_STATUS_INVALID_PARAMS);
4192
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004193 hci_dev_lock(hdev);
4194
4195 hdev->le_scan_interval = interval;
4196 hdev->le_scan_window = window;
4197
4198 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4199
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004200 /* If background scan is running, restart it so new parameters are
4201 * loaded.
4202 */
4203 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4204 hdev->discovery.state == DISCOVERY_STOPPED) {
4205 struct hci_request req;
4206
4207 hci_req_init(&req, hdev);
4208
4209 hci_req_add_le_scan_disable(&req);
4210 hci_req_add_le_passive_scan(&req);
4211
4212 hci_req_run(&req, NULL);
4213 }
4214
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004215 hci_dev_unlock(hdev);
4216
4217 return err;
4218}
4219
Johan Hedberg33e38b32013-03-15 17:07:05 -05004220static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4221{
4222 struct pending_cmd *cmd;
4223
4224 BT_DBG("status 0x%02x", status);
4225
4226 hci_dev_lock(hdev);
4227
4228 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4229 if (!cmd)
4230 goto unlock;
4231
4232 if (status) {
4233 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4234 mgmt_status(status));
4235 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004236 struct mgmt_mode *cp = cmd->param;
4237
4238 if (cp->val)
4239 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4240 else
4241 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4242
Johan Hedberg33e38b32013-03-15 17:07:05 -05004243 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4244 new_settings(hdev, cmd->sk);
4245 }
4246
4247 mgmt_pending_remove(cmd);
4248
4249unlock:
4250 hci_dev_unlock(hdev);
4251}
4252
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004253static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004254 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004255{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004256 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004257 struct pending_cmd *cmd;
4258 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004259 int err;
4260
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004261 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004262
Johan Hedberg56f87902013-10-02 13:43:13 +03004263 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4264 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004265 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4266 MGMT_STATUS_NOT_SUPPORTED);
4267
Johan Hedberga7e80f22013-01-09 16:05:19 +02004268 if (cp->val != 0x00 && cp->val != 0x01)
4269 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4270 MGMT_STATUS_INVALID_PARAMS);
4271
Johan Hedberg5400c042012-02-21 16:40:33 +02004272 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004273 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004274 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004275
4276 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004277 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004278 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004279
4280 hci_dev_lock(hdev);
4281
Johan Hedberg05cbf292013-03-15 17:07:07 -05004282 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4283 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4284 MGMT_STATUS_BUSY);
4285 goto unlock;
4286 }
4287
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004288 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4289 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4290 hdev);
4291 goto unlock;
4292 }
4293
Johan Hedberg33e38b32013-03-15 17:07:05 -05004294 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4295 data, len);
4296 if (!cmd) {
4297 err = -ENOMEM;
4298 goto unlock;
4299 }
4300
4301 hci_req_init(&req, hdev);
4302
Johan Hedberg406d7802013-03-15 17:07:09 -05004303 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004304
4305 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004306 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004307 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004308 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004309 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004310 }
4311
Johan Hedberg33e38b32013-03-15 17:07:05 -05004312unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004313 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004314
Antti Julkuf6422ec2011-06-22 13:11:56 +03004315 return err;
4316}
4317
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004318static void set_bredr_scan(struct hci_request *req)
4319{
4320 struct hci_dev *hdev = req->hdev;
4321 u8 scan = 0;
4322
4323 /* Ensure that fast connectable is disabled. This function will
4324 * not do anything if the page scan parameters are already what
4325 * they should be.
4326 */
4327 write_fast_connectable(req, false);
4328
4329 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4330 scan |= SCAN_PAGE;
4331 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4332 scan |= SCAN_INQUIRY;
4333
4334 if (scan)
4335 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4336}
4337
Johan Hedberg0663ca22013-10-02 13:43:14 +03004338static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4339{
4340 struct pending_cmd *cmd;
4341
4342 BT_DBG("status 0x%02x", status);
4343
4344 hci_dev_lock(hdev);
4345
4346 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4347 if (!cmd)
4348 goto unlock;
4349
4350 if (status) {
4351 u8 mgmt_err = mgmt_status(status);
4352
4353 /* We need to restore the flag if related HCI commands
4354 * failed.
4355 */
4356 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4357
4358 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4359 } else {
4360 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4361 new_settings(hdev, cmd->sk);
4362 }
4363
4364 mgmt_pending_remove(cmd);
4365
4366unlock:
4367 hci_dev_unlock(hdev);
4368}
4369
4370static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4371{
4372 struct mgmt_mode *cp = data;
4373 struct pending_cmd *cmd;
4374 struct hci_request req;
4375 int err;
4376
4377 BT_DBG("request for %s", hdev->name);
4378
4379 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4380 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4381 MGMT_STATUS_NOT_SUPPORTED);
4382
4383 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4384 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4385 MGMT_STATUS_REJECTED);
4386
4387 if (cp->val != 0x00 && cp->val != 0x01)
4388 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4389 MGMT_STATUS_INVALID_PARAMS);
4390
4391 hci_dev_lock(hdev);
4392
4393 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4394 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4395 goto unlock;
4396 }
4397
4398 if (!hdev_is_powered(hdev)) {
4399 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004400 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4401 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4402 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4403 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4404 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4405 }
4406
4407 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4408
4409 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4410 if (err < 0)
4411 goto unlock;
4412
4413 err = new_settings(hdev, sk);
4414 goto unlock;
4415 }
4416
4417 /* Reject disabling when powered on */
4418 if (!cp->val) {
4419 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4420 MGMT_STATUS_REJECTED);
4421 goto unlock;
4422 }
4423
4424 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4425 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4426 MGMT_STATUS_BUSY);
4427 goto unlock;
4428 }
4429
4430 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4431 if (!cmd) {
4432 err = -ENOMEM;
4433 goto unlock;
4434 }
4435
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004436 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004437 * generates the correct flags.
4438 */
4439 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4440
4441 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004442
4443 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4444 set_bredr_scan(&req);
4445
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004446 /* Since only the advertising data flags will change, there
4447 * is no need to update the scan response data.
4448 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004449 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004450
Johan Hedberg0663ca22013-10-02 13:43:14 +03004451 err = hci_req_run(&req, set_bredr_complete);
4452 if (err < 0)
4453 mgmt_pending_remove(cmd);
4454
4455unlock:
4456 hci_dev_unlock(hdev);
4457 return err;
4458}
4459
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004460static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4461 void *data, u16 len)
4462{
4463 struct mgmt_mode *cp = data;
4464 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004465 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004466 int err;
4467
4468 BT_DBG("request for %s", hdev->name);
4469
4470 status = mgmt_bredr_support(hdev);
4471 if (status)
4472 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4473 status);
4474
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004475 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004476 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004477 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4478 MGMT_STATUS_NOT_SUPPORTED);
4479
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004480 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004481 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4482 MGMT_STATUS_INVALID_PARAMS);
4483
4484 hci_dev_lock(hdev);
4485
4486 if (!hdev_is_powered(hdev)) {
4487 bool changed;
4488
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004489 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004490 changed = !test_and_set_bit(HCI_SC_ENABLED,
4491 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004492 if (cp->val == 0x02)
4493 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4494 else
4495 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4496 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004497 changed = test_and_clear_bit(HCI_SC_ENABLED,
4498 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004499 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4500 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004501
4502 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4503 if (err < 0)
4504 goto failed;
4505
4506 if (changed)
4507 err = new_settings(hdev, sk);
4508
4509 goto failed;
4510 }
4511
4512 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4513 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4514 MGMT_STATUS_BUSY);
4515 goto failed;
4516 }
4517
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004518 val = !!cp->val;
4519
4520 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4521 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004522 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4523 goto failed;
4524 }
4525
4526 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4527 if (!cmd) {
4528 err = -ENOMEM;
4529 goto failed;
4530 }
4531
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004532 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004533 if (err < 0) {
4534 mgmt_pending_remove(cmd);
4535 goto failed;
4536 }
4537
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004538 if (cp->val == 0x02)
4539 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4540 else
4541 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4542
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004543failed:
4544 hci_dev_unlock(hdev);
4545 return err;
4546}
4547
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004548static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4549 void *data, u16 len)
4550{
4551 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004552 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004553 int err;
4554
4555 BT_DBG("request for %s", hdev->name);
4556
Johan Hedbergb97109792014-06-24 14:00:28 +03004557 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004558 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4559 MGMT_STATUS_INVALID_PARAMS);
4560
4561 hci_dev_lock(hdev);
4562
4563 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004564 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4565 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004566 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004567 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4568 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004569
Johan Hedbergb97109792014-06-24 14:00:28 +03004570 if (cp->val == 0x02)
4571 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4572 &hdev->dev_flags);
4573 else
4574 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4575 &hdev->dev_flags);
4576
4577 if (hdev_is_powered(hdev) && use_changed &&
4578 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4579 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4580 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4581 sizeof(mode), &mode);
4582 }
4583
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004584 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4585 if (err < 0)
4586 goto unlock;
4587
4588 if (changed)
4589 err = new_settings(hdev, sk);
4590
4591unlock:
4592 hci_dev_unlock(hdev);
4593 return err;
4594}
4595
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004596static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4597 u16 len)
4598{
4599 struct mgmt_cp_set_privacy *cp = cp_data;
4600 bool changed;
4601 int err;
4602
4603 BT_DBG("request for %s", hdev->name);
4604
4605 if (!lmp_le_capable(hdev))
4606 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4607 MGMT_STATUS_NOT_SUPPORTED);
4608
4609 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4610 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4611 MGMT_STATUS_INVALID_PARAMS);
4612
4613 if (hdev_is_powered(hdev))
4614 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4615 MGMT_STATUS_REJECTED);
4616
4617 hci_dev_lock(hdev);
4618
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004619 /* If user space supports this command it is also expected to
4620 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4621 */
4622 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4623
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004624 if (cp->privacy) {
4625 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4626 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4627 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4628 } else {
4629 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4630 memset(hdev->irk, 0, sizeof(hdev->irk));
4631 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4632 }
4633
4634 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4635 if (err < 0)
4636 goto unlock;
4637
4638 if (changed)
4639 err = new_settings(hdev, sk);
4640
4641unlock:
4642 hci_dev_unlock(hdev);
4643 return err;
4644}
4645
Johan Hedberg41edf162014-02-18 10:19:35 +02004646static bool irk_is_valid(struct mgmt_irk_info *irk)
4647{
4648 switch (irk->addr.type) {
4649 case BDADDR_LE_PUBLIC:
4650 return true;
4651
4652 case BDADDR_LE_RANDOM:
4653 /* Two most significant bits shall be set */
4654 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4655 return false;
4656 return true;
4657 }
4658
4659 return false;
4660}
4661
4662static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4663 u16 len)
4664{
4665 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004666 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4667 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004668 u16 irk_count, expected_len;
4669 int i, err;
4670
4671 BT_DBG("request for %s", hdev->name);
4672
4673 if (!lmp_le_capable(hdev))
4674 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4675 MGMT_STATUS_NOT_SUPPORTED);
4676
4677 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004678 if (irk_count > max_irk_count) {
4679 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4680 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4681 MGMT_STATUS_INVALID_PARAMS);
4682 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004683
4684 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4685 if (expected_len != len) {
4686 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004687 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004688 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4689 MGMT_STATUS_INVALID_PARAMS);
4690 }
4691
4692 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4693
4694 for (i = 0; i < irk_count; i++) {
4695 struct mgmt_irk_info *key = &cp->irks[i];
4696
4697 if (!irk_is_valid(key))
4698 return cmd_status(sk, hdev->id,
4699 MGMT_OP_LOAD_IRKS,
4700 MGMT_STATUS_INVALID_PARAMS);
4701 }
4702
4703 hci_dev_lock(hdev);
4704
4705 hci_smp_irks_clear(hdev);
4706
4707 for (i = 0; i < irk_count; i++) {
4708 struct mgmt_irk_info *irk = &cp->irks[i];
4709 u8 addr_type;
4710
4711 if (irk->addr.type == BDADDR_LE_PUBLIC)
4712 addr_type = ADDR_LE_DEV_PUBLIC;
4713 else
4714 addr_type = ADDR_LE_DEV_RANDOM;
4715
4716 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4717 BDADDR_ANY);
4718 }
4719
4720 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4721
4722 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4723
4724 hci_dev_unlock(hdev);
4725
4726 return err;
4727}
4728
Johan Hedberg3f706b72013-01-20 14:27:16 +02004729static bool ltk_is_valid(struct mgmt_ltk_info *key)
4730{
4731 if (key->master != 0x00 && key->master != 0x01)
4732 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004733
4734 switch (key->addr.type) {
4735 case BDADDR_LE_PUBLIC:
4736 return true;
4737
4738 case BDADDR_LE_RANDOM:
4739 /* Two most significant bits shall be set */
4740 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4741 return false;
4742 return true;
4743 }
4744
4745 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004746}
4747
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004748static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004749 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004750{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004751 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004752 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4753 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004754 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004755 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004756
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004757 BT_DBG("request for %s", hdev->name);
4758
4759 if (!lmp_le_capable(hdev))
4760 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4761 MGMT_STATUS_NOT_SUPPORTED);
4762
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004763 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004764 if (key_count > max_key_count) {
4765 BT_ERR("load_ltks: too big key_count value %u", key_count);
4766 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4767 MGMT_STATUS_INVALID_PARAMS);
4768 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004769
4770 expected_len = sizeof(*cp) + key_count *
4771 sizeof(struct mgmt_ltk_info);
4772 if (expected_len != len) {
4773 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004774 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004775 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004776 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004777 }
4778
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004779 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004780
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004781 for (i = 0; i < key_count; i++) {
4782 struct mgmt_ltk_info *key = &cp->keys[i];
4783
Johan Hedberg3f706b72013-01-20 14:27:16 +02004784 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004785 return cmd_status(sk, hdev->id,
4786 MGMT_OP_LOAD_LONG_TERM_KEYS,
4787 MGMT_STATUS_INVALID_PARAMS);
4788 }
4789
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004790 hci_dev_lock(hdev);
4791
4792 hci_smp_ltks_clear(hdev);
4793
4794 for (i = 0; i < key_count; i++) {
4795 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004796 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004797
4798 if (key->addr.type == BDADDR_LE_PUBLIC)
4799 addr_type = ADDR_LE_DEV_PUBLIC;
4800 else
4801 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004802
4803 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004804 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004805 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004806 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004807
Johan Hedberg61b43352014-05-29 19:36:53 +03004808 switch (key->type) {
4809 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004810 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004811 break;
4812 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004813 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004814 break;
4815 default:
4816 continue;
4817 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004818
Johan Hedberg35d70272014-02-19 14:57:47 +02004819 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004820 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004821 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004822 }
4823
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004824 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4825 NULL, 0);
4826
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004827 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004828
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004829 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004830}
4831
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004832struct cmd_conn_lookup {
4833 struct hci_conn *conn;
4834 bool valid_tx_power;
4835 u8 mgmt_status;
4836};
4837
4838static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4839{
4840 struct cmd_conn_lookup *match = data;
4841 struct mgmt_cp_get_conn_info *cp;
4842 struct mgmt_rp_get_conn_info rp;
4843 struct hci_conn *conn = cmd->user_data;
4844
4845 if (conn != match->conn)
4846 return;
4847
4848 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4849
4850 memset(&rp, 0, sizeof(rp));
4851 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4852 rp.addr.type = cp->addr.type;
4853
4854 if (!match->mgmt_status) {
4855 rp.rssi = conn->rssi;
4856
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004857 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004858 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004859 rp.max_tx_power = conn->max_tx_power;
4860 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004861 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004862 rp.max_tx_power = HCI_TX_POWER_INVALID;
4863 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004864 }
4865
4866 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4867 match->mgmt_status, &rp, sizeof(rp));
4868
4869 hci_conn_drop(conn);
4870
4871 mgmt_pending_remove(cmd);
4872}
4873
4874static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4875{
4876 struct hci_cp_read_rssi *cp;
4877 struct hci_conn *conn;
4878 struct cmd_conn_lookup match;
4879 u16 handle;
4880
4881 BT_DBG("status 0x%02x", status);
4882
4883 hci_dev_lock(hdev);
4884
4885 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004886 * otherwise we assume it's not valid. At the moment we assume that
4887 * either both or none of current and max values are valid to keep code
4888 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004889 */
4890 match.valid_tx_power = !status;
4891
4892 /* Commands sent in request are either Read RSSI or Read Transmit Power
4893 * Level so we check which one was last sent to retrieve connection
4894 * handle. Both commands have handle as first parameter so it's safe to
4895 * cast data on the same command struct.
4896 *
4897 * First command sent is always Read RSSI and we fail only if it fails.
4898 * In other case we simply override error to indicate success as we
4899 * already remembered if TX power value is actually valid.
4900 */
4901 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4902 if (!cp) {
4903 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4904 status = 0;
4905 }
4906
4907 if (!cp) {
4908 BT_ERR("invalid sent_cmd in response");
4909 goto unlock;
4910 }
4911
4912 handle = __le16_to_cpu(cp->handle);
4913 conn = hci_conn_hash_lookup_handle(hdev, handle);
4914 if (!conn) {
4915 BT_ERR("unknown handle (%d) in response", handle);
4916 goto unlock;
4917 }
4918
4919 match.conn = conn;
4920 match.mgmt_status = mgmt_status(status);
4921
4922 /* Cache refresh is complete, now reply for mgmt request for given
4923 * connection only.
4924 */
4925 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4926 get_conn_info_complete, &match);
4927
4928unlock:
4929 hci_dev_unlock(hdev);
4930}
4931
4932static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4933 u16 len)
4934{
4935 struct mgmt_cp_get_conn_info *cp = data;
4936 struct mgmt_rp_get_conn_info rp;
4937 struct hci_conn *conn;
4938 unsigned long conn_info_age;
4939 int err = 0;
4940
4941 BT_DBG("%s", hdev->name);
4942
4943 memset(&rp, 0, sizeof(rp));
4944 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4945 rp.addr.type = cp->addr.type;
4946
4947 if (!bdaddr_type_is_valid(cp->addr.type))
4948 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4949 MGMT_STATUS_INVALID_PARAMS,
4950 &rp, sizeof(rp));
4951
4952 hci_dev_lock(hdev);
4953
4954 if (!hdev_is_powered(hdev)) {
4955 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4956 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4957 goto unlock;
4958 }
4959
4960 if (cp->addr.type == BDADDR_BREDR)
4961 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4962 &cp->addr.bdaddr);
4963 else
4964 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4965
4966 if (!conn || conn->state != BT_CONNECTED) {
4967 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4968 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4969 goto unlock;
4970 }
4971
4972 /* To avoid client trying to guess when to poll again for information we
4973 * calculate conn info age as random value between min/max set in hdev.
4974 */
4975 conn_info_age = hdev->conn_info_min_age +
4976 prandom_u32_max(hdev->conn_info_max_age -
4977 hdev->conn_info_min_age);
4978
4979 /* Query controller to refresh cached values if they are too old or were
4980 * never read.
4981 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004982 if (time_after(jiffies, conn->conn_info_timestamp +
4983 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004984 !conn->conn_info_timestamp) {
4985 struct hci_request req;
4986 struct hci_cp_read_tx_power req_txp_cp;
4987 struct hci_cp_read_rssi req_rssi_cp;
4988 struct pending_cmd *cmd;
4989
4990 hci_req_init(&req, hdev);
4991 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4992 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4993 &req_rssi_cp);
4994
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004995 /* For LE links TX power does not change thus we don't need to
4996 * query for it once value is known.
4997 */
4998 if (!bdaddr_type_is_le(cp->addr.type) ||
4999 conn->tx_power == HCI_TX_POWER_INVALID) {
5000 req_txp_cp.handle = cpu_to_le16(conn->handle);
5001 req_txp_cp.type = 0x00;
5002 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5003 sizeof(req_txp_cp), &req_txp_cp);
5004 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005005
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005006 /* Max TX power needs to be read only once per connection */
5007 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5008 req_txp_cp.handle = cpu_to_le16(conn->handle);
5009 req_txp_cp.type = 0x01;
5010 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5011 sizeof(req_txp_cp), &req_txp_cp);
5012 }
5013
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005014 err = hci_req_run(&req, conn_info_refresh_complete);
5015 if (err < 0)
5016 goto unlock;
5017
5018 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5019 data, len);
5020 if (!cmd) {
5021 err = -ENOMEM;
5022 goto unlock;
5023 }
5024
5025 hci_conn_hold(conn);
5026 cmd->user_data = conn;
5027
5028 conn->conn_info_timestamp = jiffies;
5029 } else {
5030 /* Cache is valid, just reply with values cached in hci_conn */
5031 rp.rssi = conn->rssi;
5032 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005033 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005034
5035 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5036 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5037 }
5038
5039unlock:
5040 hci_dev_unlock(hdev);
5041 return err;
5042}
5043
Johan Hedberg95868422014-06-28 17:54:07 +03005044static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5045{
5046 struct mgmt_cp_get_clock_info *cp;
5047 struct mgmt_rp_get_clock_info rp;
5048 struct hci_cp_read_clock *hci_cp;
5049 struct pending_cmd *cmd;
5050 struct hci_conn *conn;
5051
5052 BT_DBG("%s status %u", hdev->name, status);
5053
5054 hci_dev_lock(hdev);
5055
5056 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5057 if (!hci_cp)
5058 goto unlock;
5059
5060 if (hci_cp->which) {
5061 u16 handle = __le16_to_cpu(hci_cp->handle);
5062 conn = hci_conn_hash_lookup_handle(hdev, handle);
5063 } else {
5064 conn = NULL;
5065 }
5066
5067 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5068 if (!cmd)
5069 goto unlock;
5070
5071 cp = cmd->param;
5072
5073 memset(&rp, 0, sizeof(rp));
5074 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5075
5076 if (status)
5077 goto send_rsp;
5078
5079 rp.local_clock = cpu_to_le32(hdev->clock);
5080
5081 if (conn) {
5082 rp.piconet_clock = cpu_to_le32(conn->clock);
5083 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5084 }
5085
5086send_rsp:
5087 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5088 &rp, sizeof(rp));
5089 mgmt_pending_remove(cmd);
5090 if (conn)
5091 hci_conn_drop(conn);
5092
5093unlock:
5094 hci_dev_unlock(hdev);
5095}
5096
5097static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5098 u16 len)
5099{
5100 struct mgmt_cp_get_clock_info *cp = data;
5101 struct mgmt_rp_get_clock_info rp;
5102 struct hci_cp_read_clock hci_cp;
5103 struct pending_cmd *cmd;
5104 struct hci_request req;
5105 struct hci_conn *conn;
5106 int err;
5107
5108 BT_DBG("%s", hdev->name);
5109
5110 memset(&rp, 0, sizeof(rp));
5111 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5112 rp.addr.type = cp->addr.type;
5113
5114 if (cp->addr.type != BDADDR_BREDR)
5115 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5116 MGMT_STATUS_INVALID_PARAMS,
5117 &rp, sizeof(rp));
5118
5119 hci_dev_lock(hdev);
5120
5121 if (!hdev_is_powered(hdev)) {
5122 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5123 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5124 goto unlock;
5125 }
5126
5127 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5128 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5129 &cp->addr.bdaddr);
5130 if (!conn || conn->state != BT_CONNECTED) {
5131 err = cmd_complete(sk, hdev->id,
5132 MGMT_OP_GET_CLOCK_INFO,
5133 MGMT_STATUS_NOT_CONNECTED,
5134 &rp, sizeof(rp));
5135 goto unlock;
5136 }
5137 } else {
5138 conn = NULL;
5139 }
5140
5141 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5142 if (!cmd) {
5143 err = -ENOMEM;
5144 goto unlock;
5145 }
5146
5147 hci_req_init(&req, hdev);
5148
5149 memset(&hci_cp, 0, sizeof(hci_cp));
5150 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5151
5152 if (conn) {
5153 hci_conn_hold(conn);
5154 cmd->user_data = conn;
5155
5156 hci_cp.handle = cpu_to_le16(conn->handle);
5157 hci_cp.which = 0x01; /* Piconet clock */
5158 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5159 }
5160
5161 err = hci_req_run(&req, get_clock_info_complete);
5162 if (err < 0)
5163 mgmt_pending_remove(cmd);
5164
5165unlock:
5166 hci_dev_unlock(hdev);
5167 return err;
5168}
5169
Marcel Holtmann8afef092014-06-29 22:28:34 +02005170static void device_added(struct sock *sk, struct hci_dev *hdev,
5171 bdaddr_t *bdaddr, u8 type, u8 action)
5172{
5173 struct mgmt_ev_device_added ev;
5174
5175 bacpy(&ev.addr.bdaddr, bdaddr);
5176 ev.addr.type = type;
5177 ev.action = action;
5178
5179 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5180}
5181
Marcel Holtmann2faade52014-06-29 19:44:03 +02005182static int add_device(struct sock *sk, struct hci_dev *hdev,
5183 void *data, u16 len)
5184{
5185 struct mgmt_cp_add_device *cp = data;
5186 u8 auto_conn, addr_type;
5187 int err;
5188
5189 BT_DBG("%s", hdev->name);
5190
5191 if (!bdaddr_type_is_le(cp->addr.type) ||
5192 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5193 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5194 MGMT_STATUS_INVALID_PARAMS,
5195 &cp->addr, sizeof(cp->addr));
5196
5197 if (cp->action != 0x00 && cp->action != 0x01)
5198 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5199 MGMT_STATUS_INVALID_PARAMS,
5200 &cp->addr, sizeof(cp->addr));
5201
5202 hci_dev_lock(hdev);
5203
5204 if (cp->addr.type == BDADDR_LE_PUBLIC)
5205 addr_type = ADDR_LE_DEV_PUBLIC;
5206 else
5207 addr_type = ADDR_LE_DEV_RANDOM;
5208
5209 if (cp->action)
5210 auto_conn = HCI_AUTO_CONN_ALWAYS;
5211 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005212 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005213
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005214 /* If the connection parameters don't exist for this device,
5215 * they will be created and configured with defaults.
5216 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005217 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5218 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005219 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5220 MGMT_STATUS_FAILED,
5221 &cp->addr, sizeof(cp->addr));
5222 goto unlock;
5223 }
5224
Marcel Holtmann8afef092014-06-29 22:28:34 +02005225 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5226
Marcel Holtmann2faade52014-06-29 19:44:03 +02005227 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5228 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5229
5230unlock:
5231 hci_dev_unlock(hdev);
5232 return err;
5233}
5234
Marcel Holtmann8afef092014-06-29 22:28:34 +02005235static void device_removed(struct sock *sk, struct hci_dev *hdev,
5236 bdaddr_t *bdaddr, u8 type)
5237{
5238 struct mgmt_ev_device_removed ev;
5239
5240 bacpy(&ev.addr.bdaddr, bdaddr);
5241 ev.addr.type = type;
5242
5243 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5244}
5245
Marcel Holtmann2faade52014-06-29 19:44:03 +02005246static int remove_device(struct sock *sk, struct hci_dev *hdev,
5247 void *data, u16 len)
5248{
5249 struct mgmt_cp_remove_device *cp = data;
5250 int err;
5251
5252 BT_DBG("%s", hdev->name);
5253
5254 hci_dev_lock(hdev);
5255
5256 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005257 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005258 u8 addr_type;
5259
5260 if (!bdaddr_type_is_le(cp->addr.type)) {
5261 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5262 MGMT_STATUS_INVALID_PARAMS,
5263 &cp->addr, sizeof(cp->addr));
5264 goto unlock;
5265 }
5266
5267 if (cp->addr.type == BDADDR_LE_PUBLIC)
5268 addr_type = ADDR_LE_DEV_PUBLIC;
5269 else
5270 addr_type = ADDR_LE_DEV_RANDOM;
5271
Johan Hedbergc71593d2014-07-02 17:37:28 +03005272 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5273 addr_type);
5274 if (!params) {
5275 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5276 MGMT_STATUS_INVALID_PARAMS,
5277 &cp->addr, sizeof(cp->addr));
5278 goto unlock;
5279 }
5280
5281 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5282 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5283 MGMT_STATUS_INVALID_PARAMS,
5284 &cp->addr, sizeof(cp->addr));
5285 goto unlock;
5286 }
5287
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005288 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005289 list_del(&params->list);
5290 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005291 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005292
5293 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005294 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005295 struct hci_conn_params *p, *tmp;
5296
Marcel Holtmann2faade52014-06-29 19:44:03 +02005297 if (cp->addr.type) {
5298 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5299 MGMT_STATUS_INVALID_PARAMS,
5300 &cp->addr, sizeof(cp->addr));
5301 goto unlock;
5302 }
5303
Johan Hedberg19de0822014-07-06 13:06:51 +03005304 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5305 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5306 continue;
5307 device_removed(sk, hdev, &p->addr, p->addr_type);
5308 list_del(&p->action);
5309 list_del(&p->list);
5310 kfree(p);
5311 }
5312
5313 BT_DBG("All LE connection parameters were removed");
5314
5315 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005316 }
5317
5318 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5319 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5320
5321unlock:
5322 hci_dev_unlock(hdev);
5323 return err;
5324}
5325
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005326static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5327 u16 len)
5328{
5329 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005330 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5331 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005332 u16 param_count, expected_len;
5333 int i;
5334
5335 if (!lmp_le_capable(hdev))
5336 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5337 MGMT_STATUS_NOT_SUPPORTED);
5338
5339 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005340 if (param_count > max_param_count) {
5341 BT_ERR("load_conn_param: too big param_count value %u",
5342 param_count);
5343 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5344 MGMT_STATUS_INVALID_PARAMS);
5345 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005346
5347 expected_len = sizeof(*cp) + param_count *
5348 sizeof(struct mgmt_conn_param);
5349 if (expected_len != len) {
5350 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5351 expected_len, len);
5352 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5353 MGMT_STATUS_INVALID_PARAMS);
5354 }
5355
5356 BT_DBG("%s param_count %u", hdev->name, param_count);
5357
5358 hci_dev_lock(hdev);
5359
5360 hci_conn_params_clear_disabled(hdev);
5361
5362 for (i = 0; i < param_count; i++) {
5363 struct mgmt_conn_param *param = &cp->params[i];
5364 struct hci_conn_params *hci_param;
5365 u16 min, max, latency, timeout;
5366 u8 addr_type;
5367
5368 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5369 param->addr.type);
5370
5371 if (param->addr.type == BDADDR_LE_PUBLIC) {
5372 addr_type = ADDR_LE_DEV_PUBLIC;
5373 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5374 addr_type = ADDR_LE_DEV_RANDOM;
5375 } else {
5376 BT_ERR("Ignoring invalid connection parameters");
5377 continue;
5378 }
5379
5380 min = le16_to_cpu(param->min_interval);
5381 max = le16_to_cpu(param->max_interval);
5382 latency = le16_to_cpu(param->latency);
5383 timeout = le16_to_cpu(param->timeout);
5384
5385 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5386 min, max, latency, timeout);
5387
5388 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5389 BT_ERR("Ignoring invalid connection parameters");
5390 continue;
5391 }
5392
5393 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5394 addr_type);
5395 if (!hci_param) {
5396 BT_ERR("Failed to add connection parameters");
5397 continue;
5398 }
5399
5400 hci_param->conn_min_interval = min;
5401 hci_param->conn_max_interval = max;
5402 hci_param->conn_latency = latency;
5403 hci_param->supervision_timeout = timeout;
5404 }
5405
5406 hci_dev_unlock(hdev);
5407
5408 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5409}
5410
Marcel Holtmanndbece372014-07-04 18:11:55 +02005411static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5412 void *data, u16 len)
5413{
5414 struct mgmt_cp_set_external_config *cp = data;
5415 bool changed;
5416 int err;
5417
5418 BT_DBG("%s", hdev->name);
5419
5420 if (hdev_is_powered(hdev))
5421 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5422 MGMT_STATUS_REJECTED);
5423
5424 if (cp->config != 0x00 && cp->config != 0x01)
5425 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5426 MGMT_STATUS_INVALID_PARAMS);
5427
5428 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5429 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5430 MGMT_STATUS_NOT_SUPPORTED);
5431
5432 hci_dev_lock(hdev);
5433
5434 if (cp->config)
5435 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5436 &hdev->dev_flags);
5437 else
5438 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5439 &hdev->dev_flags);
5440
5441 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5442 if (err < 0)
5443 goto unlock;
5444
5445 if (!changed)
5446 goto unlock;
5447
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005448 err = new_options(hdev, sk);
5449
Marcel Holtmanndbece372014-07-04 18:11:55 +02005450 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5451 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005452
5453 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5454 set_bit(HCI_CONFIG, &hdev->dev_flags);
5455 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5456
5457 queue_work(hdev->req_workqueue, &hdev->power_on);
5458 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005459 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005460 mgmt_index_added(hdev);
5461 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005462 }
5463
5464unlock:
5465 hci_dev_unlock(hdev);
5466 return err;
5467}
5468
Marcel Holtmann9713c172014-07-06 12:11:15 +02005469static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5470 void *data, u16 len)
5471{
5472 struct mgmt_cp_set_public_address *cp = data;
5473 bool changed;
5474 int err;
5475
5476 BT_DBG("%s", hdev->name);
5477
5478 if (hdev_is_powered(hdev))
5479 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5480 MGMT_STATUS_REJECTED);
5481
5482 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5483 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5484 MGMT_STATUS_INVALID_PARAMS);
5485
5486 if (!hdev->set_bdaddr)
5487 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5488 MGMT_STATUS_NOT_SUPPORTED);
5489
5490 hci_dev_lock(hdev);
5491
5492 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5493 bacpy(&hdev->public_addr, &cp->bdaddr);
5494
5495 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5496 if (err < 0)
5497 goto unlock;
5498
5499 if (!changed)
5500 goto unlock;
5501
5502 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5503 err = new_options(hdev, sk);
5504
5505 if (is_configured(hdev)) {
5506 mgmt_index_removed(hdev);
5507
5508 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5509
5510 set_bit(HCI_CONFIG, &hdev->dev_flags);
5511 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5512
5513 queue_work(hdev->req_workqueue, &hdev->power_on);
5514 }
5515
5516unlock:
5517 hci_dev_unlock(hdev);
5518 return err;
5519}
5520
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005521static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005522 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5523 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005524 bool var_len;
5525 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005526} mgmt_handlers[] = {
5527 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005528 { read_version, false, MGMT_READ_VERSION_SIZE },
5529 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5530 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5531 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5532 { set_powered, false, MGMT_SETTING_SIZE },
5533 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5534 { set_connectable, false, MGMT_SETTING_SIZE },
5535 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5536 { set_pairable, false, MGMT_SETTING_SIZE },
5537 { set_link_security, false, MGMT_SETTING_SIZE },
5538 { set_ssp, false, MGMT_SETTING_SIZE },
5539 { set_hs, false, MGMT_SETTING_SIZE },
5540 { set_le, false, MGMT_SETTING_SIZE },
5541 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5542 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5543 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5544 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5545 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5546 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5547 { disconnect, false, MGMT_DISCONNECT_SIZE },
5548 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5549 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5550 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5551 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5552 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5553 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5554 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5555 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5556 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5557 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5558 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5559 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005560 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005561 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5562 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5563 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5564 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5565 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5566 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005567 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005568 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005569 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005570 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005571 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005572 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005573 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005574 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005575 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005576 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005577 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005578 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5579 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005580 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5581 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005582 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005583 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005584 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005585};
5586
Johan Hedberg03811012010-12-08 00:21:06 +02005587int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5588{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005589 void *buf;
5590 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005591 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005592 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005593 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005594 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005595 int err;
5596
5597 BT_DBG("got %zu bytes", msglen);
5598
5599 if (msglen < sizeof(*hdr))
5600 return -EINVAL;
5601
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005602 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005603 if (!buf)
5604 return -ENOMEM;
5605
5606 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5607 err = -EFAULT;
5608 goto done;
5609 }
5610
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005611 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005612 opcode = __le16_to_cpu(hdr->opcode);
5613 index = __le16_to_cpu(hdr->index);
5614 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005615
5616 if (len != msglen - sizeof(*hdr)) {
5617 err = -EINVAL;
5618 goto done;
5619 }
5620
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005621 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005622 hdev = hci_dev_get(index);
5623 if (!hdev) {
5624 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005625 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005626 goto done;
5627 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005628
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005629 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005630 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005631 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005632 err = cmd_status(sk, index, opcode,
5633 MGMT_STATUS_INVALID_INDEX);
5634 goto done;
5635 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005636
5637 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005638 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005639 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5640 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005641 err = cmd_status(sk, index, opcode,
5642 MGMT_STATUS_INVALID_INDEX);
5643 goto done;
5644 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005645 }
5646
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005647 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005648 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005649 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005650 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005651 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005652 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005653 }
5654
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005655 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5656 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5657 err = cmd_status(sk, index, opcode,
5658 MGMT_STATUS_INVALID_INDEX);
5659 goto done;
5660 }
5661
5662 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5663 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005664 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005665 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005666 goto done;
5667 }
5668
Johan Hedbergbe22b542012-03-01 22:24:41 +02005669 handler = &mgmt_handlers[opcode];
5670
5671 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005672 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005673 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005674 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005675 goto done;
5676 }
5677
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005678 if (hdev)
5679 mgmt_init_hdev(sk, hdev);
5680
5681 cp = buf + sizeof(*hdr);
5682
Johan Hedbergbe22b542012-03-01 22:24:41 +02005683 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005684 if (err < 0)
5685 goto done;
5686
Johan Hedberg03811012010-12-08 00:21:06 +02005687 err = msglen;
5688
5689done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005690 if (hdev)
5691 hci_dev_put(hdev);
5692
Johan Hedberg03811012010-12-08 00:21:06 +02005693 kfree(buf);
5694 return err;
5695}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005696
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005697void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005698{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005699 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005700 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005701
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005702 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5703 return;
5704
5705 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5706 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5707 else
5708 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005709}
5710
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005711void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005712{
Johan Hedberg5f159032012-03-02 03:13:19 +02005713 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005714
Marcel Holtmann1514b892013-10-06 08:25:01 -07005715 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005716 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005717
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005718 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5719 return;
5720
Johan Hedberg744cf192011-11-08 20:40:14 +02005721 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005722
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02005723 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5724 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5725 else
5726 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005727}
5728
Andre Guedes6046dc32014-02-26 20:21:51 -03005729/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005730static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005731{
5732 struct hci_conn_params *p;
5733
5734 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005735 /* Needed for AUTO_OFF case where might not "really"
5736 * have been powered off.
5737 */
5738 list_del_init(&p->action);
5739
5740 switch (p->auto_connect) {
5741 case HCI_AUTO_CONN_ALWAYS:
5742 list_add(&p->action, &hdev->pend_le_conns);
5743 break;
5744 case HCI_AUTO_CONN_REPORT:
5745 list_add(&p->action, &hdev->pend_le_reports);
5746 break;
5747 default:
5748 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005749 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005750 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005751
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005752 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005753}
5754
Johan Hedberg229ab392013-03-15 17:06:53 -05005755static void powered_complete(struct hci_dev *hdev, u8 status)
5756{
5757 struct cmd_lookup match = { NULL, hdev };
5758
5759 BT_DBG("status 0x%02x", status);
5760
5761 hci_dev_lock(hdev);
5762
Johan Hedbergd7347f32014-07-04 12:37:23 +03005763 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005764
Johan Hedberg229ab392013-03-15 17:06:53 -05005765 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5766
5767 new_settings(hdev, match.sk);
5768
5769 hci_dev_unlock(hdev);
5770
5771 if (match.sk)
5772 sock_put(match.sk);
5773}
5774
Johan Hedberg70da6242013-03-15 17:06:51 -05005775static int powered_update_hci(struct hci_dev *hdev)
5776{
Johan Hedberg890ea892013-03-15 17:06:52 -05005777 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005778 u8 link_sec;
5779
Johan Hedberg890ea892013-03-15 17:06:52 -05005780 hci_req_init(&req, hdev);
5781
Johan Hedberg70da6242013-03-15 17:06:51 -05005782 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5783 !lmp_host_ssp_capable(hdev)) {
5784 u8 ssp = 1;
5785
Johan Hedberg890ea892013-03-15 17:06:52 -05005786 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005787 }
5788
Johan Hedbergc73eee92013-04-19 18:35:21 +03005789 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5790 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005791 struct hci_cp_write_le_host_supported cp;
5792
5793 cp.le = 1;
5794 cp.simul = lmp_le_br_capable(hdev);
5795
5796 /* Check first if we already have the right
5797 * host state (host features set)
5798 */
5799 if (cp.le != lmp_host_le_capable(hdev) ||
5800 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005801 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5802 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005803 }
5804
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005805 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005806 /* Make sure the controller has a good default for
5807 * advertising data. This also applies to the case
5808 * where BR/EDR was toggled during the AUTO_OFF phase.
5809 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005810 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005811 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005812 update_scan_rsp_data(&req);
5813 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005814
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005815 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5816 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005817 }
5818
Johan Hedberg70da6242013-03-15 17:06:51 -05005819 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5820 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005821 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5822 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005823
5824 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005825 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5826 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005827 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005828 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005829 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005830 }
5831
Johan Hedberg229ab392013-03-15 17:06:53 -05005832 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005833}
5834
Johan Hedberg744cf192011-11-08 20:40:14 +02005835int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005836{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005837 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005838 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5839 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005840 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005841
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005842 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5843 return 0;
5844
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005845 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005846 if (powered_update_hci(hdev) == 0)
5847 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005848
Johan Hedberg229ab392013-03-15 17:06:53 -05005849 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5850 &match);
5851 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005852 }
5853
Johan Hedberg229ab392013-03-15 17:06:53 -05005854 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5855 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5856
5857 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5858 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5859 zero_cod, sizeof(zero_cod), NULL);
5860
5861new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005862 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005863
5864 if (match.sk)
5865 sock_put(match.sk);
5866
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005867 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005868}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005869
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005870void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005871{
5872 struct pending_cmd *cmd;
5873 u8 status;
5874
5875 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5876 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005877 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005878
5879 if (err == -ERFKILL)
5880 status = MGMT_STATUS_RFKILLED;
5881 else
5882 status = MGMT_STATUS_FAILED;
5883
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005884 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005885
5886 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005887}
5888
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005889void mgmt_discoverable_timeout(struct hci_dev *hdev)
5890{
5891 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005892
5893 hci_dev_lock(hdev);
5894
5895 /* When discoverable timeout triggers, then just make sure
5896 * the limited discoverable flag is cleared. Even in the case
5897 * of a timeout triggered from general discoverable, it is
5898 * safe to unconditionally clear the flag.
5899 */
5900 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005901 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005902
5903 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005904 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5905 u8 scan = SCAN_PAGE;
5906 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5907 sizeof(scan), &scan);
5908 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005909 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005910 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005911 hci_req_run(&req, NULL);
5912
5913 hdev->discov_timeout = 0;
5914
Johan Hedberg9a43e252013-10-20 19:00:07 +03005915 new_settings(hdev, NULL);
5916
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005917 hci_dev_unlock(hdev);
5918}
5919
Marcel Holtmann86a75642013-10-15 06:33:54 -07005920void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005921{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005922 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005923
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005924 /* Nothing needed here if there's a pending command since that
5925 * commands request completion callback takes care of everything
5926 * necessary.
5927 */
5928 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005929 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005930
Johan Hedbergbd107992014-02-24 14:52:19 +02005931 /* Powering off may clear the scan mode - don't let that interfere */
5932 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5933 return;
5934
Johan Hedberg9a43e252013-10-20 19:00:07 +03005935 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005936 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005937 } else {
5938 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005939 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005940 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005941
Johan Hedberg9a43e252013-10-20 19:00:07 +03005942 if (changed) {
5943 struct hci_request req;
5944
5945 /* In case this change in discoverable was triggered by
5946 * a disabling of connectable there could be a need to
5947 * update the advertising flags.
5948 */
5949 hci_req_init(&req, hdev);
5950 update_adv_data(&req);
5951 hci_req_run(&req, NULL);
5952
Marcel Holtmann86a75642013-10-15 06:33:54 -07005953 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005954 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005955}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005956
Marcel Holtmanna3309162013-10-15 06:33:55 -07005957void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005958{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005959 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005960
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005961 /* Nothing needed here if there's a pending command since that
5962 * commands request completion callback takes care of everything
5963 * necessary.
5964 */
5965 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005966 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005967
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005968 /* Powering off may clear the scan mode - don't let that interfere */
5969 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5970 return;
5971
Marcel Holtmanna3309162013-10-15 06:33:55 -07005972 if (connectable)
5973 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5974 else
5975 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005976
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005977 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005978 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005979}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005980
Johan Hedberg778b2352014-02-24 14:52:17 +02005981void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5982{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005983 /* Powering off may stop advertising - don't let that interfere */
5984 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5985 return;
5986
Johan Hedberg778b2352014-02-24 14:52:17 +02005987 if (advertising)
5988 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5989 else
5990 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5991}
5992
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005993void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005994{
Johan Hedbergca69b792011-11-11 18:10:00 +02005995 u8 mgmt_err = mgmt_status(status);
5996
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005997 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005998 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005999 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006000
6001 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02006002 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006003 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006004}
6005
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006006void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6007 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006008{
Johan Hedberg86742e12011-11-07 23:13:38 +02006009 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006010
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006011 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006012
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006013 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006014 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006015 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006016 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006017 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006018 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006019
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006020 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006021}
Johan Hedbergf7520542011-01-20 12:34:39 +02006022
Johan Hedbergd7b25452014-05-23 13:19:53 +03006023static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6024{
6025 if (ltk->authenticated)
6026 return MGMT_LTK_AUTHENTICATED;
6027
6028 return MGMT_LTK_UNAUTHENTICATED;
6029}
6030
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006031void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006032{
6033 struct mgmt_ev_new_long_term_key ev;
6034
6035 memset(&ev, 0, sizeof(ev));
6036
Marcel Holtmann5192d302014-02-19 17:11:58 -08006037 /* Devices using resolvable or non-resolvable random addresses
6038 * without providing an indentity resolving key don't require
6039 * to store long term keys. Their addresses will change the
6040 * next time around.
6041 *
6042 * Only when a remote device provides an identity address
6043 * make sure the long term key is stored. If the remote
6044 * identity is known, the long term keys are internally
6045 * mapped to the identity address. So allow static random
6046 * and public addresses here.
6047 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006048 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6049 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6050 ev.store_hint = 0x00;
6051 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006052 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006053
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006054 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006055 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006056 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006057 ev.key.enc_size = key->enc_size;
6058 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006059 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006060
Johan Hedberg2ceba532014-06-16 19:25:16 +03006061 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006062 ev.key.master = 1;
6063
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006064 memcpy(ev.key.val, key->val, sizeof(key->val));
6065
Marcel Holtmann083368f2013-10-15 14:26:29 -07006066 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006067}
6068
Johan Hedberg95fbac82014-02-19 15:18:31 +02006069void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6070{
6071 struct mgmt_ev_new_irk ev;
6072
6073 memset(&ev, 0, sizeof(ev));
6074
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006075 /* For identity resolving keys from devices that are already
6076 * using a public address or static random address, do not
6077 * ask for storing this key. The identity resolving key really
6078 * is only mandatory for devices using resovlable random
6079 * addresses.
6080 *
6081 * Storing all identity resolving keys has the downside that
6082 * they will be also loaded on next boot of they system. More
6083 * identity resolving keys, means more time during scanning is
6084 * needed to actually resolve these addresses.
6085 */
6086 if (bacmp(&irk->rpa, BDADDR_ANY))
6087 ev.store_hint = 0x01;
6088 else
6089 ev.store_hint = 0x00;
6090
Johan Hedberg95fbac82014-02-19 15:18:31 +02006091 bacpy(&ev.rpa, &irk->rpa);
6092 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6093 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6094 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6095
6096 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6097}
6098
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006099void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6100 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006101{
6102 struct mgmt_ev_new_csrk ev;
6103
6104 memset(&ev, 0, sizeof(ev));
6105
6106 /* Devices using resolvable or non-resolvable random addresses
6107 * without providing an indentity resolving key don't require
6108 * to store signature resolving keys. Their addresses will change
6109 * the next time around.
6110 *
6111 * Only when a remote device provides an identity address
6112 * make sure the signature resolving key is stored. So allow
6113 * static random and public addresses here.
6114 */
6115 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6116 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6117 ev.store_hint = 0x00;
6118 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006119 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006120
6121 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6122 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6123 ev.key.master = csrk->master;
6124 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6125
6126 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6127}
6128
Andre Guedesffb5a8272014-07-01 18:10:11 -03006129void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006130 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6131 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006132{
6133 struct mgmt_ev_new_conn_param ev;
6134
Johan Hedbergc103aea2014-07-02 17:37:34 +03006135 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6136 return;
6137
Andre Guedesffb5a8272014-07-01 18:10:11 -03006138 memset(&ev, 0, sizeof(ev));
6139 bacpy(&ev.addr.bdaddr, bdaddr);
6140 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006141 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006142 ev.min_interval = cpu_to_le16(min_interval);
6143 ev.max_interval = cpu_to_le16(max_interval);
6144 ev.latency = cpu_to_le16(latency);
6145 ev.timeout = cpu_to_le16(timeout);
6146
6147 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6148}
6149
Marcel Holtmann94933992013-10-15 10:26:39 -07006150static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6151 u8 data_len)
6152{
6153 eir[eir_len++] = sizeof(type) + data_len;
6154 eir[eir_len++] = type;
6155 memcpy(&eir[eir_len], data, data_len);
6156 eir_len += data_len;
6157
6158 return eir_len;
6159}
6160
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006161void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6162 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6163 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006164{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006165 char buf[512];
6166 struct mgmt_ev_device_connected *ev = (void *) buf;
6167 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006168
Johan Hedbergb644ba32012-01-17 21:48:47 +02006169 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006170 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006171
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006172 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006173
Johan Hedbergb644ba32012-01-17 21:48:47 +02006174 if (name_len > 0)
6175 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006176 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006177
6178 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006179 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006180 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006181
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006182 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006183
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006184 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6185 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006186}
6187
Johan Hedberg8962ee72011-01-20 12:40:27 +02006188static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6189{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006190 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006191 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006192 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006193
Johan Hedberg88c3df12012-02-09 14:27:38 +02006194 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6195 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006196
Johan Hedbergaee9b212012-02-18 15:07:59 +02006197 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006198 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006199
6200 *sk = cmd->sk;
6201 sock_hold(*sk);
6202
Johan Hedberga664b5b2011-02-19 12:06:02 -03006203 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006204}
6205
Johan Hedberg124f6e32012-02-09 13:50:12 +02006206static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006207{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006208 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006209 struct mgmt_cp_unpair_device *cp = cmd->param;
6210 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006211
6212 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006213 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6214 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006215
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006216 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6217
Johan Hedbergaee9b212012-02-18 15:07:59 +02006218 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006219
6220 mgmt_pending_remove(cmd);
6221}
6222
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006223void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006224 u8 link_type, u8 addr_type, u8 reason,
6225 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006226{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006227 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006228 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006229 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006230
Johan Hedberg8b064a32014-02-24 14:52:22 +02006231 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6232 if (power_off) {
6233 struct mgmt_mode *cp = power_off->param;
6234
6235 /* The connection is still in hci_conn_hash so test for 1
6236 * instead of 0 to know if this is the last one.
6237 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006238 if (!cp->val && hci_conn_count(hdev) == 1) {
6239 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006240 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006241 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006242 }
6243
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006244 if (!mgmt_connected)
6245 return;
6246
Andre Guedes57eb7762013-10-30 19:01:41 -03006247 if (link_type != ACL_LINK && link_type != LE_LINK)
6248 return;
6249
Johan Hedberg744cf192011-11-08 20:40:14 +02006250 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006251
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006252 bacpy(&ev.addr.bdaddr, bdaddr);
6253 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6254 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006255
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006256 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006257
6258 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006259 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006260
Johan Hedberg124f6e32012-02-09 13:50:12 +02006261 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006262 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006263}
6264
Marcel Holtmann78929242013-10-06 23:55:47 -07006265void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6266 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006267{
Andre Guedes3655bba2013-10-30 19:01:40 -03006268 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6269 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006270 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006271 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006272
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006273 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6274 hdev);
6275
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006276 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006277 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006278 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006279
Andre Guedes3655bba2013-10-30 19:01:40 -03006280 cp = cmd->param;
6281
6282 if (bacmp(bdaddr, &cp->addr.bdaddr))
6283 return;
6284
6285 if (cp->addr.type != bdaddr_type)
6286 return;
6287
Johan Hedberg88c3df12012-02-09 14:27:38 +02006288 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006289 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006290
Marcel Holtmann78929242013-10-06 23:55:47 -07006291 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6292 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006293
Johan Hedberga664b5b2011-02-19 12:06:02 -03006294 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006295}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006296
Marcel Holtmann445608d2013-10-06 23:55:48 -07006297void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6298 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006299{
6300 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006301 struct pending_cmd *power_off;
6302
6303 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6304 if (power_off) {
6305 struct mgmt_mode *cp = power_off->param;
6306
6307 /* The connection is still in hci_conn_hash so test for 1
6308 * instead of 0 to know if this is the last one.
6309 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006310 if (!cp->val && hci_conn_count(hdev) == 1) {
6311 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006312 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006313 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006314 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006315
Johan Hedberg4c659c32011-11-07 23:13:39 +02006316 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006317 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006318 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006319
Marcel Holtmann445608d2013-10-06 23:55:48 -07006320 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006321}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006322
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006323void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006324{
6325 struct mgmt_ev_pin_code_request ev;
6326
Johan Hedbergd8457692012-02-17 14:24:57 +02006327 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006328 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006329 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006330
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006331 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006332}
6333
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006334void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6335 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006336{
6337 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006338 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006339
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006340 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006341 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006342 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006343
Johan Hedbergd8457692012-02-17 14:24:57 +02006344 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006345 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006346
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006347 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6348 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006349
Johan Hedberga664b5b2011-02-19 12:06:02 -03006350 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006351}
6352
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006353void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6354 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006355{
6356 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006357 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006358
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006359 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006360 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006361 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006362
Johan Hedbergd8457692012-02-17 14:24:57 +02006363 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006364 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006365
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006366 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6367 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006368
Johan Hedberga664b5b2011-02-19 12:06:02 -03006369 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006370}
Johan Hedberga5c29682011-02-19 12:05:57 -03006371
Johan Hedberg744cf192011-11-08 20:40:14 +02006372int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006373 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006374 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006375{
6376 struct mgmt_ev_user_confirm_request ev;
6377
Johan Hedberg744cf192011-11-08 20:40:14 +02006378 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006379
Johan Hedberg272d90d2012-02-09 15:26:12 +02006380 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006381 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006382 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006383 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006384
Johan Hedberg744cf192011-11-08 20:40:14 +02006385 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006386 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006387}
6388
Johan Hedberg272d90d2012-02-09 15:26:12 +02006389int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006390 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006391{
6392 struct mgmt_ev_user_passkey_request ev;
6393
6394 BT_DBG("%s", hdev->name);
6395
Johan Hedberg272d90d2012-02-09 15:26:12 +02006396 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006397 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006398
6399 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006400 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006401}
6402
Brian Gix0df4c182011-11-16 13:53:13 -08006403static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006404 u8 link_type, u8 addr_type, u8 status,
6405 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006406{
6407 struct pending_cmd *cmd;
6408 struct mgmt_rp_user_confirm_reply rp;
6409 int err;
6410
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006411 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006412 if (!cmd)
6413 return -ENOENT;
6414
Johan Hedberg272d90d2012-02-09 15:26:12 +02006415 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006416 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006417 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006418 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006419
Johan Hedberga664b5b2011-02-19 12:06:02 -03006420 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006421
6422 return err;
6423}
6424
Johan Hedberg744cf192011-11-08 20:40:14 +02006425int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006426 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006427{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006428 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006429 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006430}
6431
Johan Hedberg272d90d2012-02-09 15:26:12 +02006432int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006433 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006434{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006435 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006436 status,
6437 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006438}
Johan Hedberg2a611692011-02-19 12:06:00 -03006439
Brian Gix604086b2011-11-23 08:28:33 -08006440int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006441 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006442{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006443 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006444 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006445}
6446
Johan Hedberg272d90d2012-02-09 15:26:12 +02006447int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006448 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006449{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006450 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006451 status,
6452 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006453}
6454
Johan Hedberg92a25252012-09-06 18:39:26 +03006455int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6456 u8 link_type, u8 addr_type, u32 passkey,
6457 u8 entered)
6458{
6459 struct mgmt_ev_passkey_notify ev;
6460
6461 BT_DBG("%s", hdev->name);
6462
6463 bacpy(&ev.addr.bdaddr, bdaddr);
6464 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6465 ev.passkey = __cpu_to_le32(passkey);
6466 ev.entered = entered;
6467
6468 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6469}
6470
Marcel Holtmanne5460992013-10-15 14:26:23 -07006471void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6472 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006473{
6474 struct mgmt_ev_auth_failed ev;
6475
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006476 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006477 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006478 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006479
Marcel Holtmanne5460992013-10-15 14:26:23 -07006480 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006481}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006482
Marcel Holtmann464996a2013-10-15 14:26:24 -07006483void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006484{
6485 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006486 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006487
6488 if (status) {
6489 u8 mgmt_err = mgmt_status(status);
6490 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006491 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006492 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006493 }
6494
Marcel Holtmann464996a2013-10-15 14:26:24 -07006495 if (test_bit(HCI_AUTH, &hdev->flags))
6496 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6497 &hdev->dev_flags);
6498 else
6499 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6500 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006501
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006502 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006503 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006504
Johan Hedberg47990ea2012-02-22 11:58:37 +02006505 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006506 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006507
6508 if (match.sk)
6509 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006510}
6511
Johan Hedberg890ea892013-03-15 17:06:52 -05006512static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006513{
Johan Hedberg890ea892013-03-15 17:06:52 -05006514 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006515 struct hci_cp_write_eir cp;
6516
Johan Hedberg976eb202012-10-24 21:12:01 +03006517 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006518 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006519
Johan Hedbergc80da272012-02-22 15:38:48 +02006520 memset(hdev->eir, 0, sizeof(hdev->eir));
6521
Johan Hedbergcacaf522012-02-21 00:52:42 +02006522 memset(&cp, 0, sizeof(cp));
6523
Johan Hedberg890ea892013-03-15 17:06:52 -05006524 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006525}
6526
Marcel Holtmann3e248562013-10-15 14:26:25 -07006527void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006528{
6529 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006530 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006531 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006532
6533 if (status) {
6534 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006535
6536 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006537 &hdev->dev_flags)) {
6538 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006539 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006540 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006541
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006542 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6543 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006544 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006545 }
6546
6547 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006548 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006549 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006550 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6551 if (!changed)
6552 changed = test_and_clear_bit(HCI_HS_ENABLED,
6553 &hdev->dev_flags);
6554 else
6555 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006556 }
6557
6558 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6559
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006560 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006561 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006562
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006563 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006564 sock_put(match.sk);
6565
Johan Hedberg890ea892013-03-15 17:06:52 -05006566 hci_req_init(&req, hdev);
6567
Johan Hedberg37699722014-06-24 14:00:27 +03006568 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6569 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6570 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6571 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006572 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006573 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006574 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006575 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006576
6577 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006578}
6579
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006580void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6581{
6582 struct cmd_lookup match = { NULL, hdev };
6583 bool changed = false;
6584
6585 if (status) {
6586 u8 mgmt_err = mgmt_status(status);
6587
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006588 if (enable) {
6589 if (test_and_clear_bit(HCI_SC_ENABLED,
6590 &hdev->dev_flags))
6591 new_settings(hdev, NULL);
6592 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6593 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006594
6595 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6596 cmd_status_rsp, &mgmt_err);
6597 return;
6598 }
6599
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006600 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006601 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006602 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006603 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006604 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6605 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006606
6607 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6608 settings_rsp, &match);
6609
6610 if (changed)
6611 new_settings(hdev, match.sk);
6612
6613 if (match.sk)
6614 sock_put(match.sk);
6615}
6616
Johan Hedberg92da6092013-03-15 17:06:55 -05006617static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006618{
6619 struct cmd_lookup *match = data;
6620
Johan Hedberg90e70452012-02-23 23:09:40 +02006621 if (match->sk == NULL) {
6622 match->sk = cmd->sk;
6623 sock_hold(match->sk);
6624 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006625}
6626
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006627void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6628 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006629{
Johan Hedberg90e70452012-02-23 23:09:40 +02006630 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006631
Johan Hedberg92da6092013-03-15 17:06:55 -05006632 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6633 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6634 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006635
6636 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006637 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6638 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006639
6640 if (match.sk)
6641 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006642}
6643
Marcel Holtmann7667da32013-10-15 14:26:27 -07006644void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006645{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006646 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006647 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006648
Johan Hedberg13928972013-03-15 17:07:00 -05006649 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006650 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006651
6652 memset(&ev, 0, sizeof(ev));
6653 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006654 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006655
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006656 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006657 if (!cmd) {
6658 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006659
Johan Hedberg13928972013-03-15 17:07:00 -05006660 /* If this is a HCI command related to powering on the
6661 * HCI dev don't send any mgmt signals.
6662 */
6663 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006664 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006665 }
6666
Marcel Holtmann7667da32013-10-15 14:26:27 -07006667 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6668 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006669}
Szymon Jancc35938b2011-03-22 13:12:21 +01006670
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006671void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6672 u8 *randomizer192, u8 *hash256,
6673 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006674{
6675 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006676
Johan Hedberg744cf192011-11-08 20:40:14 +02006677 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006678
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006679 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006680 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006681 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006682
6683 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006684 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6685 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006686 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006687 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6688 hash256 && randomizer256) {
6689 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006690
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006691 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6692 memcpy(rp.randomizer192, randomizer192,
6693 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006694
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006695 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6696 memcpy(rp.randomizer256, randomizer256,
6697 sizeof(rp.randomizer256));
6698
6699 cmd_complete(cmd->sk, hdev->id,
6700 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6701 &rp, sizeof(rp));
6702 } else {
6703 struct mgmt_rp_read_local_oob_data rp;
6704
6705 memcpy(rp.hash, hash192, sizeof(rp.hash));
6706 memcpy(rp.randomizer, randomizer192,
6707 sizeof(rp.randomizer));
6708
6709 cmd_complete(cmd->sk, hdev->id,
6710 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6711 &rp, sizeof(rp));
6712 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006713 }
6714
6715 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006716}
Johan Hedberge17acd42011-03-30 23:57:16 +03006717
Marcel Holtmann901801b2013-10-06 23:55:51 -07006718void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006719 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6720 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006721{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006722 char buf[512];
6723 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006724 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006725
Johan Hedberg75ce2082014-07-02 22:42:01 +03006726 /* Don't send events for a non-kernel initiated discovery. With
6727 * LE one exception is if we have pend_le_reports > 0 in which
6728 * case we're doing passive scanning and want these events.
6729 */
6730 if (!hci_discovery_active(hdev)) {
6731 if (link_type == ACL_LINK)
6732 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006733 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006734 return;
6735 }
Andre Guedes12602d02013-04-30 15:29:40 -03006736
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006737 /* Make sure that the buffer is big enough. The 5 extra bytes
6738 * are for the potential CoD field.
6739 */
6740 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006741 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006742
Johan Hedberg1dc06092012-01-15 21:01:23 +02006743 memset(buf, 0, sizeof(buf));
6744
Johan Hedberg841c5642014-07-07 12:45:54 +03006745 bacpy(&ev->addr.bdaddr, bdaddr);
6746 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006747 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006748 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006749
Johan Hedberg1dc06092012-01-15 21:01:23 +02006750 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006751 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006752
Johan Hedberg1dc06092012-01-15 21:01:23 +02006753 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6754 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006755 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006756
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006757 if (scan_rsp_len > 0)
6758 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6759
6760 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6761 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006762
Marcel Holtmann901801b2013-10-06 23:55:51 -07006763 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006764}
Johan Hedberga88a9652011-03-30 13:18:12 +03006765
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006766void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6767 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006768{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006769 struct mgmt_ev_device_found *ev;
6770 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6771 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006772
Johan Hedbergb644ba32012-01-17 21:48:47 +02006773 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006774
Johan Hedbergb644ba32012-01-17 21:48:47 +02006775 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006776
Johan Hedbergb644ba32012-01-17 21:48:47 +02006777 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006778 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006779 ev->rssi = rssi;
6780
6781 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006782 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006783
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006784 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006785
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006786 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006787}
Johan Hedberg314b2382011-04-27 10:29:57 -04006788
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006789void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006790{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006791 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006792 struct pending_cmd *cmd;
6793
Andre Guedes343fb142011-11-22 17:14:19 -03006794 BT_DBG("%s discovering %u", hdev->name, discovering);
6795
Johan Hedberg164a6e72011-11-01 17:06:44 +02006796 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006797 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006798 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006799 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006800
6801 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006802 u8 type = hdev->discovery.type;
6803
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006804 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6805 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006806 mgmt_pending_remove(cmd);
6807 }
6808
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006809 memset(&ev, 0, sizeof(ev));
6810 ev.type = hdev->discovery.type;
6811 ev.discovering = discovering;
6812
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006813 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006814}
Antti Julku5e762442011-08-25 16:48:02 +03006815
Marcel Holtmann5976e602013-10-06 04:08:14 -07006816static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6817{
6818 BT_DBG("%s status %u", hdev->name, status);
6819
6820 /* Clear the advertising mgmt setting if we failed to re-enable it */
6821 if (status) {
6822 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006823 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006824 }
6825}
6826
6827void mgmt_reenable_advertising(struct hci_dev *hdev)
6828{
6829 struct hci_request req;
6830
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006831 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006832 return;
6833
6834 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6835 return;
6836
6837 hci_req_init(&req, hdev);
6838 enable_advertising(&req);
6839
6840 /* If this fails we have no option but to let user space know
6841 * that we've disabled advertising.
6842 */
6843 if (hci_req_run(&req, adv_enable_complete) < 0) {
6844 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006845 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006846 }
6847}