blob: dc8e428050d93e353ddcfbf5e8e0cd92669537f7 [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 Hedberg71290692015-02-20 13:26:23 +020032#include <net/bluetooth/hci_sock.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030033#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020034#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070035
Johan Hedberg0857dd32014-12-19 13:40:20 +020036#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070037#include "smp.h"
Johan Hedberga380b6c2015-03-17 13:48:48 +020038#include "mgmt_util.h"
Johan Hedberg03811012010-12-08 00:21:06 +020039
Johan Hedberg2da9c552012-02-17 14:39:28 +020040#define MGMT_VERSION 1
Marcel Holtmanne58627d2015-06-18 18:58:03 +020041#define MGMT_REVISION 10
Johan Hedberg02d98122010-12-13 21:07:04 +020042
Johan Hedberge70bb2e2012-02-13 16:59:33 +020043static const u16 mgmt_commands[] = {
44 MGMT_OP_READ_INDEX_LIST,
45 MGMT_OP_READ_INFO,
46 MGMT_OP_SET_POWERED,
47 MGMT_OP_SET_DISCOVERABLE,
48 MGMT_OP_SET_CONNECTABLE,
49 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030050 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020051 MGMT_OP_SET_LINK_SECURITY,
52 MGMT_OP_SET_SSP,
53 MGMT_OP_SET_HS,
54 MGMT_OP_SET_LE,
55 MGMT_OP_SET_DEV_CLASS,
56 MGMT_OP_SET_LOCAL_NAME,
57 MGMT_OP_ADD_UUID,
58 MGMT_OP_REMOVE_UUID,
59 MGMT_OP_LOAD_LINK_KEYS,
60 MGMT_OP_LOAD_LONG_TERM_KEYS,
61 MGMT_OP_DISCONNECT,
62 MGMT_OP_GET_CONNECTIONS,
63 MGMT_OP_PIN_CODE_REPLY,
64 MGMT_OP_PIN_CODE_NEG_REPLY,
65 MGMT_OP_SET_IO_CAPABILITY,
66 MGMT_OP_PAIR_DEVICE,
67 MGMT_OP_CANCEL_PAIR_DEVICE,
68 MGMT_OP_UNPAIR_DEVICE,
69 MGMT_OP_USER_CONFIRM_REPLY,
70 MGMT_OP_USER_CONFIRM_NEG_REPLY,
71 MGMT_OP_USER_PASSKEY_REPLY,
72 MGMT_OP_USER_PASSKEY_NEG_REPLY,
73 MGMT_OP_READ_LOCAL_OOB_DATA,
74 MGMT_OP_ADD_REMOTE_OOB_DATA,
75 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
76 MGMT_OP_START_DISCOVERY,
77 MGMT_OP_STOP_DISCOVERY,
78 MGMT_OP_CONFIRM_NAME,
79 MGMT_OP_BLOCK_DEVICE,
80 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070081 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030082 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030083 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070084 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070085 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080086 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080087 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020088 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020089 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020090 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030091 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020092 MGMT_OP_ADD_DEVICE,
93 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030094 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020095 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020096 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020097 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020098 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010099 MGMT_OP_START_SERVICE_DISCOVERY,
Marcel Holtmann4f0f1552015-03-14 22:43:19 -0700100 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann96f14742015-03-14 19:27:57 -0700101 MGMT_OP_READ_EXT_INDEX_LIST,
Marcel Holtmannd3d53052015-03-14 20:53:25 -0700102 MGMT_OP_READ_ADV_FEATURES,
Arman Uguray24b4f382015-03-23 15:57:12 -0700103 MGMT_OP_ADD_ADVERTISING,
Arman Ugurayda9293352015-03-23 15:57:13 -0700104 MGMT_OP_REMOVE_ADVERTISING,
Marcel Holtmann40b25fe2015-11-19 16:16:43 +0100105 MGMT_OP_GET_ADV_SIZE_INFO,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200106};
107
108static const u16 mgmt_events[] = {
109 MGMT_EV_CONTROLLER_ERROR,
110 MGMT_EV_INDEX_ADDED,
111 MGMT_EV_INDEX_REMOVED,
112 MGMT_EV_NEW_SETTINGS,
113 MGMT_EV_CLASS_OF_DEV_CHANGED,
114 MGMT_EV_LOCAL_NAME_CHANGED,
115 MGMT_EV_NEW_LINK_KEY,
116 MGMT_EV_NEW_LONG_TERM_KEY,
117 MGMT_EV_DEVICE_CONNECTED,
118 MGMT_EV_DEVICE_DISCONNECTED,
119 MGMT_EV_CONNECT_FAILED,
120 MGMT_EV_PIN_CODE_REQUEST,
121 MGMT_EV_USER_CONFIRM_REQUEST,
122 MGMT_EV_USER_PASSKEY_REQUEST,
123 MGMT_EV_AUTH_FAILED,
124 MGMT_EV_DEVICE_FOUND,
125 MGMT_EV_DISCOVERING,
126 MGMT_EV_DEVICE_BLOCKED,
127 MGMT_EV_DEVICE_UNBLOCKED,
128 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300129 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800130 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700131 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200132 MGMT_EV_DEVICE_ADDED,
133 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300134 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200135 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200136 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200137 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700138 MGMT_EV_EXT_INDEX_ADDED,
139 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700140 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Arman Uguray24b4f382015-03-23 15:57:12 -0700141 MGMT_EV_ADVERTISING_ADDED,
142 MGMT_EV_ADVERTISING_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200143};
144
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700145static const u16 mgmt_untrusted_commands[] = {
146 MGMT_OP_READ_INDEX_LIST,
147 MGMT_OP_READ_INFO,
148 MGMT_OP_READ_UNCONF_INDEX_LIST,
149 MGMT_OP_READ_CONFIG_INFO,
150 MGMT_OP_READ_EXT_INDEX_LIST,
151};
152
153static const u16 mgmt_untrusted_events[] = {
154 MGMT_EV_INDEX_ADDED,
155 MGMT_EV_INDEX_REMOVED,
156 MGMT_EV_NEW_SETTINGS,
157 MGMT_EV_CLASS_OF_DEV_CHANGED,
158 MGMT_EV_LOCAL_NAME_CHANGED,
159 MGMT_EV_UNCONF_INDEX_ADDED,
160 MGMT_EV_UNCONF_INDEX_REMOVED,
161 MGMT_EV_NEW_CONFIG_OPTIONS,
162 MGMT_EV_EXT_INDEX_ADDED,
163 MGMT_EV_EXT_INDEX_REMOVED,
164};
165
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800166#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200167
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200168#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
169 "\x00\x00\x00\x00\x00\x00\x00\x00"
170
Johan Hedbergca69b792011-11-11 18:10:00 +0200171/* HCI to MGMT error code conversion table */
172static u8 mgmt_status_table[] = {
173 MGMT_STATUS_SUCCESS,
174 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
175 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
176 MGMT_STATUS_FAILED, /* Hardware Failure */
177 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
178 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200179 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200180 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
181 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
182 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
183 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
184 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
185 MGMT_STATUS_BUSY, /* Command Disallowed */
186 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
187 MGMT_STATUS_REJECTED, /* Rejected Security */
188 MGMT_STATUS_REJECTED, /* Rejected Personal */
189 MGMT_STATUS_TIMEOUT, /* Host Timeout */
190 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
191 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
192 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
193 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
194 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
195 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
196 MGMT_STATUS_BUSY, /* Repeated Attempts */
197 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
198 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
199 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
200 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
201 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
202 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
203 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
204 MGMT_STATUS_FAILED, /* Unspecified Error */
205 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
206 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
207 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
208 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
209 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
210 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
211 MGMT_STATUS_FAILED, /* Unit Link Key Used */
212 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
213 MGMT_STATUS_TIMEOUT, /* Instant Passed */
214 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
215 MGMT_STATUS_FAILED, /* Transaction Collision */
216 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
217 MGMT_STATUS_REJECTED, /* QoS Rejected */
218 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
219 MGMT_STATUS_REJECTED, /* Insufficient Security */
220 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
221 MGMT_STATUS_BUSY, /* Role Switch Pending */
222 MGMT_STATUS_FAILED, /* Slot Violation */
223 MGMT_STATUS_FAILED, /* Role Switch Failed */
224 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
225 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
226 MGMT_STATUS_BUSY, /* Host Busy Pairing */
227 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
228 MGMT_STATUS_BUSY, /* Controller Busy */
229 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
230 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
231 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
232 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
233 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
234};
235
236static u8 mgmt_status(u8 hci_status)
237{
238 if (hci_status < ARRAY_SIZE(mgmt_status_table))
239 return mgmt_status_table[hci_status];
240
241 return MGMT_STATUS_FAILED;
242}
243
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700244static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
245 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700246{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700247 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
248 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700249}
250
Marcel Holtmann72000df2015-03-16 16:11:21 -0700251static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
252 u16 len, int flag, struct sock *skip_sk)
253{
254 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
255 flag, skip_sk);
256}
257
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700258static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
259 u16 len, struct sock *skip_sk)
260{
261 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
262 HCI_MGMT_GENERIC_EVENTS, skip_sk);
263}
264
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200265static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
266 struct sock *skip_sk)
267{
268 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700269 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200270}
271
Johan Hedberg85813a72015-10-21 18:02:59 +0300272static u8 le_addr_type(u8 mgmt_addr_type)
273{
274 if (mgmt_addr_type == BDADDR_LE_PUBLIC)
275 return ADDR_LE_DEV_PUBLIC;
276 else
277 return ADDR_LE_DEV_RANDOM;
278}
279
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300280static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
281 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200282{
283 struct mgmt_rp_read_version rp;
284
285 BT_DBG("sock %p", sk);
286
287 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700288 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200289
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200290 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
291 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292}
293
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300294static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
295 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200296{
297 struct mgmt_rp_read_commands *rp;
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700298 u16 num_commands, num_events;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200299 size_t rp_size;
300 int i, err;
301
302 BT_DBG("sock %p", sk);
303
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700304 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
305 num_commands = ARRAY_SIZE(mgmt_commands);
306 num_events = ARRAY_SIZE(mgmt_events);
307 } else {
308 num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
309 num_events = ARRAY_SIZE(mgmt_untrusted_events);
310 }
311
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200312 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
313
314 rp = kmalloc(rp_size, GFP_KERNEL);
315 if (!rp)
316 return -ENOMEM;
317
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700318 rp->num_commands = cpu_to_le16(num_commands);
319 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200320
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700321 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
322 __le16 *opcode = rp->opcodes;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200323
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700324 for (i = 0; i < num_commands; i++, opcode++)
325 put_unaligned_le16(mgmt_commands[i], opcode);
326
327 for (i = 0; i < num_events; i++, opcode++)
328 put_unaligned_le16(mgmt_events[i], opcode);
329 } else {
330 __le16 *opcode = rp->opcodes;
331
332 for (i = 0; i < num_commands; i++, opcode++)
333 put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
334
335 for (i = 0; i < num_events; i++, opcode++)
336 put_unaligned_le16(mgmt_untrusted_events[i], opcode);
337 }
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200338
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200339 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
340 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200341 kfree(rp);
342
343 return err;
344}
345
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300346static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
347 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200348{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200349 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200350 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200351 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200352 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300353 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200354
355 BT_DBG("sock %p", sk);
356
357 read_lock(&hci_dev_list_lock);
358
359 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300360 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200361 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700362 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700363 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200364 }
365
Johan Hedberga38528f2011-01-22 06:46:43 +0200366 rp_len = sizeof(*rp) + (2 * count);
367 rp = kmalloc(rp_len, GFP_ATOMIC);
368 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100369 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100371 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200372
Johan Hedberg476e44c2012-10-19 20:10:46 +0300373 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200374 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700375 if (hci_dev_test_flag(d, HCI_SETUP) ||
376 hci_dev_test_flag(d, HCI_CONFIG) ||
377 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200378 continue;
379
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200380 /* Devices marked as raw-only are neither configured
381 * nor unconfigured controllers.
382 */
383 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700384 continue;
385
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200386 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700387 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700388 rp->index[count++] = cpu_to_le16(d->id);
389 BT_DBG("Added hci%u", d->id);
390 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200391 }
392
Johan Hedberg476e44c2012-10-19 20:10:46 +0300393 rp->num_controllers = cpu_to_le16(count);
394 rp_len = sizeof(*rp) + (2 * count);
395
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200396 read_unlock(&hci_dev_list_lock);
397
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200398 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
399 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200400
Johan Hedberga38528f2011-01-22 06:46:43 +0200401 kfree(rp);
402
403 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404}
405
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200406static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
407 void *data, u16 data_len)
408{
409 struct mgmt_rp_read_unconf_index_list *rp;
410 struct hci_dev *d;
411 size_t rp_len;
412 u16 count;
413 int err;
414
415 BT_DBG("sock %p", sk);
416
417 read_lock(&hci_dev_list_lock);
418
419 count = 0;
420 list_for_each_entry(d, &hci_dev_list, list) {
421 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700422 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200423 count++;
424 }
425
426 rp_len = sizeof(*rp) + (2 * count);
427 rp = kmalloc(rp_len, GFP_ATOMIC);
428 if (!rp) {
429 read_unlock(&hci_dev_list_lock);
430 return -ENOMEM;
431 }
432
433 count = 0;
434 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700435 if (hci_dev_test_flag(d, HCI_SETUP) ||
436 hci_dev_test_flag(d, HCI_CONFIG) ||
437 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200438 continue;
439
440 /* Devices marked as raw-only are neither configured
441 * nor unconfigured controllers.
442 */
443 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
444 continue;
445
446 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700447 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200448 rp->index[count++] = cpu_to_le16(d->id);
449 BT_DBG("Added hci%u", d->id);
450 }
451 }
452
453 rp->num_controllers = cpu_to_le16(count);
454 rp_len = sizeof(*rp) + (2 * count);
455
456 read_unlock(&hci_dev_list_lock);
457
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200458 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
459 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200460
461 kfree(rp);
462
463 return err;
464}
465
Marcel Holtmann96f14742015-03-14 19:27:57 -0700466static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
467 void *data, u16 data_len)
468{
469 struct mgmt_rp_read_ext_index_list *rp;
470 struct hci_dev *d;
471 size_t rp_len;
472 u16 count;
473 int err;
474
475 BT_DBG("sock %p", sk);
476
477 read_lock(&hci_dev_list_lock);
478
479 count = 0;
480 list_for_each_entry(d, &hci_dev_list, list) {
481 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
482 count++;
483 }
484
485 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
486 rp = kmalloc(rp_len, GFP_ATOMIC);
487 if (!rp) {
488 read_unlock(&hci_dev_list_lock);
489 return -ENOMEM;
490 }
491
492 count = 0;
493 list_for_each_entry(d, &hci_dev_list, list) {
494 if (hci_dev_test_flag(d, HCI_SETUP) ||
495 hci_dev_test_flag(d, HCI_CONFIG) ||
496 hci_dev_test_flag(d, HCI_USER_CHANNEL))
497 continue;
498
499 /* Devices marked as raw-only are neither configured
500 * nor unconfigured controllers.
501 */
502 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
503 continue;
504
505 if (d->dev_type == HCI_BREDR) {
506 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
507 rp->entry[count].type = 0x01;
508 else
509 rp->entry[count].type = 0x00;
510 } else if (d->dev_type == HCI_AMP) {
511 rp->entry[count].type = 0x02;
512 } else {
513 continue;
514 }
515
516 rp->entry[count].bus = d->bus;
517 rp->entry[count++].index = cpu_to_le16(d->id);
518 BT_DBG("Added hci%u", d->id);
519 }
520
521 rp->num_controllers = cpu_to_le16(count);
522 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
523
524 read_unlock(&hci_dev_list_lock);
525
526 /* If this command is called at least once, then all the
527 * default index and unconfigured index events are disabled
528 * and from now on only extended index events are used.
529 */
530 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
531 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
532 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
533
534 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
535 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
536
537 kfree(rp);
538
539 return err;
540}
541
Marcel Holtmanndbece372014-07-04 18:11:55 +0200542static bool is_configured(struct hci_dev *hdev)
543{
544 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700545 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200546 return false;
547
548 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
549 !bacmp(&hdev->public_addr, BDADDR_ANY))
550 return false;
551
552 return true;
553}
554
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200555static __le32 get_missing_options(struct hci_dev *hdev)
556{
557 u32 options = 0;
558
Marcel Holtmanndbece372014-07-04 18:11:55 +0200559 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700560 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200561 options |= MGMT_OPTION_EXTERNAL_CONFIG;
562
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200563 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
564 !bacmp(&hdev->public_addr, BDADDR_ANY))
565 options |= MGMT_OPTION_PUBLIC_ADDRESS;
566
567 return cpu_to_le32(options);
568}
569
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200570static int new_options(struct hci_dev *hdev, struct sock *skip)
571{
572 __le32 options = get_missing_options(hdev);
573
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700574 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
575 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200576}
577
Marcel Holtmanndbece372014-07-04 18:11:55 +0200578static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
579{
580 __le32 options = get_missing_options(hdev);
581
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200582 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
583 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200584}
585
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200586static int read_config_info(struct sock *sk, struct hci_dev *hdev,
587 void *data, u16 data_len)
588{
589 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200590 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200591
592 BT_DBG("sock %p %s", sk, hdev->name);
593
594 hci_dev_lock(hdev);
595
596 memset(&rp, 0, sizeof(rp));
597 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200598
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200599 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
600 options |= MGMT_OPTION_EXTERNAL_CONFIG;
601
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200602 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200603 options |= MGMT_OPTION_PUBLIC_ADDRESS;
604
605 rp.supported_options = cpu_to_le32(options);
606 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200607
608 hci_dev_unlock(hdev);
609
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200610 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
611 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200612}
613
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200615{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200617
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300619 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800620 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300621 settings |= MGMT_SETTING_CONNECTABLE;
622 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200623
Andre Guedesed3fa312012-07-24 15:03:46 -0300624 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500625 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
626 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200627 settings |= MGMT_SETTING_BREDR;
628 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700629
630 if (lmp_ssp_capable(hdev)) {
631 settings |= MGMT_SETTING_SSP;
632 settings |= MGMT_SETTING_HS;
633 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800634
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800635 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800636 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700637 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100638
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300639 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200640 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300641 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300642 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200643 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800644 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300645 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200646
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200647 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
648 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200649 settings |= MGMT_SETTING_CONFIGURATION;
650
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200651 return settings;
652}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200653
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200654static u32 get_current_settings(struct hci_dev *hdev)
655{
656 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200657
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200658 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100659 settings |= MGMT_SETTING_POWERED;
660
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700661 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200662 settings |= MGMT_SETTING_CONNECTABLE;
663
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700664 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500665 settings |= MGMT_SETTING_FAST_CONNECTABLE;
666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700667 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200668 settings |= MGMT_SETTING_DISCOVERABLE;
669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700670 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300671 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200672
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700673 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200674 settings |= MGMT_SETTING_BREDR;
675
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700676 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200677 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200678
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700679 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200680 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200681
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700682 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200683 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200684
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700685 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200686 settings |= MGMT_SETTING_HS;
687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700688 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300689 settings |= MGMT_SETTING_ADVERTISING;
690
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700691 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800692 settings |= MGMT_SETTING_SECURE_CONN;
693
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700694 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800695 settings |= MGMT_SETTING_DEBUG_KEYS;
696
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700697 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200698 settings |= MGMT_SETTING_PRIVACY;
699
Marcel Holtmann93690c22015-03-06 10:11:21 -0800700 /* The current setting for static address has two purposes. The
701 * first is to indicate if the static address will be used and
702 * the second is to indicate if it is actually set.
703 *
704 * This means if the static address is not configured, this flag
Marcel Holtmann08dc0e92015-03-25 18:32:13 -0700705 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800706 * address is actually used decides if the flag is set or not.
707 *
708 * For single mode LE only controllers and dual-mode controllers
709 * with BR/EDR disabled, the existence of the static address will
710 * be evaluated.
711 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700712 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700713 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800714 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
715 if (bacmp(&hdev->static_addr, BDADDR_ANY))
716 settings |= MGMT_SETTING_STATIC_ADDRESS;
717 }
718
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200719 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200720}
721
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300722#define PNP_INFO_SVCLASS_ID 0x1200
723
Johan Hedberg213202e2013-01-27 00:31:33 +0200724static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
725{
726 u8 *ptr = data, *uuids_start = NULL;
727 struct bt_uuid *uuid;
728
729 if (len < 4)
730 return ptr;
731
732 list_for_each_entry(uuid, &hdev->uuids, list) {
733 u16 uuid16;
734
735 if (uuid->size != 16)
736 continue;
737
738 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
739 if (uuid16 < 0x1100)
740 continue;
741
742 if (uuid16 == PNP_INFO_SVCLASS_ID)
743 continue;
744
745 if (!uuids_start) {
746 uuids_start = ptr;
747 uuids_start[0] = 1;
748 uuids_start[1] = EIR_UUID16_ALL;
749 ptr += 2;
750 }
751
752 /* Stop if not enough space to put next UUID */
753 if ((ptr - data) + sizeof(u16) > len) {
754 uuids_start[1] = EIR_UUID16_SOME;
755 break;
756 }
757
758 *ptr++ = (uuid16 & 0x00ff);
759 *ptr++ = (uuid16 & 0xff00) >> 8;
760 uuids_start[0] += sizeof(uuid16);
761 }
762
763 return ptr;
764}
765
Johan Hedbergcdf19632013-01-27 00:31:34 +0200766static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
767{
768 u8 *ptr = data, *uuids_start = NULL;
769 struct bt_uuid *uuid;
770
771 if (len < 6)
772 return ptr;
773
774 list_for_each_entry(uuid, &hdev->uuids, list) {
775 if (uuid->size != 32)
776 continue;
777
778 if (!uuids_start) {
779 uuids_start = ptr;
780 uuids_start[0] = 1;
781 uuids_start[1] = EIR_UUID32_ALL;
782 ptr += 2;
783 }
784
785 /* Stop if not enough space to put next UUID */
786 if ((ptr - data) + sizeof(u32) > len) {
787 uuids_start[1] = EIR_UUID32_SOME;
788 break;
789 }
790
791 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
792 ptr += sizeof(u32);
793 uuids_start[0] += sizeof(u32);
794 }
795
796 return ptr;
797}
798
Johan Hedbergc00d5752013-01-27 00:31:35 +0200799static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
800{
801 u8 *ptr = data, *uuids_start = NULL;
802 struct bt_uuid *uuid;
803
804 if (len < 18)
805 return ptr;
806
807 list_for_each_entry(uuid, &hdev->uuids, list) {
808 if (uuid->size != 128)
809 continue;
810
811 if (!uuids_start) {
812 uuids_start = ptr;
813 uuids_start[0] = 1;
814 uuids_start[1] = EIR_UUID128_ALL;
815 ptr += 2;
816 }
817
818 /* Stop if not enough space to put next UUID */
819 if ((ptr - data) + 16 > len) {
820 uuids_start[1] = EIR_UUID128_SOME;
821 break;
822 }
823
824 memcpy(ptr, uuid->uuid, 16);
825 ptr += 16;
826 uuids_start[0] += 16;
827 }
828
829 return ptr;
830}
831
Johan Hedberg333ae952015-03-17 13:48:47 +0200832static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
833{
834 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
835}
836
Johan Hedberg333ae952015-03-17 13:48:47 +0200837static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
838 struct hci_dev *hdev,
839 const void *data)
840{
841 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
842}
843
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200844static u8 get_current_adv_instance(struct hci_dev *hdev)
845{
846 /* The "Set Advertising" setting supersedes the "Add Advertising"
847 * setting. Here we set the advertising data based on which
848 * setting was set. When neither apply, default to the global settings,
849 * represented by instance "0".
850 */
851 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
852 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Florian Grandel3ff37e62015-06-18 03:16:39 +0200853 return hdev->cur_adv_instance;
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200854
855 return 0x00;
856}
857
Arman Uguray4117ed72015-03-23 15:57:14 -0700858static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700859{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700860 u8 ad_len = 0;
861 size_t name_len;
862
863 name_len = strlen(hdev->dev_name);
864 if (name_len > 0) {
865 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
866
867 if (name_len > max_len) {
868 name_len = max_len;
869 ptr[1] = EIR_NAME_SHORT;
870 } else
871 ptr[1] = EIR_NAME_COMPLETE;
872
873 ptr[0] = name_len + 1;
874
875 memcpy(ptr + 2, hdev->dev_name, name_len);
876
877 ad_len += (name_len + 2);
878 ptr += (name_len + 2);
879 }
880
881 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700882}
883
Florian Grandelca21fbe2015-06-18 03:16:43 +0200884static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
885 u8 *ptr)
Arman Uguray4117ed72015-03-23 15:57:14 -0700886{
Florian Grandelca21fbe2015-06-18 03:16:43 +0200887 struct adv_info *adv_instance;
888
889 adv_instance = hci_find_adv_instance(hdev, instance);
890 if (!adv_instance)
891 return 0;
892
Arman Uguray4117ed72015-03-23 15:57:14 -0700893 /* TODO: Set the appropriate entries based on advertising instance flags
894 * here once flags other than 0 are supported.
895 */
Florian Grandelca21fbe2015-06-18 03:16:43 +0200896 memcpy(ptr, adv_instance->scan_rsp_data,
897 adv_instance->scan_rsp_len);
Arman Uguray4117ed72015-03-23 15:57:14 -0700898
Florian Grandelca21fbe2015-06-18 03:16:43 +0200899 return adv_instance->scan_rsp_len;
Arman Uguray4117ed72015-03-23 15:57:14 -0700900}
901
Florian Grandelefae0022015-06-18 03:16:37 +0200902static void update_inst_scan_rsp_data(struct hci_request *req, u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700903{
904 struct hci_dev *hdev = req->hdev;
905 struct hci_cp_le_set_scan_rsp_data cp;
906 u8 len;
907
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700908 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700909 return;
910
911 memset(&cp, 0, sizeof(cp));
912
Arman Uguray4117ed72015-03-23 15:57:14 -0700913 if (instance)
Florian Grandelca21fbe2015-06-18 03:16:43 +0200914 len = create_instance_scan_rsp_data(hdev, instance, cp.data);
Arman Uguray4117ed72015-03-23 15:57:14 -0700915 else
916 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700917
Johan Hedbergeb438b52013-10-16 15:31:07 +0300918 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700919 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700920 return;
921
Johan Hedbergeb438b52013-10-16 15:31:07 +0300922 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
923 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700924
925 cp.length = len;
926
927 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
928}
929
Arman Uguray4117ed72015-03-23 15:57:14 -0700930static void update_scan_rsp_data(struct hci_request *req)
931{
Florian Grandelefae0022015-06-18 03:16:37 +0200932 update_inst_scan_rsp_data(req, get_current_adv_instance(req->hdev));
Arman Uguray4117ed72015-03-23 15:57:14 -0700933}
934
Johan Hedberg9a43e252013-10-20 19:00:07 +0300935static u8 get_adv_discov_flags(struct hci_dev *hdev)
936{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200937 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300938
939 /* If there's a pending mgmt command the flags will not yet have
940 * their final values, so check for this first.
941 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200942 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300943 if (cmd) {
944 struct mgmt_mode *cp = cmd->param;
945 if (cp->val == 0x01)
946 return LE_AD_GENERAL;
947 else if (cp->val == 0x02)
948 return LE_AD_LIMITED;
949 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700950 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300951 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700952 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300953 return LE_AD_GENERAL;
954 }
955
956 return 0;
957}
958
Arman Uguraye7a685d2015-03-25 18:53:40 -0700959static bool get_connectable(struct hci_dev *hdev)
960{
961 struct mgmt_pending_cmd *cmd;
962
963 /* If there's a pending mgmt command the flag will not yet have
964 * it's final value, so check for this first.
965 */
966 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
967 if (cmd) {
968 struct mgmt_mode *cp = cmd->param;
969
970 return cp->val;
971 }
972
973 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
974}
975
976static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
977{
978 u32 flags;
Florian Grandel411b4122015-06-18 03:16:40 +0200979 struct adv_info *adv_instance;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700980
Florian Grandelbea28e62015-06-18 03:16:41 +0200981 if (instance == 0x00) {
982 /* Instance 0 always manages the "Tx Power" and "Flags"
983 * fields
984 */
985 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700986
Florian Grandelbea28e62015-06-18 03:16:41 +0200987 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting
988 * corresponds to the "connectable" instance flag.
989 */
990 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
991 flags |= MGMT_ADV_FLAG_CONNECTABLE;
Florian Grandel411b4122015-06-18 03:16:40 +0200992
Florian Grandelbea28e62015-06-18 03:16:41 +0200993 return flags;
Florian Grandel411b4122015-06-18 03:16:40 +0200994 }
Arman Uguraye7a685d2015-03-25 18:53:40 -0700995
Florian Grandelbea28e62015-06-18 03:16:41 +0200996 adv_instance = hci_find_adv_instance(hdev, instance);
Arman Uguraye7a685d2015-03-25 18:53:40 -0700997
Florian Grandelbea28e62015-06-18 03:16:41 +0200998 /* Return 0 when we got an invalid instance identifier. */
999 if (!adv_instance)
1000 return 0;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001001
Florian Grandelbea28e62015-06-18 03:16:41 +02001002 return adv_instance->flags;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001003}
1004
Florian Grandel7b683b72015-06-18 03:16:42 +02001005static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
Arman Ugurayc7d48832015-03-28 12:38:59 -07001006{
Florian Grandel7b683b72015-06-18 03:16:42 +02001007 u8 instance = get_current_adv_instance(hdev);
1008 struct adv_info *adv_instance;
1009
1010 /* Ignore instance 0 */
1011 if (instance == 0x00)
1012 return 0;
1013
1014 adv_instance = hci_find_adv_instance(hdev, instance);
1015 if (!adv_instance)
Arman Ugurayc7d48832015-03-28 12:38:59 -07001016 return 0;
1017
1018 /* TODO: Take into account the "appearance" and "local-name" flags here.
1019 * These are currently being ignored as they are not supported.
1020 */
Florian Grandel7b683b72015-06-18 03:16:42 +02001021 return adv_instance->scan_rsp_len;
Arman Ugurayc7d48832015-03-28 12:38:59 -07001022}
1023
Arman Ugurayfdf51782015-03-25 18:53:46 -07001024static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1025{
Florian Grandelf63ba242015-06-18 03:16:44 +02001026 struct adv_info *adv_instance = NULL;
Arman Ugurayfdf51782015-03-25 18:53:46 -07001027 u8 ad_len = 0, flags = 0;
Florian Grandelf63ba242015-06-18 03:16:44 +02001028 u32 instance_flags;
1029
1030 /* Return 0 when the current instance identifier is invalid. */
1031 if (instance) {
1032 adv_instance = hci_find_adv_instance(hdev, instance);
1033 if (!adv_instance)
1034 return 0;
1035 }
1036
1037 instance_flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfdf51782015-03-25 18:53:46 -07001038
1039 /* The Add Advertising command allows userspace to set both the general
1040 * and limited discoverable flags.
1041 */
1042 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1043 flags |= LE_AD_GENERAL;
1044
1045 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1046 flags |= LE_AD_LIMITED;
1047
1048 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1049 /* If a discovery flag wasn't provided, simply use the global
1050 * settings.
1051 */
1052 if (!flags)
1053 flags |= get_adv_discov_flags(hdev);
1054
1055 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1056 flags |= LE_AD_NO_BREDR;
1057
1058 /* If flags would still be empty, then there is no need to
1059 * include the "Flags" AD field".
1060 */
1061 if (flags) {
1062 ptr[0] = 0x02;
1063 ptr[1] = EIR_FLAGS;
1064 ptr[2] = flags;
1065
1066 ad_len += 3;
1067 ptr += 3;
1068 }
1069 }
1070
Florian Grandelf63ba242015-06-18 03:16:44 +02001071 if (adv_instance) {
1072 memcpy(ptr, adv_instance->adv_data,
1073 adv_instance->adv_data_len);
1074 ad_len += adv_instance->adv_data_len;
1075 ptr += adv_instance->adv_data_len;
Marcel Holtmann38c8af62015-04-03 13:23:12 -07001076 }
1077
Arman Ugurayfdf51782015-03-25 18:53:46 -07001078 /* Provide Tx Power only if we can provide a valid value for it */
1079 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1080 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1081 ptr[0] = 0x02;
1082 ptr[1] = EIR_TX_POWER;
1083 ptr[2] = (u8)hdev->adv_tx_power;
1084
1085 ad_len += 3;
1086 ptr += 3;
1087 }
1088
Arman Ugurayfdf51782015-03-25 18:53:46 -07001089 return ad_len;
1090}
1091
Florian Grandelefae0022015-06-18 03:16:37 +02001092static void update_inst_adv_data(struct hci_request *req, u8 instance)
Arman Ugurayfdf51782015-03-25 18:53:46 -07001093{
1094 struct hci_dev *hdev = req->hdev;
1095 struct hci_cp_le_set_adv_data cp;
1096 u8 len;
1097
1098 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1099 return;
1100
1101 memset(&cp, 0, sizeof(cp));
1102
1103 len = create_instance_adv_data(hdev, instance, cp.data);
1104
1105 /* There's nothing to do if the data hasn't changed */
1106 if (hdev->adv_data_len == len &&
1107 memcmp(cp.data, hdev->adv_data, len) == 0)
1108 return;
1109
1110 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1111 hdev->adv_data_len = len;
1112
1113 cp.length = len;
1114
1115 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1116}
1117
Arman Uguraye7a685d2015-03-25 18:53:40 -07001118static void update_adv_data(struct hci_request *req)
1119{
Florian Grandelefae0022015-06-18 03:16:37 +02001120 update_inst_adv_data(req, get_current_adv_instance(req->hdev));
Arman Uguray24b4f382015-03-23 15:57:12 -07001121}
1122
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001123int mgmt_update_adv_data(struct hci_dev *hdev)
1124{
1125 struct hci_request req;
1126
1127 hci_req_init(&req, hdev);
1128 update_adv_data(&req);
1129
1130 return hci_req_run(&req, NULL);
1131}
1132
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001133static void create_eir(struct hci_dev *hdev, u8 *data)
1134{
1135 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001136 size_t name_len;
1137
1138 name_len = strlen(hdev->dev_name);
1139
1140 if (name_len > 0) {
1141 /* EIR Data type */
1142 if (name_len > 48) {
1143 name_len = 48;
1144 ptr[1] = EIR_NAME_SHORT;
1145 } else
1146 ptr[1] = EIR_NAME_COMPLETE;
1147
1148 /* EIR Data length */
1149 ptr[0] = name_len + 1;
1150
1151 memcpy(ptr + 2, hdev->dev_name, name_len);
1152
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001153 ptr += (name_len + 2);
1154 }
1155
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001156 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001157 ptr[0] = 2;
1158 ptr[1] = EIR_TX_POWER;
1159 ptr[2] = (u8) hdev->inq_tx_power;
1160
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001161 ptr += 3;
1162 }
1163
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001164 if (hdev->devid_source > 0) {
1165 ptr[0] = 9;
1166 ptr[1] = EIR_DEVICE_ID;
1167
1168 put_unaligned_le16(hdev->devid_source, ptr + 2);
1169 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1170 put_unaligned_le16(hdev->devid_product, ptr + 6);
1171 put_unaligned_le16(hdev->devid_version, ptr + 8);
1172
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001173 ptr += 10;
1174 }
1175
Johan Hedberg213202e2013-01-27 00:31:33 +02001176 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001177 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001178 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001179}
1180
Johan Hedberg890ea892013-03-15 17:06:52 -05001181static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001182{
Johan Hedberg890ea892013-03-15 17:06:52 -05001183 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001184 struct hci_cp_write_eir cp;
1185
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001186 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001187 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001188
Johan Hedberg976eb202012-10-24 21:12:01 +03001189 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001190 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001191
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001192 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001193 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001194
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001195 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001196 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001197
1198 memset(&cp, 0, sizeof(cp));
1199
1200 create_eir(hdev, cp.data);
1201
1202 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001203 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001204
1205 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1206
Johan Hedberg890ea892013-03-15 17:06:52 -05001207 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001208}
1209
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001210static u8 get_service_classes(struct hci_dev *hdev)
1211{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001212 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001213 u8 val = 0;
1214
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001215 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001216 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001217
1218 return val;
1219}
1220
Johan Hedberg890ea892013-03-15 17:06:52 -05001221static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001222{
Johan Hedberg890ea892013-03-15 17:06:52 -05001223 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001224 u8 cod[3];
1225
1226 BT_DBG("%s", hdev->name);
1227
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001228 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001229 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001230
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001231 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001232 return;
1233
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001234 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001235 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001236
1237 cod[0] = hdev->minor_class;
1238 cod[1] = hdev->major_class;
1239 cod[2] = get_service_classes(hdev);
1240
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001241 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001242 cod[1] |= 0x20;
1243
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001244 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001245 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001246
Johan Hedberg890ea892013-03-15 17:06:52 -05001247 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001248}
1249
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001250static void disable_advertising(struct hci_request *req)
1251{
1252 u8 enable = 0x00;
1253
1254 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1255}
1256
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001257static void enable_advertising(struct hci_request *req)
1258{
1259 struct hci_dev *hdev = req->hdev;
1260 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001261 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001262 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001263 u8 instance;
1264 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001265
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001266 if (hci_conn_num(hdev, LE_LINK) > 0)
1267 return;
1268
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001269 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001270 disable_advertising(req);
1271
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001272 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001273 * hci_update_random_address knows that it's safe to go ahead
1274 * and write a new random address. The flag will be set back on
1275 * as soon as the SET_ADV_ENABLE HCI command completes.
1276 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001277 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001278
Arman Uguraye7a685d2015-03-25 18:53:40 -07001279 instance = get_current_adv_instance(hdev);
1280 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001281
1282 /* If the "connectable" instance flag was not set, then choose between
1283 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1284 */
1285 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1286 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001287
Johan Hedberga4858cb2014-02-25 19:56:31 +02001288 /* Set require_privacy to true only when non-connectable
1289 * advertising is used. In that case it is fine to use a
1290 * non-resolvable private address.
1291 */
1292 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001293 return;
1294
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001295 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001296 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1297 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001298
1299 if (connectable)
1300 cp.type = LE_ADV_IND;
Florian Grandel7b683b72015-06-18 03:16:42 +02001301 else if (get_cur_adv_instance_scan_rsp_len(hdev))
Arman Ugurayc7d48832015-03-28 12:38:59 -07001302 cp.type = LE_ADV_SCAN_IND;
1303 else
1304 cp.type = LE_ADV_NONCONN_IND;
1305
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001306 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001307 cp.channel_map = hdev->le_adv_channel_map;
1308
1309 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1310
1311 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1312}
1313
Johan Hedberg7d785252011-12-15 00:47:39 +02001314static void service_cache_off(struct work_struct *work)
1315{
1316 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001317 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001318 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001319
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001320 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001321 return;
1322
Johan Hedberg890ea892013-03-15 17:06:52 -05001323 hci_req_init(&req, hdev);
1324
Johan Hedberg7d785252011-12-15 00:47:39 +02001325 hci_dev_lock(hdev);
1326
Johan Hedberg890ea892013-03-15 17:06:52 -05001327 update_eir(&req);
1328 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001329
1330 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001331
1332 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001333}
1334
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001335static void rpa_expired(struct work_struct *work)
1336{
1337 struct hci_dev *hdev = container_of(work, struct hci_dev,
1338 rpa_expired.work);
1339 struct hci_request req;
1340
1341 BT_DBG("");
1342
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001343 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001344
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001345 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001346 return;
1347
1348 /* The generation of a new RPA and programming it into the
1349 * controller happens in the enable_advertising() function.
1350 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001351 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001352 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001353 hci_req_run(&req, NULL);
1354}
1355
Johan Hedberg6a919082012-02-28 06:17:26 +02001356static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001357{
Marcel Holtmann238be782015-03-13 02:11:06 -07001358 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001359 return;
1360
Johan Hedberg4f87da82012-03-02 19:55:56 +02001361 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001362 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001363
Johan Hedberg4f87da82012-03-02 19:55:56 +02001364 /* Non-mgmt controlled devices get this bit set
1365 * implicitly so that pairing works for them, however
1366 * for mgmt we require user-space to explicitly enable
1367 * it
1368 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001369 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001370}
1371
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001372static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001373 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001374{
1375 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001376
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001377 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001378
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001379 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001380
Johan Hedberg03811012010-12-08 00:21:06 +02001381 memset(&rp, 0, sizeof(rp));
1382
Johan Hedberg03811012010-12-08 00:21:06 +02001383 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001384
1385 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001386 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001387
1388 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1389 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1390
1391 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001392
1393 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001394 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001395
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001396 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001397
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001398 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1399 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001400}
1401
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001402static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001403{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001404 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001405
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001406 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1407 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001408}
1409
Marcel Holtmann1904a852015-01-11 13:50:44 -08001410static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001411{
1412 BT_DBG("%s status 0x%02x", hdev->name, status);
1413
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (hci_conn_count(hdev) == 0) {
1415 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001416 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001417 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418}
1419
Arman Uguray912098a2015-03-23 15:57:15 -07001420static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1421 u8 instance)
1422{
1423 struct mgmt_ev_advertising_added ev;
1424
1425 ev.instance = instance;
1426
1427 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1428}
1429
1430static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1431 u8 instance)
1432{
1433 struct mgmt_ev_advertising_removed ev;
1434
1435 ev.instance = instance;
1436
1437 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1438}
1439
Florian Grandel7816b822015-06-18 03:16:45 +02001440static int schedule_adv_instance(struct hci_request *req, u8 instance,
1441 bool force) {
1442 struct hci_dev *hdev = req->hdev;
1443 struct adv_info *adv_instance = NULL;
1444 u16 timeout;
1445
1446 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
1447 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1448 return -EPERM;
1449
1450 if (hdev->adv_instance_timeout)
1451 return -EBUSY;
1452
1453 adv_instance = hci_find_adv_instance(hdev, instance);
1454 if (!adv_instance)
1455 return -ENOENT;
1456
1457 /* A zero timeout means unlimited advertising. As long as there is
1458 * only one instance, duration should be ignored. We still set a timeout
1459 * in case further instances are being added later on.
1460 *
1461 * If the remaining lifetime of the instance is more than the duration
1462 * then the timeout corresponds to the duration, otherwise it will be
1463 * reduced to the remaining instance lifetime.
1464 */
1465 if (adv_instance->timeout == 0 ||
1466 adv_instance->duration <= adv_instance->remaining_time)
1467 timeout = adv_instance->duration;
1468 else
1469 timeout = adv_instance->remaining_time;
1470
1471 /* The remaining time is being reduced unless the instance is being
1472 * advertised without time limit.
1473 */
1474 if (adv_instance->timeout)
1475 adv_instance->remaining_time =
1476 adv_instance->remaining_time - timeout;
1477
1478 hdev->adv_instance_timeout = timeout;
1479 queue_delayed_work(hdev->workqueue,
1480 &hdev->adv_instance_expire,
1481 msecs_to_jiffies(timeout * 1000));
1482
1483 /* If we're just re-scheduling the same instance again then do not
1484 * execute any HCI commands. This happens when a single instance is
1485 * being advertised.
1486 */
1487 if (!force && hdev->cur_adv_instance == instance &&
1488 hci_dev_test_flag(hdev, HCI_LE_ADV))
1489 return 0;
1490
1491 hdev->cur_adv_instance = instance;
1492 update_adv_data(req);
1493 update_scan_rsp_data(req);
1494 enable_advertising(req);
1495
1496 return 0;
1497}
1498
1499static void cancel_adv_timeout(struct hci_dev *hdev)
1500{
1501 if (hdev->adv_instance_timeout) {
1502 hdev->adv_instance_timeout = 0;
1503 cancel_delayed_work(&hdev->adv_instance_expire);
1504 }
1505}
1506
Florian Grandel847818d2015-06-18 03:16:46 +02001507/* For a single instance:
1508 * - force == true: The instance will be removed even when its remaining
1509 * lifetime is not zero.
1510 * - force == false: the instance will be deactivated but kept stored unless
1511 * the remaining lifetime is zero.
1512 *
1513 * For instance == 0x00:
1514 * - force == true: All instances will be removed regardless of their timeout
1515 * setting.
1516 * - force == false: Only instances that have a timeout will be removed.
1517 */
1518static void clear_adv_instance(struct hci_dev *hdev, struct hci_request *req,
1519 u8 instance, bool force)
Arman Uguray912098a2015-03-23 15:57:15 -07001520{
Florian Grandel847818d2015-06-18 03:16:46 +02001521 struct adv_info *adv_instance, *n, *next_instance = NULL;
1522 int err;
1523 u8 rem_inst;
Arman Uguray912098a2015-03-23 15:57:15 -07001524
Florian Grandel847818d2015-06-18 03:16:46 +02001525 /* Cancel any timeout concerning the removed instance(s). */
1526 if (!instance || hdev->cur_adv_instance == instance)
1527 cancel_adv_timeout(hdev);
Arman Uguray912098a2015-03-23 15:57:15 -07001528
Florian Grandel847818d2015-06-18 03:16:46 +02001529 /* Get the next instance to advertise BEFORE we remove
1530 * the current one. This can be the same instance again
1531 * if there is only one instance.
1532 */
1533 if (instance && hdev->cur_adv_instance == instance)
1534 next_instance = hci_get_next_instance(hdev, instance);
Arman Uguray912098a2015-03-23 15:57:15 -07001535
Florian Grandel847818d2015-06-18 03:16:46 +02001536 if (instance == 0x00) {
1537 list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances,
1538 list) {
1539 if (!(force || adv_instance->timeout))
1540 continue;
Arman Uguray912098a2015-03-23 15:57:15 -07001541
Florian Grandel847818d2015-06-18 03:16:46 +02001542 rem_inst = adv_instance->instance;
1543 err = hci_remove_adv_instance(hdev, rem_inst);
1544 if (!err)
1545 advertising_removed(NULL, hdev, rem_inst);
1546 }
1547 hdev->cur_adv_instance = 0x00;
1548 } else {
1549 adv_instance = hci_find_adv_instance(hdev, instance);
1550
1551 if (force || (adv_instance && adv_instance->timeout &&
1552 !adv_instance->remaining_time)) {
1553 /* Don't advertise a removed instance. */
1554 if (next_instance &&
1555 next_instance->instance == instance)
1556 next_instance = NULL;
1557
1558 err = hci_remove_adv_instance(hdev, instance);
1559 if (!err)
1560 advertising_removed(NULL, hdev, instance);
1561 }
1562 }
1563
1564 if (list_empty(&hdev->adv_instances)) {
1565 hdev->cur_adv_instance = 0x00;
1566 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1567 }
1568
1569 if (!req || !hdev_is_powered(hdev) ||
Arman Uguray912098a2015-03-23 15:57:15 -07001570 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1571 return;
1572
Florian Grandel847818d2015-06-18 03:16:46 +02001573 if (next_instance)
1574 schedule_adv_instance(req, next_instance->instance, false);
Arman Uguray912098a2015-03-23 15:57:15 -07001575}
1576
Johan Hedberg8b064a32014-02-24 14:52:22 +02001577static int clean_up_hci_state(struct hci_dev *hdev)
1578{
1579 struct hci_request req;
1580 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001581 bool discov_stopped;
1582 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001583
1584 hci_req_init(&req, hdev);
1585
1586 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1587 test_bit(HCI_PSCAN, &hdev->flags)) {
1588 u8 scan = 0x00;
1589 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1590 }
1591
Florian Grandel847818d2015-06-18 03:16:46 +02001592 clear_adv_instance(hdev, NULL, 0x00, false);
Arman Uguray912098a2015-03-23 15:57:15 -07001593
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001594 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001595 disable_advertising(&req);
1596
Johan Hedberg2154d3f2015-11-11 08:30:45 +02001597 discov_stopped = hci_req_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001598
1599 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
Johan Hedberg89e0ccc2015-10-22 10:49:38 +03001600 /* 0x15 == Terminated due to Power Off */
1601 __hci_abort_conn(&req, conn, 0x15);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001602 }
1603
Johan Hedberg23a48092014-07-08 16:05:06 +03001604 err = hci_req_run(&req, clean_up_hci_complete);
1605 if (!err && discov_stopped)
1606 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1607
1608 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001609}
1610
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001611static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001612 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001613{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001614 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001615 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001616 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001617
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001618 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001619
Johan Hedberga7e80f22013-01-09 16:05:19 +02001620 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001621 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1622 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001623
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001624 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001625
Johan Hedberg333ae952015-03-17 13:48:47 +02001626 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001627 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1628 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001629 goto failed;
1630 }
1631
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001632 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001633 cancel_delayed_work(&hdev->power_off);
1634
1635 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001636 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1637 data, len);
1638 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001639 goto failed;
1640 }
1641 }
1642
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001643 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001644 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001645 goto failed;
1646 }
1647
Johan Hedberg03811012010-12-08 00:21:06 +02001648 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1649 if (!cmd) {
1650 err = -ENOMEM;
1651 goto failed;
1652 }
1653
Johan Hedberg8b064a32014-02-24 14:52:22 +02001654 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001655 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001656 err = 0;
1657 } else {
1658 /* Disconnect connections, stop scans, etc */
1659 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001660 if (!err)
1661 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1662 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001663
Johan Hedberg8b064a32014-02-24 14:52:22 +02001664 /* ENODATA means there were no HCI commands queued */
1665 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001666 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001667 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1668 err = 0;
1669 }
1670 }
Johan Hedberg03811012010-12-08 00:21:06 +02001671
1672failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001673 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001674 return err;
1675}
1676
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001677static int new_settings(struct hci_dev *hdev, struct sock *skip)
1678{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001679 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001680
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001681 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1682 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001683}
1684
Johan Hedberg91a668b2014-07-09 13:28:26 +03001685int mgmt_new_settings(struct hci_dev *hdev)
1686{
1687 return new_settings(hdev, NULL);
1688}
1689
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001690struct cmd_lookup {
1691 struct sock *sk;
1692 struct hci_dev *hdev;
1693 u8 mgmt_status;
1694};
1695
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001696static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001697{
1698 struct cmd_lookup *match = data;
1699
1700 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1701
1702 list_del(&cmd->list);
1703
1704 if (match->sk == NULL) {
1705 match->sk = cmd->sk;
1706 sock_hold(match->sk);
1707 }
1708
1709 mgmt_pending_free(cmd);
1710}
1711
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001712static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001713{
1714 u8 *status = data;
1715
Johan Hedberga69e8372015-03-06 21:08:53 +02001716 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001717 mgmt_pending_remove(cmd);
1718}
1719
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001720static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001721{
1722 if (cmd->cmd_complete) {
1723 u8 *status = data;
1724
1725 cmd->cmd_complete(cmd, *status);
1726 mgmt_pending_remove(cmd);
1727
1728 return;
1729 }
1730
1731 cmd_status_rsp(cmd, data);
1732}
1733
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001734static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001735{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001736 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1737 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001738}
1739
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001740static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001741{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001742 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1743 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001744}
1745
Johan Hedberge6fe7982013-10-02 15:45:22 +03001746static u8 mgmt_bredr_support(struct hci_dev *hdev)
1747{
1748 if (!lmp_bredr_capable(hdev))
1749 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001750 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001751 return MGMT_STATUS_REJECTED;
1752 else
1753 return MGMT_STATUS_SUCCESS;
1754}
1755
1756static u8 mgmt_le_support(struct hci_dev *hdev)
1757{
1758 if (!lmp_le_capable(hdev))
1759 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001760 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001761 return MGMT_STATUS_REJECTED;
1762 else
1763 return MGMT_STATUS_SUCCESS;
1764}
1765
Marcel Holtmann1904a852015-01-11 13:50:44 -08001766static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1767 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001768{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001769 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001770 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001771 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001772 bool changed;
1773
1774 BT_DBG("status 0x%02x", status);
1775
1776 hci_dev_lock(hdev);
1777
Johan Hedberg333ae952015-03-17 13:48:47 +02001778 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001779 if (!cmd)
1780 goto unlock;
1781
1782 if (status) {
1783 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001784 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001785 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001786 goto remove_cmd;
1787 }
1788
1789 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001790 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001791 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001792
1793 if (hdev->discov_timeout > 0) {
1794 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1795 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1796 to);
1797 }
1798 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001799 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001800 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001801
1802 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1803
1804 if (changed)
1805 new_settings(hdev, cmd->sk);
1806
Marcel Holtmann970ba522013-10-15 06:33:57 -07001807 /* When the discoverable mode gets changed, make sure
1808 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001809 * bit correctly set. Also update page scan based on whitelist
1810 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001811 */
1812 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001813 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001814 update_class(&req);
1815 hci_req_run(&req, NULL);
1816
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001817remove_cmd:
1818 mgmt_pending_remove(cmd);
1819
1820unlock:
1821 hci_dev_unlock(hdev);
1822}
1823
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001824static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001825 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001826{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001827 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001828 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001829 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001830 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001831 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001832 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001833
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001834 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001835
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001836 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1837 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001838 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1839 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001840
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001841 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001842 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1843 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001844
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001845 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001846
1847 /* Disabling discoverable requires that no timeout is set,
1848 * and enabling limited discoverable requires a timeout.
1849 */
1850 if ((cp->val == 0x00 && timeout > 0) ||
1851 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001852 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1853 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001854
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001855 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001856
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001857 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001858 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1859 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001860 goto failed;
1861 }
1862
Johan Hedberg333ae952015-03-17 13:48:47 +02001863 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1864 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001865 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1866 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001867 goto failed;
1868 }
1869
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001870 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001871 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1872 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001873 goto failed;
1874 }
1875
1876 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001877 bool changed = false;
1878
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001879 /* Setting limited discoverable when powered off is
1880 * not a valid operation since it requires a timeout
1881 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1882 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001883 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001884 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001885 changed = true;
1886 }
1887
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001888 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001889 if (err < 0)
1890 goto failed;
1891
1892 if (changed)
1893 err = new_settings(hdev, sk);
1894
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001895 goto failed;
1896 }
1897
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001898 /* If the current mode is the same, then just update the timeout
1899 * value with the new value. And if only the timeout gets updated,
1900 * then no need for any HCI transactions.
1901 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001902 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1903 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1904 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001905 cancel_delayed_work(&hdev->discov_off);
1906 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001907
Marcel Holtmann36261542013-10-15 08:28:51 -07001908 if (cp->val && hdev->discov_timeout > 0) {
1909 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001910 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001911 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001912 }
1913
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001914 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001915 goto failed;
1916 }
1917
1918 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1919 if (!cmd) {
1920 err = -ENOMEM;
1921 goto failed;
1922 }
1923
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001924 /* Cancel any potential discoverable timeout that might be
1925 * still active and store new timeout value. The arming of
1926 * the timeout happens in the complete handler.
1927 */
1928 cancel_delayed_work(&hdev->discov_off);
1929 hdev->discov_timeout = timeout;
1930
Johan Hedbergb456f872013-10-19 23:38:22 +03001931 /* Limited discoverable mode */
1932 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001933 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001934 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001935 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001936
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001937 hci_req_init(&req, hdev);
1938
Johan Hedberg9a43e252013-10-20 19:00:07 +03001939 /* The procedure for LE-only controllers is much simpler - just
1940 * update the advertising data.
1941 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001942 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001943 goto update_ad;
1944
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001945 scan = SCAN_PAGE;
1946
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001947 if (cp->val) {
1948 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001949
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001950 if (cp->val == 0x02) {
1951 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001952 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001953 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1954 hci_cp.iac_lap[1] = 0x8b;
1955 hci_cp.iac_lap[2] = 0x9e;
1956 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1957 hci_cp.iac_lap[4] = 0x8b;
1958 hci_cp.iac_lap[5] = 0x9e;
1959 } else {
1960 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001961 hci_cp.num_iac = 1;
1962 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1963 hci_cp.iac_lap[1] = 0x8b;
1964 hci_cp.iac_lap[2] = 0x9e;
1965 }
1966
1967 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1968 (hci_cp.num_iac * 3) + 1, &hci_cp);
1969
1970 scan |= SCAN_INQUIRY;
1971 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001972 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001973 }
1974
1975 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001976
Johan Hedberg9a43e252013-10-20 19:00:07 +03001977update_ad:
1978 update_adv_data(&req);
1979
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001980 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001981 if (err < 0)
1982 mgmt_pending_remove(cmd);
1983
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001984failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001985 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001986 return err;
1987}
1988
Johan Hedberg406d7802013-03-15 17:07:09 -05001989static void write_fast_connectable(struct hci_request *req, bool enable)
1990{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001991 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001992 struct hci_cp_write_page_scan_activity acp;
1993 u8 type;
1994
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001995 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001996 return;
1997
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001998 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1999 return;
2000
Johan Hedberg406d7802013-03-15 17:07:09 -05002001 if (enable) {
2002 type = PAGE_SCAN_TYPE_INTERLACED;
2003
2004 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002005 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05002006 } else {
2007 type = PAGE_SCAN_TYPE_STANDARD; /* default */
2008
2009 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002010 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05002011 }
2012
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002013 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05002014
Johan Hedbergbd98b992013-03-15 17:07:13 -05002015 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
2016 __cpu_to_le16(hdev->page_scan_window) != acp.window)
2017 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
2018 sizeof(acp), &acp);
2019
2020 if (hdev->page_scan_type != type)
2021 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05002022}
2023
Marcel Holtmann1904a852015-01-11 13:50:44 -08002024static void set_connectable_complete(struct hci_dev *hdev, u8 status,
2025 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05002026{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002027 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002028 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002029 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002030
2031 BT_DBG("status 0x%02x", status);
2032
2033 hci_dev_lock(hdev);
2034
Johan Hedberg333ae952015-03-17 13:48:47 +02002035 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05002036 if (!cmd)
2037 goto unlock;
2038
Johan Hedberg37438c12013-10-14 16:20:05 +03002039 if (status) {
2040 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02002041 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03002042 goto remove_cmd;
2043 }
2044
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002045 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002046 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002047 conn_changed = !hci_dev_test_and_set_flag(hdev,
2048 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002049 discov_changed = false;
2050 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002051 conn_changed = hci_dev_test_and_clear_flag(hdev,
2052 HCI_CONNECTABLE);
2053 discov_changed = hci_dev_test_and_clear_flag(hdev,
2054 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002055 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002056
Johan Hedberg2b76f452013-03-15 17:07:04 -05002057 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
2058
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002059 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002060 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002061 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002062 if (discov_changed)
2063 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03002064 hci_update_background_scan(hdev);
2065 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002066
Johan Hedberg37438c12013-10-14 16:20:05 +03002067remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002068 mgmt_pending_remove(cmd);
2069
2070unlock:
2071 hci_dev_unlock(hdev);
2072}
2073
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002074static int set_connectable_update_settings(struct hci_dev *hdev,
2075 struct sock *sk, u8 val)
2076{
2077 bool changed = false;
2078 int err;
2079
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002080 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002081 changed = true;
2082
2083 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002084 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002085 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002086 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2087 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002088 }
2089
2090 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2091 if (err < 0)
2092 return err;
2093
Johan Hedberg562064e2014-07-08 16:35:34 +03002094 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002095 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002096 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002097 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002098 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002099
2100 return 0;
2101}
2102
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002103static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002104 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002105{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002106 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002107 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002108 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002109 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002110 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002111
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002112 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002113
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002114 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2115 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002116 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2117 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002118
Johan Hedberga7e80f22013-01-09 16:05:19 +02002119 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002120 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2121 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002122
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002123 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002124
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002125 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002126 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002127 goto failed;
2128 }
2129
Johan Hedberg333ae952015-03-17 13:48:47 +02002130 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2131 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002132 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2133 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002134 goto failed;
2135 }
2136
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002137 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2138 if (!cmd) {
2139 err = -ENOMEM;
2140 goto failed;
2141 }
2142
Johan Hedberg2b76f452013-03-15 17:07:04 -05002143 hci_req_init(&req, hdev);
2144
Johan Hedberg9a43e252013-10-20 19:00:07 +03002145 /* If BR/EDR is not enabled and we disable advertising as a
2146 * by-product of disabling connectable, we need to update the
2147 * advertising flags.
2148 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002149 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002150 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002151 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2152 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002153 }
2154 update_adv_data(&req);
2155 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002156 if (cp->val) {
2157 scan = SCAN_PAGE;
2158 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002159 /* If we don't have any whitelist entries just
2160 * disable all scanning. If there are entries
2161 * and we had both page and inquiry scanning
2162 * enabled then fall back to only page scanning.
2163 * Otherwise no changes are needed.
2164 */
2165 if (list_empty(&hdev->whitelist))
2166 scan = SCAN_DISABLED;
2167 else if (test_bit(HCI_ISCAN, &hdev->flags))
2168 scan = SCAN_PAGE;
2169 else
2170 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002171
2172 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002173 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002174 cancel_delayed_work(&hdev->discov_off);
2175 }
2176
2177 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2178 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002179
Johan Hedberg3bd27242014-07-28 20:53:58 +03002180no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002181 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002182 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2183 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002184 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002185
Johan Hedberg2b76f452013-03-15 17:07:04 -05002186 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002187 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002188 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002189 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002190 err = set_connectable_update_settings(hdev, sk,
2191 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002192 goto failed;
2193 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002194
2195failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002196 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002197 return err;
2198}
2199
Johan Hedbergb2939472014-07-30 09:22:23 +03002200static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002201 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002202{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002203 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002204 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002205 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002207 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002208
Johan Hedberga7e80f22013-01-09 16:05:19 +02002209 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002210 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2211 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002212
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002213 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002214
2215 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002216 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002217 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002218 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002219
Johan Hedbergb2939472014-07-30 09:22:23 +03002220 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002221 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002222 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002223
Marcel Holtmann55594352013-10-06 16:11:57 -07002224 if (changed)
2225 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002226
Marcel Holtmann55594352013-10-06 16:11:57 -07002227unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002228 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002229 return err;
2230}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002231
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002232static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2233 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002234{
2235 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002236 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002237 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002238 int err;
2239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002240 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002241
Johan Hedberge6fe7982013-10-02 15:45:22 +03002242 status = mgmt_bredr_support(hdev);
2243 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002244 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2245 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002246
Johan Hedberga7e80f22013-01-09 16:05:19 +02002247 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002248 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2249 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002250
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002251 hci_dev_lock(hdev);
2252
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002253 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002254 bool changed = false;
2255
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002256 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002257 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002258 changed = true;
2259 }
2260
2261 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2262 if (err < 0)
2263 goto failed;
2264
2265 if (changed)
2266 err = new_settings(hdev, sk);
2267
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002268 goto failed;
2269 }
2270
Johan Hedberg333ae952015-03-17 13:48:47 +02002271 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002272 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2273 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002274 goto failed;
2275 }
2276
2277 val = !!cp->val;
2278
2279 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2280 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2281 goto failed;
2282 }
2283
2284 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2285 if (!cmd) {
2286 err = -ENOMEM;
2287 goto failed;
2288 }
2289
2290 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2291 if (err < 0) {
2292 mgmt_pending_remove(cmd);
2293 goto failed;
2294 }
2295
2296failed:
2297 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002298 return err;
2299}
2300
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002301static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002302{
2303 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002304 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002305 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002306 int err;
2307
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002308 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002309
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002310 status = mgmt_bredr_support(hdev);
2311 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002312 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002313
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002314 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002315 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2316 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002317
Johan Hedberga7e80f22013-01-09 16:05:19 +02002318 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002319 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2320 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002321
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002322 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002323
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002324 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002325 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002326
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002327 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002328 changed = !hci_dev_test_and_set_flag(hdev,
2329 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002330 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002331 changed = hci_dev_test_and_clear_flag(hdev,
2332 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002333 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002334 changed = hci_dev_test_and_clear_flag(hdev,
2335 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002336 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002337 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002338 }
2339
2340 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2341 if (err < 0)
2342 goto failed;
2343
2344 if (changed)
2345 err = new_settings(hdev, sk);
2346
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002347 goto failed;
2348 }
2349
Johan Hedberg333ae952015-03-17 13:48:47 +02002350 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002351 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2352 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002353 goto failed;
2354 }
2355
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002356 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002357 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2358 goto failed;
2359 }
2360
2361 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2362 if (!cmd) {
2363 err = -ENOMEM;
2364 goto failed;
2365 }
2366
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002367 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002368 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2369 sizeof(cp->val), &cp->val);
2370
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002371 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002372 if (err < 0) {
2373 mgmt_pending_remove(cmd);
2374 goto failed;
2375 }
2376
2377failed:
2378 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002379 return err;
2380}
2381
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002382static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002383{
2384 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002385 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002386 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002387 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002389 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002390
Johan Hedberge6fe7982013-10-02 15:45:22 +03002391 status = mgmt_bredr_support(hdev);
2392 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002393 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002394
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002395 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002396 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2397 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002398
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002399 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002400 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2401 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002402
Johan Hedberga7e80f22013-01-09 16:05:19 +02002403 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002404 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2405 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002406
Marcel Holtmannee392692013-10-01 22:59:23 -07002407 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002408
Johan Hedberg333ae952015-03-17 13:48:47 +02002409 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002410 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2411 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002412 goto unlock;
2413 }
2414
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002415 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002416 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002417 } else {
2418 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002419 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2420 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002421 goto unlock;
2422 }
2423
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002424 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002425 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002426
2427 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2428 if (err < 0)
2429 goto unlock;
2430
2431 if (changed)
2432 err = new_settings(hdev, sk);
2433
2434unlock:
2435 hci_dev_unlock(hdev);
2436 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002437}
2438
Marcel Holtmann1904a852015-01-11 13:50:44 -08002439static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002440{
2441 struct cmd_lookup match = { NULL, hdev };
2442
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302443 hci_dev_lock(hdev);
2444
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002445 if (status) {
2446 u8 mgmt_err = mgmt_status(status);
2447
2448 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2449 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302450 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002451 }
2452
2453 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2454
2455 new_settings(hdev, match.sk);
2456
2457 if (match.sk)
2458 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002459
2460 /* Make sure the controller has a good default for
2461 * advertising data. Restrict the update to when LE
2462 * has actually been enabled. During power on, the
2463 * update in powered_update_hci will take care of it.
2464 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002465 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002466 struct hci_request req;
2467
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002468 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002469 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002470 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002471 hci_req_run(&req, NULL);
Johan Hedberg2e93e532015-11-11 08:11:17 +02002472 hci_update_background_scan(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002473 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302474
2475unlock:
2476 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002477}
2478
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002479static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002480{
2481 struct mgmt_mode *cp = data;
2482 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002483 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002484 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002485 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002486 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002487
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002488 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002489
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002490 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002491 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2492 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002493
Johan Hedberga7e80f22013-01-09 16:05:19 +02002494 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002495 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2496 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002497
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002498 /* Bluetooth single mode LE only controllers or dual-mode
2499 * controllers configured as LE only devices, do not allow
2500 * switching LE off. These have either LE enabled explicitly
2501 * or BR/EDR has been previously switched off.
2502 *
2503 * When trying to enable an already enabled LE, then gracefully
2504 * send a positive response. Trying to disable it however will
2505 * result into rejection.
2506 */
2507 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2508 if (cp->val == 0x01)
2509 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2510
Johan Hedberga69e8372015-03-06 21:08:53 +02002511 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2512 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002513 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002514
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002515 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002516
2517 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002518 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002519
Florian Grandel847818d2015-06-18 03:16:46 +02002520 if (!val)
2521 clear_adv_instance(hdev, NULL, 0x00, true);
2522
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002523 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002524 bool changed = false;
2525
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002526 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002527 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002528 changed = true;
2529 }
2530
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002531 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002532 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002533 changed = true;
2534 }
2535
Johan Hedberg06199cf2012-02-22 16:37:11 +02002536 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2537 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002538 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002539
2540 if (changed)
2541 err = new_settings(hdev, sk);
2542
Johan Hedberg1de028c2012-02-29 19:55:35 -08002543 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002544 }
2545
Johan Hedberg333ae952015-03-17 13:48:47 +02002546 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2547 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002548 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2549 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002550 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002551 }
2552
2553 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2554 if (!cmd) {
2555 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002556 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002557 }
2558
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002559 hci_req_init(&req, hdev);
2560
Johan Hedberg06199cf2012-02-22 16:37:11 +02002561 memset(&hci_cp, 0, sizeof(hci_cp));
2562
2563 if (val) {
2564 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002565 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002566 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002567 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002568 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002569 }
2570
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002571 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2572 &hci_cp);
2573
2574 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302575 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002576 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002577
Johan Hedberg1de028c2012-02-29 19:55:35 -08002578unlock:
2579 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002580 return err;
2581}
2582
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002583/* This is a helper function to test for pending mgmt commands that can
2584 * cause CoD or EIR HCI commands. We can only allow one such pending
2585 * mgmt command at a time since otherwise we cannot easily track what
2586 * the current values are, will be, and based on that calculate if a new
2587 * HCI command needs to be sent and if yes with what value.
2588 */
2589static bool pending_eir_or_class(struct hci_dev *hdev)
2590{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002591 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002592
2593 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2594 switch (cmd->opcode) {
2595 case MGMT_OP_ADD_UUID:
2596 case MGMT_OP_REMOVE_UUID:
2597 case MGMT_OP_SET_DEV_CLASS:
2598 case MGMT_OP_SET_POWERED:
2599 return true;
2600 }
2601 }
2602
2603 return false;
2604}
2605
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002606static const u8 bluetooth_base_uuid[] = {
2607 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2608 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2609};
2610
2611static u8 get_uuid_size(const u8 *uuid)
2612{
2613 u32 val;
2614
2615 if (memcmp(uuid, bluetooth_base_uuid, 12))
2616 return 128;
2617
2618 val = get_unaligned_le32(&uuid[12]);
2619 if (val > 0xffff)
2620 return 32;
2621
2622 return 16;
2623}
2624
Johan Hedberg92da6092013-03-15 17:06:55 -05002625static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2626{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002627 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002628
2629 hci_dev_lock(hdev);
2630
Johan Hedberg333ae952015-03-17 13:48:47 +02002631 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002632 if (!cmd)
2633 goto unlock;
2634
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002635 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2636 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002637
2638 mgmt_pending_remove(cmd);
2639
2640unlock:
2641 hci_dev_unlock(hdev);
2642}
2643
Marcel Holtmann1904a852015-01-11 13:50:44 -08002644static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002645{
2646 BT_DBG("status 0x%02x", status);
2647
2648 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2649}
2650
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002651static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002652{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002653 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002654 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002655 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002656 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002657 int err;
2658
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002659 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002660
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002661 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002662
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002663 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002664 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2665 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002666 goto failed;
2667 }
2668
Andre Guedes92c4c202012-06-07 19:05:44 -03002669 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002670 if (!uuid) {
2671 err = -ENOMEM;
2672 goto failed;
2673 }
2674
2675 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002676 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002677 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002678
Johan Hedbergde66aa62013-01-27 00:31:27 +02002679 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002680
Johan Hedberg890ea892013-03-15 17:06:52 -05002681 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002682
Johan Hedberg890ea892013-03-15 17:06:52 -05002683 update_class(&req);
2684 update_eir(&req);
2685
Johan Hedberg92da6092013-03-15 17:06:55 -05002686 err = hci_req_run(&req, add_uuid_complete);
2687 if (err < 0) {
2688 if (err != -ENODATA)
2689 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002690
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002691 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2692 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002693 goto failed;
2694 }
2695
2696 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002697 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002698 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002699 goto failed;
2700 }
2701
2702 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002703
2704failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002705 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002706 return err;
2707}
2708
Johan Hedberg24b78d02012-02-23 23:24:30 +02002709static bool enable_service_cache(struct hci_dev *hdev)
2710{
2711 if (!hdev_is_powered(hdev))
2712 return false;
2713
Marcel Holtmann238be782015-03-13 02:11:06 -07002714 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002715 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2716 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002717 return true;
2718 }
2719
2720 return false;
2721}
2722
Marcel Holtmann1904a852015-01-11 13:50:44 -08002723static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002724{
2725 BT_DBG("status 0x%02x", status);
2726
2727 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2728}
2729
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002730static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002731 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002732{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002733 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002734 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002735 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002736 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 -05002737 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002738 int err, found;
2739
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002740 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002741
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002742 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002743
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002744 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002745 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2746 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002747 goto unlock;
2748 }
2749
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002750 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002751 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002752
Johan Hedberg24b78d02012-02-23 23:24:30 +02002753 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002754 err = mgmt_cmd_complete(sk, hdev->id,
2755 MGMT_OP_REMOVE_UUID,
2756 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002757 goto unlock;
2758 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002759
Johan Hedberg9246a862012-02-23 21:33:16 +02002760 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002761 }
2762
2763 found = 0;
2764
Johan Hedberg056341c2013-01-27 00:31:30 +02002765 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002766 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2767 continue;
2768
2769 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002770 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002771 found++;
2772 }
2773
2774 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002775 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2776 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002777 goto unlock;
2778 }
2779
Johan Hedberg9246a862012-02-23 21:33:16 +02002780update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002781 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002782
Johan Hedberg890ea892013-03-15 17:06:52 -05002783 update_class(&req);
2784 update_eir(&req);
2785
Johan Hedberg92da6092013-03-15 17:06:55 -05002786 err = hci_req_run(&req, remove_uuid_complete);
2787 if (err < 0) {
2788 if (err != -ENODATA)
2789 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002790
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002791 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2792 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002793 goto unlock;
2794 }
2795
2796 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002797 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002798 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002799 goto unlock;
2800 }
2801
2802 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002803
2804unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002805 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002806 return err;
2807}
2808
Marcel Holtmann1904a852015-01-11 13:50:44 -08002809static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002810{
2811 BT_DBG("status 0x%02x", status);
2812
2813 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2814}
2815
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002816static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002817 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002818{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002819 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002820 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002821 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002822 int err;
2823
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002824 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002825
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002826 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002827 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2828 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002829
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002830 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002831
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002832 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002833 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2834 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002835 goto unlock;
2836 }
2837
2838 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002839 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2840 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002841 goto unlock;
2842 }
2843
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002844 hdev->major_class = cp->major;
2845 hdev->minor_class = cp->minor;
2846
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002847 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002848 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2849 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002850 goto unlock;
2851 }
2852
Johan Hedberg890ea892013-03-15 17:06:52 -05002853 hci_req_init(&req, hdev);
2854
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002855 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002856 hci_dev_unlock(hdev);
2857 cancel_delayed_work_sync(&hdev->service_cache);
2858 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002859 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002860 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002861
Johan Hedberg890ea892013-03-15 17:06:52 -05002862 update_class(&req);
2863
Johan Hedberg92da6092013-03-15 17:06:55 -05002864 err = hci_req_run(&req, set_class_complete);
2865 if (err < 0) {
2866 if (err != -ENODATA)
2867 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002868
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002869 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2870 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002871 goto unlock;
2872 }
2873
2874 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002875 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002876 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002877 goto unlock;
2878 }
2879
2880 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002881
Johan Hedbergb5235a62012-02-21 14:32:24 +02002882unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002883 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002884 return err;
2885}
2886
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002887static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002888 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002889{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002890 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002891 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2892 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002893 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002894 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002895 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002896
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002897 BT_DBG("request for %s", hdev->name);
2898
2899 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002900 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2901 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002902
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002903 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002904 if (key_count > max_key_count) {
2905 BT_ERR("load_link_keys: too big key_count value %u",
2906 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002907 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2908 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002909 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002910
Johan Hedberg86742e12011-11-07 23:13:38 +02002911 expected_len = sizeof(*cp) + key_count *
2912 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002913 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002914 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002915 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002916 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2917 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002918 }
2919
Johan Hedberg4ae14302013-01-20 14:27:13 +02002920 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002921 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2922 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002923
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002924 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002925 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002926
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002927 for (i = 0; i < key_count; i++) {
2928 struct mgmt_link_key_info *key = &cp->keys[i];
2929
Marcel Holtmann8e991132014-01-10 02:07:25 -08002930 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002931 return mgmt_cmd_status(sk, hdev->id,
2932 MGMT_OP_LOAD_LINK_KEYS,
2933 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002934 }
2935
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002936 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002937
2938 hci_link_keys_clear(hdev);
2939
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002940 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002941 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002942 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002943 changed = hci_dev_test_and_clear_flag(hdev,
2944 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002945
2946 if (changed)
2947 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002948
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002949 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002950 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002951
Johan Hedberg58e92932014-06-24 14:00:26 +03002952 /* Always ignore debug keys and require a new pairing if
2953 * the user wants to use them.
2954 */
2955 if (key->type == HCI_LK_DEBUG_COMBINATION)
2956 continue;
2957
Johan Hedberg7652ff62014-06-24 13:15:49 +03002958 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2959 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002960 }
2961
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002962 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002963
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002964 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002965
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002966 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002967}
2968
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002969static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002970 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002971{
2972 struct mgmt_ev_device_unpaired ev;
2973
2974 bacpy(&ev.addr.bdaddr, bdaddr);
2975 ev.addr.type = addr_type;
2976
2977 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002979}
2980
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002981static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002983{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002984 struct mgmt_cp_unpair_device *cp = data;
2985 struct mgmt_rp_unpair_device rp;
Johan Hedbergfc643612015-10-22 09:38:31 +03002986 struct hci_conn_params *params;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002987 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002988 struct hci_conn *conn;
Johan Hedbergec182f02015-10-21 18:03:03 +03002989 u8 addr_type;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002990 int err;
2991
Johan Hedberga8a1d192011-11-10 15:54:38 +02002992 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002993 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2994 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002995
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002996 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002997 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2998 MGMT_STATUS_INVALID_PARAMS,
2999 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003000
Johan Hedberg118da702013-01-20 14:27:20 +02003001 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003002 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3003 MGMT_STATUS_INVALID_PARAMS,
3004 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02003005
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003006 hci_dev_lock(hdev);
3007
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02003008 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003009 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3010 MGMT_STATUS_NOT_POWERED, &rp,
3011 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02003012 goto unlock;
3013 }
3014
Johan Hedberge0b2b272014-02-18 17:14:31 +02003015 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003016 /* If disconnection is requested, then look up the
3017 * connection. If the remote device is connected, it
3018 * will be later used to terminate the link.
3019 *
3020 * Setting it to NULL explicitly will cause no
3021 * termination of the link.
3022 */
3023 if (cp->disconnect)
3024 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3025 &cp->addr.bdaddr);
3026 else
3027 conn = NULL;
3028
Johan Hedberg124f6e32012-02-09 13:50:12 +02003029 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedbergec182f02015-10-21 18:03:03 +03003030 if (err < 0) {
3031 err = mgmt_cmd_complete(sk, hdev->id,
3032 MGMT_OP_UNPAIR_DEVICE,
3033 MGMT_STATUS_NOT_PAIRED, &rp,
3034 sizeof(rp));
3035 goto unlock;
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003036 }
3037
Johan Hedbergec182f02015-10-21 18:03:03 +03003038 goto done;
Johan Hedberge0b2b272014-02-18 17:14:31 +02003039 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03003040
Johan Hedbergec182f02015-10-21 18:03:03 +03003041 /* LE address type */
3042 addr_type = le_addr_type(cp->addr.type);
3043
3044 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
3045
3046 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003047 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003048 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3049 MGMT_STATUS_NOT_PAIRED, &rp,
3050 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003051 goto unlock;
3052 }
3053
Johan Hedbergec182f02015-10-21 18:03:03 +03003054 conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, addr_type);
3055 if (!conn) {
3056 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
3057 goto done;
3058 }
3059
Johan Hedbergc81d5552015-10-22 09:38:35 +03003060 /* Abort any ongoing SMP pairing */
3061 smp_cancel_pairing(conn);
3062
Johan Hedbergec182f02015-10-21 18:03:03 +03003063 /* Defer clearing up the connection parameters until closing to
3064 * give a chance of keeping them if a repairing happens.
3065 */
3066 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
3067
Johan Hedbergfc643612015-10-22 09:38:31 +03003068 /* Disable auto-connection parameters if present */
3069 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, addr_type);
3070 if (params) {
3071 if (params->explicit_connect)
3072 params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
3073 else
3074 params->auto_connect = HCI_AUTO_CONN_DISABLED;
3075 }
3076
Johan Hedbergec182f02015-10-21 18:03:03 +03003077 /* If disconnection is not requested, then clear the connection
3078 * variable so that the link is not terminated.
3079 */
3080 if (!cp->disconnect)
3081 conn = NULL;
3082
3083done:
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003084 /* If the connection variable is set, then termination of the
3085 * link is requested.
3086 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02003087 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003088 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3089 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003090 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003091 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003092 }
3093
Johan Hedberg124f6e32012-02-09 13:50:12 +02003094 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003095 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003096 if (!cmd) {
3097 err = -ENOMEM;
3098 goto unlock;
3099 }
3100
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003101 cmd->cmd_complete = addr_cmd_complete;
3102
Johan Hedberg89e0ccc2015-10-22 10:49:38 +03003103 err = hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003104 if (err < 0)
3105 mgmt_pending_remove(cmd);
3106
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003107unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003108 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003109 return err;
3110}
3111
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003112static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003113 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003114{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003115 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003116 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003117 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003118 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003119 int err;
3120
3121 BT_DBG("");
3122
Johan Hedberg06a63b12013-01-20 14:27:21 +02003123 memset(&rp, 0, sizeof(rp));
3124 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3125 rp.addr.type = cp->addr.type;
3126
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003127 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003128 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3129 MGMT_STATUS_INVALID_PARAMS,
3130 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003131
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003132 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003133
3134 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003135 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3136 MGMT_STATUS_NOT_POWERED, &rp,
3137 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003138 goto failed;
3139 }
3140
Johan Hedberg333ae952015-03-17 13:48:47 +02003141 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003142 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3143 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003144 goto failed;
3145 }
3146
Andre Guedes591f47f2012-04-24 21:02:49 -03003147 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003148 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3149 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003150 else
Johan Hedberg9d4c1cc2015-10-21 18:03:01 +03003151 conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
3152 le_addr_type(cp->addr.type));
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003153
Vishal Agarwalf9607272012-06-13 05:32:43 +05303154 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003155 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3156 MGMT_STATUS_NOT_CONNECTED, &rp,
3157 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003158 goto failed;
3159 }
3160
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003161 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003162 if (!cmd) {
3163 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003164 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003165 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003166
Johan Hedbergf5818c22014-12-05 13:36:02 +02003167 cmd->cmd_complete = generic_cmd_complete;
3168
Johan Hedberge3f2f922014-08-18 20:33:33 +03003169 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003170 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003171 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003172
3173failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003174 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003175 return err;
3176}
3177
Andre Guedes57c14772012-04-24 21:02:50 -03003178static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003179{
3180 switch (link_type) {
3181 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003182 switch (addr_type) {
3183 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003184 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003185
Johan Hedberg48264f02011-11-09 13:58:58 +02003186 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003187 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003188 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003189 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003190
Johan Hedberg4c659c32011-11-07 23:13:39 +02003191 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003192 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003193 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003194 }
3195}
3196
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003197static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3198 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003199{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003200 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003201 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003202 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003203 int err;
3204 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003205
3206 BT_DBG("");
3207
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003208 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003209
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003210 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003211 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3212 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003213 goto unlock;
3214 }
3215
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003216 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003217 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3218 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003219 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003220 }
3221
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003222 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003223 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003224 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003225 err = -ENOMEM;
3226 goto unlock;
3227 }
3228
Johan Hedberg2784eb42011-01-21 13:56:35 +02003229 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003230 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003231 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3232 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003233 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003234 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003235 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003236 continue;
3237 i++;
3238 }
3239
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003240 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003241
Johan Hedberg4c659c32011-11-07 23:13:39 +02003242 /* Recalculate length in case of filtered SCO connections, etc */
3243 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003244
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003245 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3246 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003247
Johan Hedberga38528f2011-01-22 06:46:43 +02003248 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003249
3250unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003251 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003252 return err;
3253}
3254
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003255static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003256 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003257{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003258 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003259 int err;
3260
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003261 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003262 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003263 if (!cmd)
3264 return -ENOMEM;
3265
Johan Hedbergd8457692012-02-17 14:24:57 +02003266 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003267 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003268 if (err < 0)
3269 mgmt_pending_remove(cmd);
3270
3271 return err;
3272}
3273
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003274static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003275 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003276{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003277 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003278 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003279 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003280 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003281 int err;
3282
3283 BT_DBG("");
3284
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003285 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003286
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003287 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003288 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3289 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003290 goto failed;
3291 }
3292
Johan Hedbergd8457692012-02-17 14:24:57 +02003293 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003294 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003295 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3296 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003297 goto failed;
3298 }
3299
3300 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003301 struct mgmt_cp_pin_code_neg_reply ncp;
3302
3303 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003304
3305 BT_ERR("PIN code is not 16 bytes long");
3306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003307 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003308 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003309 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3310 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003311
3312 goto failed;
3313 }
3314
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003315 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003316 if (!cmd) {
3317 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003318 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003319 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003320
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003321 cmd->cmd_complete = addr_cmd_complete;
3322
Johan Hedbergd8457692012-02-17 14:24:57 +02003323 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003324 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003325 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003326
3327 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3328 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003329 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003330
3331failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003332 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003333 return err;
3334}
3335
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003336static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3337 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003338{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003339 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003340
3341 BT_DBG("");
3342
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003343 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003344 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3345 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003346
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003347 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003348
3349 hdev->io_capability = cp->io_capability;
3350
3351 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003352 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003353
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003354 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003355
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003356 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3357 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003358}
3359
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003360static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003361{
3362 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003363 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003364
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003365 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003366 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3367 continue;
3368
Johan Hedberge9a416b2011-02-19 12:05:56 -03003369 if (cmd->user_data != conn)
3370 continue;
3371
3372 return cmd;
3373 }
3374
3375 return NULL;
3376}
3377
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003378static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003379{
3380 struct mgmt_rp_pair_device rp;
3381 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003382 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003383
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003384 bacpy(&rp.addr.bdaddr, &conn->dst);
3385 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003386
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003387 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3388 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003389
3390 /* So we don't get further callbacks for this connection */
3391 conn->connect_cfm_cb = NULL;
3392 conn->security_cfm_cb = NULL;
3393 conn->disconn_cfm_cb = NULL;
3394
David Herrmann76a68ba2013-04-06 20:28:37 +02003395 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003396
3397 /* The device is paired so there is no need to remove
3398 * its connection parameters anymore.
3399 */
3400 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003401
3402 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003403
3404 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003405}
3406
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003407void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3408{
3409 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003410 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003411
3412 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003413 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003414 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003415 mgmt_pending_remove(cmd);
3416 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003417}
3418
Johan Hedberge9a416b2011-02-19 12:05:56 -03003419static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3420{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003421 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003422
3423 BT_DBG("status %u", status);
3424
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003425 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003426 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003427 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003428 return;
3429 }
3430
3431 cmd->cmd_complete(cmd, mgmt_status(status));
3432 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003433}
3434
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003435static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303436{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003437 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303438
3439 BT_DBG("status %u", status);
3440
3441 if (!status)
3442 return;
3443
3444 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003445 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303446 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003447 return;
3448 }
3449
3450 cmd->cmd_complete(cmd, mgmt_status(status));
3451 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303452}
3453
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003454static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003455 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003456{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003457 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003458 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003459 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003460 u8 sec_level, auth_type;
3461 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003462 int err;
3463
3464 BT_DBG("");
3465
Szymon Jancf950a30e2013-01-18 12:48:07 +01003466 memset(&rp, 0, sizeof(rp));
3467 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3468 rp.addr.type = cp->addr.type;
3469
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003470 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003471 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3472 MGMT_STATUS_INVALID_PARAMS,
3473 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003474
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003475 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003476 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3477 MGMT_STATUS_INVALID_PARAMS,
3478 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003479
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003480 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003481
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003482 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003483 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3484 MGMT_STATUS_NOT_POWERED, &rp,
3485 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003486 goto unlock;
3487 }
3488
Johan Hedberg55e76b32015-03-10 22:34:40 +02003489 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3490 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3491 MGMT_STATUS_ALREADY_PAIRED, &rp,
3492 sizeof(rp));
3493 goto unlock;
3494 }
3495
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003496 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003497 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003498
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003499 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003500 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3501 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003502 } else {
Johan Hedberg85813a72015-10-21 18:02:59 +03003503 u8 addr_type = le_addr_type(cp->addr.type);
Jakub Pawlowski5157b8a2015-10-16 10:07:54 +03003504 struct hci_conn_params *p;
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003505
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003506 /* When pairing a new device, it is expected to remember
3507 * this device for future connections. Adding the connection
3508 * parameter information ahead of time allows tracking
3509 * of the slave preferred values and will speed up any
3510 * further connection establishment.
3511 *
3512 * If connection parameters already exist, then they
3513 * will be kept and this function does nothing.
3514 */
Jakub Pawlowski5157b8a2015-10-16 10:07:54 +03003515 p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3516
3517 if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
3518 p->auto_connect = HCI_AUTO_CONN_DISABLED;
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003519
Jakub Pawlowskifa142222015-08-07 20:22:56 +02003520 conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
3521 addr_type, sec_level,
Johan Hedberg0ad06aa2015-11-11 14:44:57 +02003522 HCI_LE_CONN_TIMEOUT);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003523 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003524
Ville Tervo30e76272011-02-22 16:10:53 -03003525 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003526 int status;
3527
3528 if (PTR_ERR(conn) == -EBUSY)
3529 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003530 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3531 status = MGMT_STATUS_NOT_SUPPORTED;
3532 else if (PTR_ERR(conn) == -ECONNREFUSED)
3533 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003534 else
3535 status = MGMT_STATUS_CONNECT_FAILED;
3536
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003537 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3538 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003539 goto unlock;
3540 }
3541
3542 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003543 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003544 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3545 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003546 goto unlock;
3547 }
3548
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003549 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003550 if (!cmd) {
3551 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003552 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003553 goto unlock;
3554 }
3555
Johan Hedberg04ab2742014-12-05 13:36:04 +02003556 cmd->cmd_complete = pairing_complete;
3557
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003558 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003559 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003560 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003561 conn->security_cfm_cb = pairing_complete_cb;
3562 conn->disconn_cfm_cb = pairing_complete_cb;
3563 } else {
3564 conn->connect_cfm_cb = le_pairing_complete_cb;
3565 conn->security_cfm_cb = le_pairing_complete_cb;
3566 conn->disconn_cfm_cb = le_pairing_complete_cb;
3567 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003568
Johan Hedberge9a416b2011-02-19 12:05:56 -03003569 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003570 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003571
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003572 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003573 hci_conn_security(conn, sec_level, auth_type, true)) {
3574 cmd->cmd_complete(cmd, 0);
3575 mgmt_pending_remove(cmd);
3576 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003577
3578 err = 0;
3579
3580unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003581 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003582 return err;
3583}
3584
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003585static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3586 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003587{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003588 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003589 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003590 struct hci_conn *conn;
3591 int err;
3592
3593 BT_DBG("");
3594
Johan Hedberg28424702012-02-02 04:02:29 +02003595 hci_dev_lock(hdev);
3596
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003597 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003598 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3599 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003600 goto unlock;
3601 }
3602
Johan Hedberg333ae952015-03-17 13:48:47 +02003603 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003604 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003605 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3606 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003607 goto unlock;
3608 }
3609
3610 conn = cmd->user_data;
3611
3612 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003613 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3614 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003615 goto unlock;
3616 }
3617
Johan Hedberga511b352014-12-11 21:45:45 +02003618 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3619 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003620
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003621 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3622 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003623unlock:
3624 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003625 return err;
3626}
3627
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003628static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003629 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003630 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003631{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003632 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003633 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003634 int err;
3635
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003636 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003637
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003638 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003639 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3640 MGMT_STATUS_NOT_POWERED, addr,
3641 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003642 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003643 }
3644
Johan Hedberg1707c602013-03-15 17:07:15 -05003645 if (addr->type == BDADDR_BREDR)
3646 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003647 else
Johan Hedberg9d4c1cc2015-10-21 18:03:01 +03003648 conn = hci_conn_hash_lookup_le(hdev, &addr->bdaddr,
3649 le_addr_type(addr->type));
Brian Gix47c15e22011-11-16 13:53:14 -08003650
Johan Hedberg272d90d2012-02-09 15:26:12 +02003651 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003652 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3653 MGMT_STATUS_NOT_CONNECTED, addr,
3654 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003655 goto done;
3656 }
3657
Johan Hedberg1707c602013-03-15 17:07:15 -05003658 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003659 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003660 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003661 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3662 MGMT_STATUS_SUCCESS, addr,
3663 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003664 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003665 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3666 MGMT_STATUS_FAILED, addr,
3667 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003668
Brian Gix47c15e22011-11-16 13:53:14 -08003669 goto done;
3670 }
3671
Johan Hedberg1707c602013-03-15 17:07:15 -05003672 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003673 if (!cmd) {
3674 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003675 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003676 }
3677
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003678 cmd->cmd_complete = addr_cmd_complete;
3679
Brian Gix0df4c182011-11-16 13:53:13 -08003680 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003681 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3682 struct hci_cp_user_passkey_reply cp;
3683
Johan Hedberg1707c602013-03-15 17:07:15 -05003684 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003685 cp.passkey = passkey;
3686 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3687 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003688 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3689 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003690
Johan Hedberga664b5b2011-02-19 12:06:02 -03003691 if (err < 0)
3692 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003693
Brian Gix0df4c182011-11-16 13:53:13 -08003694done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003695 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003696 return err;
3697}
3698
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303699static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3700 void *data, u16 len)
3701{
3702 struct mgmt_cp_pin_code_neg_reply *cp = data;
3703
3704 BT_DBG("");
3705
Johan Hedberg1707c602013-03-15 17:07:15 -05003706 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303707 MGMT_OP_PIN_CODE_NEG_REPLY,
3708 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3709}
3710
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003711static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3712 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003713{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003714 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003715
3716 BT_DBG("");
3717
3718 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003719 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3720 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003721
Johan Hedberg1707c602013-03-15 17:07:15 -05003722 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003723 MGMT_OP_USER_CONFIRM_REPLY,
3724 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003725}
3726
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003727static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003728 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003729{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003730 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003731
3732 BT_DBG("");
3733
Johan Hedberg1707c602013-03-15 17:07:15 -05003734 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003735 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3736 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003737}
3738
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003739static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3740 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003741{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003742 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003743
3744 BT_DBG("");
3745
Johan Hedberg1707c602013-03-15 17:07:15 -05003746 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003747 MGMT_OP_USER_PASSKEY_REPLY,
3748 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003749}
3750
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003751static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003752 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003753{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003754 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003755
3756 BT_DBG("");
3757
Johan Hedberg1707c602013-03-15 17:07:15 -05003758 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003759 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3760 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003761}
3762
Johan Hedberg13928972013-03-15 17:07:00 -05003763static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003764{
Johan Hedberg13928972013-03-15 17:07:00 -05003765 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003766 struct hci_cp_write_local_name cp;
3767
Johan Hedberg13928972013-03-15 17:07:00 -05003768 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003769
Johan Hedberg890ea892013-03-15 17:06:52 -05003770 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003771}
3772
Marcel Holtmann1904a852015-01-11 13:50:44 -08003773static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003774{
3775 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003776 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003777
3778 BT_DBG("status 0x%02x", status);
3779
3780 hci_dev_lock(hdev);
3781
Johan Hedberg333ae952015-03-17 13:48:47 +02003782 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003783 if (!cmd)
3784 goto unlock;
3785
3786 cp = cmd->param;
3787
3788 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003789 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3790 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003791 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003792 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3793 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003794
3795 mgmt_pending_remove(cmd);
3796
3797unlock:
3798 hci_dev_unlock(hdev);
3799}
3800
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003801static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003802 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003803{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003804 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003805 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003806 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003807 int err;
3808
3809 BT_DBG("");
3810
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003811 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003812
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003813 /* If the old values are the same as the new ones just return a
3814 * direct command complete event.
3815 */
3816 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3817 !memcmp(hdev->short_name, cp->short_name,
3818 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003819 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3820 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003821 goto failed;
3822 }
3823
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003824 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003825
Johan Hedbergb5235a62012-02-21 14:32:24 +02003826 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003827 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003828
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003829 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3830 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003831 if (err < 0)
3832 goto failed;
3833
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003834 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3835 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003836
Johan Hedbergb5235a62012-02-21 14:32:24 +02003837 goto failed;
3838 }
3839
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003840 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003841 if (!cmd) {
3842 err = -ENOMEM;
3843 goto failed;
3844 }
3845
Johan Hedberg13928972013-03-15 17:07:00 -05003846 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3847
Johan Hedberg890ea892013-03-15 17:06:52 -05003848 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003849
3850 if (lmp_bredr_capable(hdev)) {
3851 update_name(&req);
3852 update_eir(&req);
3853 }
3854
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003855 /* The name is stored in the scan response data and so
3856 * no need to udpate the advertising data here.
3857 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003858 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003859 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003860
Johan Hedberg13928972013-03-15 17:07:00 -05003861 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003862 if (err < 0)
3863 mgmt_pending_remove(cmd);
3864
3865failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003866 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003867 return err;
3868}
3869
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003870static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3871 u16 opcode, struct sk_buff *skb)
3872{
3873 struct mgmt_rp_read_local_oob_data mgmt_rp;
3874 size_t rp_size = sizeof(mgmt_rp);
3875 struct mgmt_pending_cmd *cmd;
3876
3877 BT_DBG("%s status %u", hdev->name, status);
3878
3879 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3880 if (!cmd)
3881 return;
3882
3883 if (status || !skb) {
3884 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3885 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3886 goto remove;
3887 }
3888
3889 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3890
3891 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3892 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3893
3894 if (skb->len < sizeof(*rp)) {
3895 mgmt_cmd_status(cmd->sk, hdev->id,
3896 MGMT_OP_READ_LOCAL_OOB_DATA,
3897 MGMT_STATUS_FAILED);
3898 goto remove;
3899 }
3900
3901 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3902 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3903
3904 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3905 } else {
3906 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3907
3908 if (skb->len < sizeof(*rp)) {
3909 mgmt_cmd_status(cmd->sk, hdev->id,
3910 MGMT_OP_READ_LOCAL_OOB_DATA,
3911 MGMT_STATUS_FAILED);
3912 goto remove;
3913 }
3914
3915 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3916 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3917
3918 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3919 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3920 }
3921
3922 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3923 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3924
3925remove:
3926 mgmt_pending_remove(cmd);
3927}
3928
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003929static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003930 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003931{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003932 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003933 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003934 int err;
3935
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003936 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003937
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003938 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003939
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003940 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003941 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3942 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003943 goto unlock;
3944 }
3945
Andre Guedes9a1a1992012-07-24 15:03:48 -03003946 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003947 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3948 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003949 goto unlock;
3950 }
3951
Johan Hedberg333ae952015-03-17 13:48:47 +02003952 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003953 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3954 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003955 goto unlock;
3956 }
3957
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003958 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003959 if (!cmd) {
3960 err = -ENOMEM;
3961 goto unlock;
3962 }
3963
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003964 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003965
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003966 if (bredr_sc_enabled(hdev))
3967 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3968 else
3969 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3970
3971 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003972 if (err < 0)
3973 mgmt_pending_remove(cmd);
3974
3975unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003976 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003977 return err;
3978}
3979
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003980static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003981 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003982{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003983 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003984 int err;
3985
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003986 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003987
Johan Hedberg5d57e792015-01-23 10:10:38 +02003988 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003989 return mgmt_cmd_complete(sk, hdev->id,
3990 MGMT_OP_ADD_REMOTE_OOB_DATA,
3991 MGMT_STATUS_INVALID_PARAMS,
3992 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003993
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003994 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003995
Marcel Holtmannec109112014-01-10 02:07:30 -08003996 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3997 struct mgmt_cp_add_remote_oob_data *cp = data;
3998 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003999
Johan Hedbergc19a4952014-11-17 20:52:19 +02004000 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004001 err = mgmt_cmd_complete(sk, hdev->id,
4002 MGMT_OP_ADD_REMOTE_OOB_DATA,
4003 MGMT_STATUS_INVALID_PARAMS,
4004 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004005 goto unlock;
4006 }
4007
Marcel Holtmannec109112014-01-10 02:07:30 -08004008 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01004009 cp->addr.type, cp->hash,
4010 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08004011 if (err < 0)
4012 status = MGMT_STATUS_FAILED;
4013 else
4014 status = MGMT_STATUS_SUCCESS;
4015
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004016 err = mgmt_cmd_complete(sk, hdev->id,
4017 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
4018 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08004019 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
4020 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004021 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08004022 u8 status;
4023
Johan Hedberg86df9202014-10-26 20:52:27 +01004024 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02004025 /* Enforce zero-valued 192-bit parameters as
4026 * long as legacy SMP OOB isn't implemented.
4027 */
4028 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
4029 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004030 err = mgmt_cmd_complete(sk, hdev->id,
4031 MGMT_OP_ADD_REMOTE_OOB_DATA,
4032 MGMT_STATUS_INVALID_PARAMS,
4033 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02004034 goto unlock;
4035 }
4036
Johan Hedberg86df9202014-10-26 20:52:27 +01004037 rand192 = NULL;
4038 hash192 = NULL;
4039 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004040 /* In case one of the P-192 values is set to zero,
4041 * then just disable OOB data for P-192.
4042 */
4043 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
4044 !memcmp(cp->hash192, ZERO_KEY, 16)) {
4045 rand192 = NULL;
4046 hash192 = NULL;
4047 } else {
4048 rand192 = cp->rand192;
4049 hash192 = cp->hash192;
4050 }
4051 }
4052
4053 /* In case one of the P-256 values is set to zero, then just
4054 * disable OOB data for P-256.
4055 */
4056 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
4057 !memcmp(cp->hash256, ZERO_KEY, 16)) {
4058 rand256 = NULL;
4059 hash256 = NULL;
4060 } else {
4061 rand256 = cp->rand256;
4062 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01004063 }
4064
Johan Hedberg81328d52014-10-26 20:33:47 +01004065 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01004066 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004067 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08004068 if (err < 0)
4069 status = MGMT_STATUS_FAILED;
4070 else
4071 status = MGMT_STATUS_SUCCESS;
4072
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004073 err = mgmt_cmd_complete(sk, hdev->id,
4074 MGMT_OP_ADD_REMOTE_OOB_DATA,
4075 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08004076 } else {
4077 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02004078 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
4079 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08004080 }
Szymon Janc2763eda2011-03-22 13:12:22 +01004081
Johan Hedbergc19a4952014-11-17 20:52:19 +02004082unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004083 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004084 return err;
4085}
4086
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004087static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004088 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01004089{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004090 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004091 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01004092 int err;
4093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004094 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01004095
Johan Hedbergc19a4952014-11-17 20:52:19 +02004096 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004097 return mgmt_cmd_complete(sk, hdev->id,
4098 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4099 MGMT_STATUS_INVALID_PARAMS,
4100 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004101
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004102 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004103
Johan Hedbergeedbd582014-11-15 09:34:23 +02004104 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4105 hci_remote_oob_data_clear(hdev);
4106 status = MGMT_STATUS_SUCCESS;
4107 goto done;
4108 }
4109
Johan Hedberg6928a922014-10-26 20:46:09 +01004110 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004111 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004112 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004113 else
Szymon Janca6785be2012-12-13 15:11:21 +01004114 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004115
Johan Hedbergeedbd582014-11-15 09:34:23 +02004116done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004117 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4118 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004119
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004120 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004121 return err;
4122}
4123
Johan Hedberge68f0722015-11-11 08:30:30 +02004124void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
Andre Guedes7c307722013-04-30 15:29:28 -03004125{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004126 struct mgmt_pending_cmd *cmd;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004127
Andre Guedes7c307722013-04-30 15:29:28 -03004128 BT_DBG("status %d", status);
4129
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004130 hci_dev_lock(hdev);
4131
Johan Hedberg333ae952015-03-17 13:48:47 +02004132 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004133 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004134 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004135
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004136 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004137 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004138 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004139 }
4140
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004141 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004142}
4143
Johan Hedberg591752a2015-11-11 08:11:24 +02004144static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type,
4145 uint8_t *mgmt_status)
4146{
4147 switch (type) {
4148 case DISCOV_TYPE_LE:
4149 *mgmt_status = mgmt_le_support(hdev);
4150 if (*mgmt_status)
4151 return false;
4152 break;
4153 case DISCOV_TYPE_INTERLEAVED:
4154 *mgmt_status = mgmt_le_support(hdev);
4155 if (*mgmt_status)
4156 return false;
4157 /* Intentional fall-through */
4158 case DISCOV_TYPE_BREDR:
4159 *mgmt_status = mgmt_bredr_support(hdev);
4160 if (*mgmt_status)
4161 return false;
4162 break;
4163 default:
4164 *mgmt_status = MGMT_STATUS_INVALID_PARAMS;
4165 return false;
4166 }
4167
4168 return true;
4169}
4170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004171static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004172 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004173{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004174 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004175 struct mgmt_pending_cmd *cmd;
Marcel Holtmann80190442014-12-04 11:36:36 +01004176 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004177 int err;
4178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004179 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004180
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004181 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004182
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004183 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004184 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4185 MGMT_STATUS_NOT_POWERED,
4186 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004187 goto failed;
4188 }
4189
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004190 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004191 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004192 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4193 MGMT_STATUS_BUSY, &cp->type,
4194 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004195 goto failed;
4196 }
4197
Johan Hedberg591752a2015-11-11 08:11:24 +02004198 if (!discovery_type_is_valid(hdev, cp->type, &status)) {
4199 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4200 status, &cp->type, sizeof(cp->type));
4201 goto failed;
4202 }
4203
Marcel Holtmann22078802014-12-05 11:45:22 +01004204 /* Clear the discovery filter first to free any previously
4205 * allocated memory for the UUID list.
4206 */
4207 hci_discovery_filter_clear(hdev);
4208
Andre Guedes4aab14e2012-02-17 20:39:36 -03004209 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004210 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004211
Johan Hedberge68f0722015-11-11 08:30:30 +02004212 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
4213 if (!cmd) {
4214 err = -ENOMEM;
Johan Hedberg04106752013-01-10 14:54:09 +02004215 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004216 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004217
Johan Hedberge68f0722015-11-11 08:30:30 +02004218 cmd->cmd_complete = generic_cmd_complete;
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004219
4220 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberge68f0722015-11-11 08:30:30 +02004221 queue_work(hdev->req_workqueue, &hdev->discov_update);
4222 err = 0;
Johan Hedberg14a53662011-04-27 10:29:56 -04004223
4224failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004225 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004226 return err;
4227}
4228
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004229static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4230 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004231{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004232 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4233 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004234}
4235
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004236static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4237 void *data, u16 len)
4238{
4239 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004240 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004241 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4242 u16 uuid_count, expected_len;
4243 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004244 int err;
4245
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004246 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004247
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004248 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004249
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004250 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004251 err = mgmt_cmd_complete(sk, hdev->id,
4252 MGMT_OP_START_SERVICE_DISCOVERY,
4253 MGMT_STATUS_NOT_POWERED,
4254 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004255 goto failed;
4256 }
4257
4258 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004259 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004260 err = mgmt_cmd_complete(sk, hdev->id,
4261 MGMT_OP_START_SERVICE_DISCOVERY,
4262 MGMT_STATUS_BUSY, &cp->type,
4263 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004264 goto failed;
4265 }
4266
4267 uuid_count = __le16_to_cpu(cp->uuid_count);
4268 if (uuid_count > max_uuid_count) {
4269 BT_ERR("service_discovery: too big uuid_count value %u",
4270 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004271 err = mgmt_cmd_complete(sk, hdev->id,
4272 MGMT_OP_START_SERVICE_DISCOVERY,
4273 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4274 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004275 goto failed;
4276 }
4277
4278 expected_len = sizeof(*cp) + uuid_count * 16;
4279 if (expected_len != len) {
4280 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4281 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004282 err = mgmt_cmd_complete(sk, hdev->id,
4283 MGMT_OP_START_SERVICE_DISCOVERY,
4284 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4285 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004286 goto failed;
4287 }
4288
Johan Hedberg591752a2015-11-11 08:11:24 +02004289 if (!discovery_type_is_valid(hdev, cp->type, &status)) {
4290 err = mgmt_cmd_complete(sk, hdev->id,
4291 MGMT_OP_START_SERVICE_DISCOVERY,
4292 status, &cp->type, sizeof(cp->type));
4293 goto failed;
4294 }
4295
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004296 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004297 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004298 if (!cmd) {
4299 err = -ENOMEM;
4300 goto failed;
4301 }
4302
Johan Hedberg2922a942014-12-05 13:36:06 +02004303 cmd->cmd_complete = service_discovery_cmd_complete;
4304
Marcel Holtmann22078802014-12-05 11:45:22 +01004305 /* Clear the discovery filter first to free any previously
4306 * allocated memory for the UUID list.
4307 */
4308 hci_discovery_filter_clear(hdev);
4309
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004310 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004311 hdev->discovery.type = cp->type;
4312 hdev->discovery.rssi = cp->rssi;
4313 hdev->discovery.uuid_count = uuid_count;
4314
4315 if (uuid_count > 0) {
4316 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4317 GFP_KERNEL);
4318 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004319 err = mgmt_cmd_complete(sk, hdev->id,
4320 MGMT_OP_START_SERVICE_DISCOVERY,
4321 MGMT_STATUS_FAILED,
4322 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004323 mgmt_pending_remove(cmd);
4324 goto failed;
4325 }
4326 }
4327
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004328 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberge68f0722015-11-11 08:30:30 +02004329 queue_work(hdev->req_workqueue, &hdev->discov_update);
4330 err = 0;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004331
4332failed:
4333 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004334 return err;
4335}
4336
Johan Hedberg2154d3f2015-11-11 08:30:45 +02004337void mgmt_stop_discovery_complete(struct hci_dev *hdev, u8 status)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004338{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004339 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004340
Andre Guedes0e05bba2013-04-30 15:29:33 -03004341 BT_DBG("status %d", status);
4342
4343 hci_dev_lock(hdev);
4344
Johan Hedberg333ae952015-03-17 13:48:47 +02004345 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004346 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004347 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004348 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004349 }
4350
Andre Guedes0e05bba2013-04-30 15:29:33 -03004351 hci_dev_unlock(hdev);
4352}
4353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004354static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004355 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004356{
Johan Hedbergd9306502012-02-20 23:25:18 +02004357 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004358 struct mgmt_pending_cmd *cmd;
Johan Hedberg14a53662011-04-27 10:29:56 -04004359 int err;
4360
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004361 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004362
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004363 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004364
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004365 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004366 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4367 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4368 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004369 goto unlock;
4370 }
4371
4372 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004373 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4374 MGMT_STATUS_INVALID_PARAMS,
4375 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004376 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004377 }
4378
Johan Hedberg2922a942014-12-05 13:36:06 +02004379 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004380 if (!cmd) {
4381 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004382 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004383 }
4384
Johan Hedberg2922a942014-12-05 13:36:06 +02004385 cmd->cmd_complete = generic_cmd_complete;
4386
Johan Hedberg2154d3f2015-11-11 08:30:45 +02004387 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
4388 queue_work(hdev->req_workqueue, &hdev->discov_update);
4389 err = 0;
Johan Hedberg14a53662011-04-27 10:29:56 -04004390
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004391unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004392 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004393 return err;
4394}
4395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004396static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004397 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004398{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004399 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004400 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004401 int err;
4402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004403 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004404
Johan Hedberg561aafb2012-01-04 13:31:59 +02004405 hci_dev_lock(hdev);
4406
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004407 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004408 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4409 MGMT_STATUS_FAILED, &cp->addr,
4410 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004411 goto failed;
4412 }
4413
Johan Hedberga198e7b2012-02-17 14:27:06 +02004414 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004415 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004416 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4417 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4418 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004419 goto failed;
4420 }
4421
4422 if (cp->name_known) {
4423 e->name_state = NAME_KNOWN;
4424 list_del(&e->list);
4425 } else {
4426 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004427 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004428 }
4429
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004430 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4431 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004432
4433failed:
4434 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004435 return err;
4436}
4437
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004438static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004439 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004440{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004441 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004442 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004443 int err;
4444
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004445 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004446
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004447 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004448 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4449 MGMT_STATUS_INVALID_PARAMS,
4450 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004451
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004452 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004453
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004454 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4455 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004456 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004457 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004458 goto done;
4459 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004460
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004461 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4462 sk);
4463 status = MGMT_STATUS_SUCCESS;
4464
4465done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004466 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4467 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004468
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004469 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004470
4471 return err;
4472}
4473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004474static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004475 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004477 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004478 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004479 int err;
4480
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004481 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004482
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004483 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004484 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4485 MGMT_STATUS_INVALID_PARAMS,
4486 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004487
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004488 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004489
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004490 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4491 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004492 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004493 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004494 goto done;
4495 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004496
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004497 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4498 sk);
4499 status = MGMT_STATUS_SUCCESS;
4500
4501done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004502 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4503 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004504
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004505 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004506
4507 return err;
4508}
4509
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004510static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4511 u16 len)
4512{
4513 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004514 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004515 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004516 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004517
4518 BT_DBG("%s", hdev->name);
4519
Szymon Jancc72d4b82012-03-16 16:02:57 +01004520 source = __le16_to_cpu(cp->source);
4521
4522 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004523 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4524 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004525
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004526 hci_dev_lock(hdev);
4527
Szymon Jancc72d4b82012-03-16 16:02:57 +01004528 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004529 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4530 hdev->devid_product = __le16_to_cpu(cp->product);
4531 hdev->devid_version = __le16_to_cpu(cp->version);
4532
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004533 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4534 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004535
Johan Hedberg890ea892013-03-15 17:06:52 -05004536 hci_req_init(&req, hdev);
4537 update_eir(&req);
4538 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004539
4540 hci_dev_unlock(hdev);
4541
4542 return err;
4543}
4544
Arman Uguray24b4f382015-03-23 15:57:12 -07004545static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4546 u16 opcode)
4547{
4548 BT_DBG("status %d", status);
4549}
4550
Marcel Holtmann1904a852015-01-11 13:50:44 -08004551static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4552 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004553{
4554 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004555 struct hci_request req;
Florian Grandel7816b822015-06-18 03:16:45 +02004556 u8 instance;
4557 struct adv_info *adv_instance;
4558 int err;
Johan Hedberg4375f102013-09-25 13:26:10 +03004559
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304560 hci_dev_lock(hdev);
4561
Johan Hedberg4375f102013-09-25 13:26:10 +03004562 if (status) {
4563 u8 mgmt_err = mgmt_status(status);
4564
4565 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4566 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304567 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004568 }
4569
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004570 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004571 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004572 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004573 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004574
Johan Hedberg4375f102013-09-25 13:26:10 +03004575 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4576 &match);
4577
4578 new_settings(hdev, match.sk);
4579
4580 if (match.sk)
4581 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304582
Arman Uguray24b4f382015-03-23 15:57:12 -07004583 /* If "Set Advertising" was just disabled and instance advertising was
Florian Grandel7816b822015-06-18 03:16:45 +02004584 * set up earlier, then re-enable multi-instance advertising.
Arman Uguray24b4f382015-03-23 15:57:12 -07004585 */
4586 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
Florian Grandel7816b822015-06-18 03:16:45 +02004587 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) ||
4588 list_empty(&hdev->adv_instances))
Arman Uguray24b4f382015-03-23 15:57:12 -07004589 goto unlock;
4590
Florian Grandel7816b822015-06-18 03:16:45 +02004591 instance = hdev->cur_adv_instance;
4592 if (!instance) {
4593 adv_instance = list_first_entry_or_null(&hdev->adv_instances,
4594 struct adv_info, list);
4595 if (!adv_instance)
4596 goto unlock;
4597
4598 instance = adv_instance->instance;
4599 }
4600
Arman Uguray24b4f382015-03-23 15:57:12 -07004601 hci_req_init(&req, hdev);
4602
Florian Grandel7816b822015-06-18 03:16:45 +02004603 err = schedule_adv_instance(&req, instance, true);
Arman Uguray24b4f382015-03-23 15:57:12 -07004604
Florian Grandel7816b822015-06-18 03:16:45 +02004605 if (!err)
4606 err = hci_req_run(&req, enable_advertising_instance);
4607
4608 if (err)
Arman Uguray24b4f382015-03-23 15:57:12 -07004609 BT_ERR("Failed to re-configure advertising");
4610
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304611unlock:
4612 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004613}
4614
Marcel Holtmann21b51872013-10-10 09:47:53 -07004615static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4616 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004617{
4618 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004619 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004620 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004621 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004622 int err;
4623
4624 BT_DBG("request for %s", hdev->name);
4625
Johan Hedberge6fe7982013-10-02 15:45:22 +03004626 status = mgmt_le_support(hdev);
4627 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004628 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4629 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004630
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004631 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004632 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4633 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004634
4635 hci_dev_lock(hdev);
4636
4637 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004638
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004639 /* The following conditions are ones which mean that we should
4640 * not do any HCI communication but directly send a mgmt
4641 * response to user space (after toggling the flag if
4642 * necessary).
4643 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004644 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004645 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4646 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004647 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004648 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004649 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004650 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004651
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004652 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004653 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004654 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004655 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004656 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004657 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004658 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004659 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004660 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004661 }
4662
4663 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4664 if (err < 0)
4665 goto unlock;
4666
4667 if (changed)
4668 err = new_settings(hdev, sk);
4669
4670 goto unlock;
4671 }
4672
Johan Hedberg333ae952015-03-17 13:48:47 +02004673 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4674 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004675 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4676 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004677 goto unlock;
4678 }
4679
4680 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4681 if (!cmd) {
4682 err = -ENOMEM;
4683 goto unlock;
4684 }
4685
4686 hci_req_init(&req, hdev);
4687
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004688 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004689 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004690 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004691 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004692
Florian Grandel7816b822015-06-18 03:16:45 +02004693 cancel_adv_timeout(hdev);
4694
Arman Uguray24b4f382015-03-23 15:57:12 -07004695 if (val) {
Florian Grandel7816b822015-06-18 03:16:45 +02004696 /* Switch to instance "0" for the Set Advertising setting.
4697 * We cannot use update_[adv|scan_rsp]_data() here as the
4698 * HCI_ADVERTISING flag is not yet set.
4699 */
Florian Grandelefae0022015-06-18 03:16:37 +02004700 update_inst_adv_data(&req, 0x00);
4701 update_inst_scan_rsp_data(&req, 0x00);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004702 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004703 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004704 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004705 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004706
4707 err = hci_req_run(&req, set_advertising_complete);
4708 if (err < 0)
4709 mgmt_pending_remove(cmd);
4710
4711unlock:
4712 hci_dev_unlock(hdev);
4713 return err;
4714}
4715
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004716static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4717 void *data, u16 len)
4718{
4719 struct mgmt_cp_set_static_address *cp = data;
4720 int err;
4721
4722 BT_DBG("%s", hdev->name);
4723
Marcel Holtmann62af4442013-10-02 22:10:32 -07004724 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004725 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4726 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004727
4728 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004729 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4730 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004731
4732 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4733 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004734 return mgmt_cmd_status(sk, hdev->id,
4735 MGMT_OP_SET_STATIC_ADDRESS,
4736 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004737
4738 /* Two most significant bits shall be set */
4739 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004740 return mgmt_cmd_status(sk, hdev->id,
4741 MGMT_OP_SET_STATIC_ADDRESS,
4742 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004743 }
4744
4745 hci_dev_lock(hdev);
4746
4747 bacpy(&hdev->static_addr, &cp->bdaddr);
4748
Marcel Holtmann93690c22015-03-06 10:11:21 -08004749 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4750 if (err < 0)
4751 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004752
Marcel Holtmann93690c22015-03-06 10:11:21 -08004753 err = new_settings(hdev, sk);
4754
4755unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004756 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004757 return err;
4758}
4759
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004760static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4761 void *data, u16 len)
4762{
4763 struct mgmt_cp_set_scan_params *cp = data;
4764 __u16 interval, window;
4765 int err;
4766
4767 BT_DBG("%s", hdev->name);
4768
4769 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004770 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4771 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004772
4773 interval = __le16_to_cpu(cp->interval);
4774
4775 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004776 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4777 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004778
4779 window = __le16_to_cpu(cp->window);
4780
4781 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004782 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4783 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004784
Marcel Holtmann899e1072013-10-14 09:55:32 -07004785 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004786 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4787 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004788
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004789 hci_dev_lock(hdev);
4790
4791 hdev->le_scan_interval = interval;
4792 hdev->le_scan_window = window;
4793
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004794 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4795 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004796
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004797 /* If background scan is running, restart it so new parameters are
4798 * loaded.
4799 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004800 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004801 hdev->discovery.state == DISCOVERY_STOPPED) {
4802 struct hci_request req;
4803
4804 hci_req_init(&req, hdev);
4805
4806 hci_req_add_le_scan_disable(&req);
4807 hci_req_add_le_passive_scan(&req);
4808
4809 hci_req_run(&req, NULL);
4810 }
4811
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004812 hci_dev_unlock(hdev);
4813
4814 return err;
4815}
4816
Marcel Holtmann1904a852015-01-11 13:50:44 -08004817static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4818 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004819{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004820 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004821
4822 BT_DBG("status 0x%02x", status);
4823
4824 hci_dev_lock(hdev);
4825
Johan Hedberg333ae952015-03-17 13:48:47 +02004826 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004827 if (!cmd)
4828 goto unlock;
4829
4830 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004831 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4832 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004833 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004834 struct mgmt_mode *cp = cmd->param;
4835
4836 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004837 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004838 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004839 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004840
Johan Hedberg33e38b32013-03-15 17:07:05 -05004841 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4842 new_settings(hdev, cmd->sk);
4843 }
4844
4845 mgmt_pending_remove(cmd);
4846
4847unlock:
4848 hci_dev_unlock(hdev);
4849}
4850
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004851static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004852 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004853{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004854 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004855 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004856 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004857 int err;
4858
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004859 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004860
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004861 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004862 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004863 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4864 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004865
Johan Hedberga7e80f22013-01-09 16:05:19 +02004866 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004867 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4868 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004869
Antti Julkuf6422ec2011-06-22 13:11:56 +03004870 hci_dev_lock(hdev);
4871
Johan Hedberg333ae952015-03-17 13:48:47 +02004872 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004873 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4874 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004875 goto unlock;
4876 }
4877
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004878 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004879 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4880 hdev);
4881 goto unlock;
4882 }
4883
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004884 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004885 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004886 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4887 hdev);
4888 new_settings(hdev, sk);
4889 goto unlock;
4890 }
4891
Johan Hedberg33e38b32013-03-15 17:07:05 -05004892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4893 data, len);
4894 if (!cmd) {
4895 err = -ENOMEM;
4896 goto unlock;
4897 }
4898
4899 hci_req_init(&req, hdev);
4900
Johan Hedberg406d7802013-03-15 17:07:09 -05004901 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004902
4903 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004904 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004905 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4906 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004907 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004908 }
4909
Johan Hedberg33e38b32013-03-15 17:07:05 -05004910unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004911 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004912
Antti Julkuf6422ec2011-06-22 13:11:56 +03004913 return err;
4914}
4915
Marcel Holtmann1904a852015-01-11 13:50:44 -08004916static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004917{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004918 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004919
4920 BT_DBG("status 0x%02x", status);
4921
4922 hci_dev_lock(hdev);
4923
Johan Hedberg333ae952015-03-17 13:48:47 +02004924 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004925 if (!cmd)
4926 goto unlock;
4927
4928 if (status) {
4929 u8 mgmt_err = mgmt_status(status);
4930
4931 /* We need to restore the flag if related HCI commands
4932 * failed.
4933 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004934 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004935
Johan Hedberga69e8372015-03-06 21:08:53 +02004936 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004937 } else {
4938 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4939 new_settings(hdev, cmd->sk);
4940 }
4941
4942 mgmt_pending_remove(cmd);
4943
4944unlock:
4945 hci_dev_unlock(hdev);
4946}
4947
4948static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4949{
4950 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004951 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004952 struct hci_request req;
4953 int err;
4954
4955 BT_DBG("request for %s", hdev->name);
4956
4957 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004958 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4959 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004960
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004961 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004962 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4963 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004964
4965 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004966 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4967 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004968
4969 hci_dev_lock(hdev);
4970
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004971 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004972 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4973 goto unlock;
4974 }
4975
4976 if (!hdev_is_powered(hdev)) {
4977 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004978 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4979 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4980 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4981 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4982 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004983 }
4984
Marcel Holtmannce05d602015-03-13 02:11:03 -07004985 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004986
4987 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4988 if (err < 0)
4989 goto unlock;
4990
4991 err = new_settings(hdev, sk);
4992 goto unlock;
4993 }
4994
4995 /* Reject disabling when powered on */
4996 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004997 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4998 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004999 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005000 } else {
5001 /* When configuring a dual-mode controller to operate
5002 * with LE only and using a static address, then switching
5003 * BR/EDR back on is not allowed.
5004 *
5005 * Dual-mode controllers shall operate with the public
5006 * address as its identity address for BR/EDR and LE. So
5007 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005008 *
5009 * The same restrictions applies when secure connections
5010 * has been enabled. For BR/EDR this is a controller feature
5011 * while for LE it is a host stack feature. This means that
5012 * switching BR/EDR back on when secure connections has been
5013 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005014 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005015 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005016 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005017 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005018 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5019 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005020 goto unlock;
5021 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005022 }
5023
Johan Hedberg333ae952015-03-17 13:48:47 +02005024 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005025 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5026 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005027 goto unlock;
5028 }
5029
5030 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5031 if (!cmd) {
5032 err = -ENOMEM;
5033 goto unlock;
5034 }
5035
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005036 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005037 * generates the correct flags.
5038 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005039 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005040
5041 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005042
Johan Hedberg432df052014-08-01 11:13:31 +03005043 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005044 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005045
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005046 /* Since only the advertising data flags will change, there
5047 * is no need to update the scan response data.
5048 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005049 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005050
Johan Hedberg0663ca22013-10-02 13:43:14 +03005051 err = hci_req_run(&req, set_bredr_complete);
5052 if (err < 0)
5053 mgmt_pending_remove(cmd);
5054
5055unlock:
5056 hci_dev_unlock(hdev);
5057 return err;
5058}
5059
Johan Hedberga1443f52015-01-23 15:42:46 +02005060static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5061{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005062 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005063 struct mgmt_mode *cp;
5064
5065 BT_DBG("%s status %u", hdev->name, status);
5066
5067 hci_dev_lock(hdev);
5068
Johan Hedberg333ae952015-03-17 13:48:47 +02005069 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005070 if (!cmd)
5071 goto unlock;
5072
5073 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005074 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5075 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005076 goto remove;
5077 }
5078
5079 cp = cmd->param;
5080
5081 switch (cp->val) {
5082 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005083 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5084 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005085 break;
5086 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005087 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005088 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005089 break;
5090 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005091 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5092 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005093 break;
5094 }
5095
5096 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5097 new_settings(hdev, cmd->sk);
5098
5099remove:
5100 mgmt_pending_remove(cmd);
5101unlock:
5102 hci_dev_unlock(hdev);
5103}
5104
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005105static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5106 void *data, u16 len)
5107{
5108 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005109 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005110 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005111 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005112 int err;
5113
5114 BT_DBG("request for %s", hdev->name);
5115
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005116 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005117 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005118 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5119 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005120
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005121 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005122 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005123 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005124 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5125 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005126
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005127 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005128 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005129 MGMT_STATUS_INVALID_PARAMS);
5130
5131 hci_dev_lock(hdev);
5132
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005133 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005134 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005135 bool changed;
5136
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005137 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005138 changed = !hci_dev_test_and_set_flag(hdev,
5139 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005140 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005141 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005142 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005143 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005144 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005145 changed = hci_dev_test_and_clear_flag(hdev,
5146 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005147 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005148 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005149
5150 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5151 if (err < 0)
5152 goto failed;
5153
5154 if (changed)
5155 err = new_settings(hdev, sk);
5156
5157 goto failed;
5158 }
5159
Johan Hedberg333ae952015-03-17 13:48:47 +02005160 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005161 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5162 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005163 goto failed;
5164 }
5165
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005166 val = !!cp->val;
5167
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005168 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5169 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005170 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5171 goto failed;
5172 }
5173
5174 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5175 if (!cmd) {
5176 err = -ENOMEM;
5177 goto failed;
5178 }
5179
Johan Hedberga1443f52015-01-23 15:42:46 +02005180 hci_req_init(&req, hdev);
5181 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5182 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005183 if (err < 0) {
5184 mgmt_pending_remove(cmd);
5185 goto failed;
5186 }
5187
5188failed:
5189 hci_dev_unlock(hdev);
5190 return err;
5191}
5192
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005193static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5194 void *data, u16 len)
5195{
5196 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005197 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005198 int err;
5199
5200 BT_DBG("request for %s", hdev->name);
5201
Johan Hedbergb97109792014-06-24 14:00:28 +03005202 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005203 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5204 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005205
5206 hci_dev_lock(hdev);
5207
5208 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005209 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005210 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005211 changed = hci_dev_test_and_clear_flag(hdev,
5212 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005213
Johan Hedbergb97109792014-06-24 14:00:28 +03005214 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005215 use_changed = !hci_dev_test_and_set_flag(hdev,
5216 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005217 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005218 use_changed = hci_dev_test_and_clear_flag(hdev,
5219 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005220
5221 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005222 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005223 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5224 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5225 sizeof(mode), &mode);
5226 }
5227
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005228 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5229 if (err < 0)
5230 goto unlock;
5231
5232 if (changed)
5233 err = new_settings(hdev, sk);
5234
5235unlock:
5236 hci_dev_unlock(hdev);
5237 return err;
5238}
5239
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005240static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5241 u16 len)
5242{
5243 struct mgmt_cp_set_privacy *cp = cp_data;
5244 bool changed;
5245 int err;
5246
5247 BT_DBG("request for %s", hdev->name);
5248
5249 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005250 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5251 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005252
5253 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005254 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5255 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005256
5257 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005258 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5259 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005260
5261 hci_dev_lock(hdev);
5262
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005263 /* If user space supports this command it is also expected to
5264 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5265 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005266 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005267
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005268 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005269 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005270 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005271 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005272 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005273 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005274 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005275 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005276 }
5277
5278 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5279 if (err < 0)
5280 goto unlock;
5281
5282 if (changed)
5283 err = new_settings(hdev, sk);
5284
5285unlock:
5286 hci_dev_unlock(hdev);
5287 return err;
5288}
5289
Johan Hedberg41edf162014-02-18 10:19:35 +02005290static bool irk_is_valid(struct mgmt_irk_info *irk)
5291{
5292 switch (irk->addr.type) {
5293 case BDADDR_LE_PUBLIC:
5294 return true;
5295
5296 case BDADDR_LE_RANDOM:
5297 /* Two most significant bits shall be set */
5298 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5299 return false;
5300 return true;
5301 }
5302
5303 return false;
5304}
5305
5306static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5307 u16 len)
5308{
5309 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005310 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5311 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005312 u16 irk_count, expected_len;
5313 int i, err;
5314
5315 BT_DBG("request for %s", hdev->name);
5316
5317 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005318 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5319 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005320
5321 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005322 if (irk_count > max_irk_count) {
5323 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005324 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5325 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005326 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005327
5328 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5329 if (expected_len != len) {
5330 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005331 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005332 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5333 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005334 }
5335
5336 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5337
5338 for (i = 0; i < irk_count; i++) {
5339 struct mgmt_irk_info *key = &cp->irks[i];
5340
5341 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005342 return mgmt_cmd_status(sk, hdev->id,
5343 MGMT_OP_LOAD_IRKS,
5344 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005345 }
5346
5347 hci_dev_lock(hdev);
5348
5349 hci_smp_irks_clear(hdev);
5350
5351 for (i = 0; i < irk_count; i++) {
5352 struct mgmt_irk_info *irk = &cp->irks[i];
Johan Hedberg41edf162014-02-18 10:19:35 +02005353
Johan Hedberg85813a72015-10-21 18:02:59 +03005354 hci_add_irk(hdev, &irk->addr.bdaddr,
5355 le_addr_type(irk->addr.type), irk->val,
Johan Hedberg41edf162014-02-18 10:19:35 +02005356 BDADDR_ANY);
5357 }
5358
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005359 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005360
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005361 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005362
5363 hci_dev_unlock(hdev);
5364
5365 return err;
5366}
5367
Johan Hedberg3f706b72013-01-20 14:27:16 +02005368static bool ltk_is_valid(struct mgmt_ltk_info *key)
5369{
5370 if (key->master != 0x00 && key->master != 0x01)
5371 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005372
5373 switch (key->addr.type) {
5374 case BDADDR_LE_PUBLIC:
5375 return true;
5376
5377 case BDADDR_LE_RANDOM:
5378 /* Two most significant bits shall be set */
5379 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5380 return false;
5381 return true;
5382 }
5383
5384 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005385}
5386
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005387static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005388 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005389{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005390 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005391 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5392 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005393 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005394 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005395
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005396 BT_DBG("request for %s", hdev->name);
5397
5398 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005399 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5400 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005401
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005402 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005403 if (key_count > max_key_count) {
5404 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005405 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5406 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005407 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005408
5409 expected_len = sizeof(*cp) + key_count *
5410 sizeof(struct mgmt_ltk_info);
5411 if (expected_len != len) {
5412 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005413 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005414 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5415 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005416 }
5417
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005418 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005419
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005420 for (i = 0; i < key_count; i++) {
5421 struct mgmt_ltk_info *key = &cp->keys[i];
5422
Johan Hedberg3f706b72013-01-20 14:27:16 +02005423 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005424 return mgmt_cmd_status(sk, hdev->id,
5425 MGMT_OP_LOAD_LONG_TERM_KEYS,
5426 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005427 }
5428
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005429 hci_dev_lock(hdev);
5430
5431 hci_smp_ltks_clear(hdev);
5432
5433 for (i = 0; i < key_count; i++) {
5434 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedberg85813a72015-10-21 18:02:59 +03005435 u8 type, authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005436
Johan Hedberg61b43352014-05-29 19:36:53 +03005437 switch (key->type) {
5438 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005439 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005440 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005441 break;
5442 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005443 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005444 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005445 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005446 case MGMT_LTK_P256_UNAUTH:
5447 authenticated = 0x00;
5448 type = SMP_LTK_P256;
5449 break;
5450 case MGMT_LTK_P256_AUTH:
5451 authenticated = 0x01;
5452 type = SMP_LTK_P256;
5453 break;
5454 case MGMT_LTK_P256_DEBUG:
5455 authenticated = 0x00;
5456 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005457 default:
5458 continue;
5459 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005460
Johan Hedberg85813a72015-10-21 18:02:59 +03005461 hci_add_ltk(hdev, &key->addr.bdaddr,
5462 le_addr_type(key->addr.type), type, authenticated,
5463 key->val, key->enc_size, key->ediv, key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005464 }
5465
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005466 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005467 NULL, 0);
5468
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005469 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005470
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005471 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005472}
5473
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005474static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005475{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005476 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005477 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005478 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005479
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005480 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005481
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005482 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005483 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005484 rp.tx_power = conn->tx_power;
5485 rp.max_tx_power = conn->max_tx_power;
5486 } else {
5487 rp.rssi = HCI_RSSI_INVALID;
5488 rp.tx_power = HCI_TX_POWER_INVALID;
5489 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005490 }
5491
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005492 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5493 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005494
5495 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005496 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005497
5498 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005499}
5500
Marcel Holtmann1904a852015-01-11 13:50:44 -08005501static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5502 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005503{
5504 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005505 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005506 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005507 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005508 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005509
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005510 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005511
5512 hci_dev_lock(hdev);
5513
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005514 /* Commands sent in request are either Read RSSI or Read Transmit Power
5515 * Level so we check which one was last sent to retrieve connection
5516 * handle. Both commands have handle as first parameter so it's safe to
5517 * cast data on the same command struct.
5518 *
5519 * First command sent is always Read RSSI and we fail only if it fails.
5520 * In other case we simply override error to indicate success as we
5521 * already remembered if TX power value is actually valid.
5522 */
5523 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5524 if (!cp) {
5525 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005526 status = MGMT_STATUS_SUCCESS;
5527 } else {
5528 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005529 }
5530
5531 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005532 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005533 goto unlock;
5534 }
5535
5536 handle = __le16_to_cpu(cp->handle);
5537 conn = hci_conn_hash_lookup_handle(hdev, handle);
5538 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005539 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005540 goto unlock;
5541 }
5542
Johan Hedberg333ae952015-03-17 13:48:47 +02005543 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005544 if (!cmd)
5545 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005546
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005547 cmd->cmd_complete(cmd, status);
5548 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005549
5550unlock:
5551 hci_dev_unlock(hdev);
5552}
5553
5554static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5555 u16 len)
5556{
5557 struct mgmt_cp_get_conn_info *cp = data;
5558 struct mgmt_rp_get_conn_info rp;
5559 struct hci_conn *conn;
5560 unsigned long conn_info_age;
5561 int err = 0;
5562
5563 BT_DBG("%s", hdev->name);
5564
5565 memset(&rp, 0, sizeof(rp));
5566 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5567 rp.addr.type = cp->addr.type;
5568
5569 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005570 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5571 MGMT_STATUS_INVALID_PARAMS,
5572 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005573
5574 hci_dev_lock(hdev);
5575
5576 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005577 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5578 MGMT_STATUS_NOT_POWERED, &rp,
5579 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005580 goto unlock;
5581 }
5582
5583 if (cp->addr.type == BDADDR_BREDR)
5584 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5585 &cp->addr.bdaddr);
5586 else
5587 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5588
5589 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005590 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5591 MGMT_STATUS_NOT_CONNECTED, &rp,
5592 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005593 goto unlock;
5594 }
5595
Johan Hedberg333ae952015-03-17 13:48:47 +02005596 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005597 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5598 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005599 goto unlock;
5600 }
5601
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005602 /* To avoid client trying to guess when to poll again for information we
5603 * calculate conn info age as random value between min/max set in hdev.
5604 */
5605 conn_info_age = hdev->conn_info_min_age +
5606 prandom_u32_max(hdev->conn_info_max_age -
5607 hdev->conn_info_min_age);
5608
5609 /* Query controller to refresh cached values if they are too old or were
5610 * never read.
5611 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005612 if (time_after(jiffies, conn->conn_info_timestamp +
5613 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005614 !conn->conn_info_timestamp) {
5615 struct hci_request req;
5616 struct hci_cp_read_tx_power req_txp_cp;
5617 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005618 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005619
5620 hci_req_init(&req, hdev);
5621 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5622 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5623 &req_rssi_cp);
5624
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005625 /* For LE links TX power does not change thus we don't need to
5626 * query for it once value is known.
5627 */
5628 if (!bdaddr_type_is_le(cp->addr.type) ||
5629 conn->tx_power == HCI_TX_POWER_INVALID) {
5630 req_txp_cp.handle = cpu_to_le16(conn->handle);
5631 req_txp_cp.type = 0x00;
5632 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5633 sizeof(req_txp_cp), &req_txp_cp);
5634 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005635
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005636 /* Max TX power needs to be read only once per connection */
5637 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5638 req_txp_cp.handle = cpu_to_le16(conn->handle);
5639 req_txp_cp.type = 0x01;
5640 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5641 sizeof(req_txp_cp), &req_txp_cp);
5642 }
5643
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005644 err = hci_req_run(&req, conn_info_refresh_complete);
5645 if (err < 0)
5646 goto unlock;
5647
5648 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5649 data, len);
5650 if (!cmd) {
5651 err = -ENOMEM;
5652 goto unlock;
5653 }
5654
5655 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005656 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005657 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005658
5659 conn->conn_info_timestamp = jiffies;
5660 } else {
5661 /* Cache is valid, just reply with values cached in hci_conn */
5662 rp.rssi = conn->rssi;
5663 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005664 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005665
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005666 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5667 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005668 }
5669
5670unlock:
5671 hci_dev_unlock(hdev);
5672 return err;
5673}
5674
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005675static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005676{
5677 struct hci_conn *conn = cmd->user_data;
5678 struct mgmt_rp_get_clock_info rp;
5679 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005680 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005681
5682 memset(&rp, 0, sizeof(rp));
5683 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5684
5685 if (status)
5686 goto complete;
5687
5688 hdev = hci_dev_get(cmd->index);
5689 if (hdev) {
5690 rp.local_clock = cpu_to_le32(hdev->clock);
5691 hci_dev_put(hdev);
5692 }
5693
5694 if (conn) {
5695 rp.piconet_clock = cpu_to_le32(conn->clock);
5696 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5697 }
5698
5699complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005700 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5701 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005702
5703 if (conn) {
5704 hci_conn_drop(conn);
5705 hci_conn_put(conn);
5706 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005707
5708 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005709}
5710
Marcel Holtmann1904a852015-01-11 13:50:44 -08005711static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005712{
Johan Hedberg95868422014-06-28 17:54:07 +03005713 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005714 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005715 struct hci_conn *conn;
5716
5717 BT_DBG("%s status %u", hdev->name, status);
5718
5719 hci_dev_lock(hdev);
5720
5721 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5722 if (!hci_cp)
5723 goto unlock;
5724
5725 if (hci_cp->which) {
5726 u16 handle = __le16_to_cpu(hci_cp->handle);
5727 conn = hci_conn_hash_lookup_handle(hdev, handle);
5728 } else {
5729 conn = NULL;
5730 }
5731
Johan Hedberg333ae952015-03-17 13:48:47 +02005732 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005733 if (!cmd)
5734 goto unlock;
5735
Johan Hedberg69487372014-12-05 13:36:07 +02005736 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005737 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005738
5739unlock:
5740 hci_dev_unlock(hdev);
5741}
5742
5743static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5744 u16 len)
5745{
5746 struct mgmt_cp_get_clock_info *cp = data;
5747 struct mgmt_rp_get_clock_info rp;
5748 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005749 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005750 struct hci_request req;
5751 struct hci_conn *conn;
5752 int err;
5753
5754 BT_DBG("%s", hdev->name);
5755
5756 memset(&rp, 0, sizeof(rp));
5757 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5758 rp.addr.type = cp->addr.type;
5759
5760 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005761 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5762 MGMT_STATUS_INVALID_PARAMS,
5763 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005764
5765 hci_dev_lock(hdev);
5766
5767 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005768 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5769 MGMT_STATUS_NOT_POWERED, &rp,
5770 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005771 goto unlock;
5772 }
5773
5774 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5775 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5776 &cp->addr.bdaddr);
5777 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005778 err = mgmt_cmd_complete(sk, hdev->id,
5779 MGMT_OP_GET_CLOCK_INFO,
5780 MGMT_STATUS_NOT_CONNECTED,
5781 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005782 goto unlock;
5783 }
5784 } else {
5785 conn = NULL;
5786 }
5787
5788 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5789 if (!cmd) {
5790 err = -ENOMEM;
5791 goto unlock;
5792 }
5793
Johan Hedberg69487372014-12-05 13:36:07 +02005794 cmd->cmd_complete = clock_info_cmd_complete;
5795
Johan Hedberg95868422014-06-28 17:54:07 +03005796 hci_req_init(&req, hdev);
5797
5798 memset(&hci_cp, 0, sizeof(hci_cp));
5799 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5800
5801 if (conn) {
5802 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005803 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005804
5805 hci_cp.handle = cpu_to_le16(conn->handle);
5806 hci_cp.which = 0x01; /* Piconet clock */
5807 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5808 }
5809
5810 err = hci_req_run(&req, get_clock_info_complete);
5811 if (err < 0)
5812 mgmt_pending_remove(cmd);
5813
5814unlock:
5815 hci_dev_unlock(hdev);
5816 return err;
5817}
5818
Johan Hedberg5a154e62014-12-19 22:26:02 +02005819static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5820{
5821 struct hci_conn *conn;
5822
5823 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5824 if (!conn)
5825 return false;
5826
5827 if (conn->dst_type != type)
5828 return false;
5829
5830 if (conn->state != BT_CONNECTED)
5831 return false;
5832
5833 return true;
5834}
5835
5836/* This function requires the caller holds hdev->lock */
Johan Hedberg51d7a942015-11-11 08:11:18 +02005837static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
Johan Hedberg5a154e62014-12-19 22:26:02 +02005838 u8 addr_type, u8 auto_connect)
5839{
Johan Hedberg5a154e62014-12-19 22:26:02 +02005840 struct hci_conn_params *params;
5841
5842 params = hci_conn_params_add(hdev, addr, addr_type);
5843 if (!params)
5844 return -EIO;
5845
5846 if (params->auto_connect == auto_connect)
5847 return 0;
5848
5849 list_del_init(&params->action);
5850
5851 switch (auto_connect) {
5852 case HCI_AUTO_CONN_DISABLED:
5853 case HCI_AUTO_CONN_LINK_LOSS:
Jakub Pawlowski28a667c2015-08-07 20:22:54 +02005854 /* If auto connect is being disabled when we're trying to
5855 * connect to device, keep connecting.
5856 */
5857 if (params->explicit_connect)
5858 list_add(&params->action, &hdev->pend_le_conns);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005859 break;
5860 case HCI_AUTO_CONN_REPORT:
Johan Hedberg49c50922015-10-16 10:07:51 +03005861 if (params->explicit_connect)
5862 list_add(&params->action, &hdev->pend_le_conns);
5863 else
5864 list_add(&params->action, &hdev->pend_le_reports);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005865 break;
5866 case HCI_AUTO_CONN_DIRECT:
5867 case HCI_AUTO_CONN_ALWAYS:
Johan Hedberg51d7a942015-11-11 08:11:18 +02005868 if (!is_connected(hdev, addr, addr_type))
Johan Hedberg5a154e62014-12-19 22:26:02 +02005869 list_add(&params->action, &hdev->pend_le_conns);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005870 break;
5871 }
5872
5873 params->auto_connect = auto_connect;
5874
5875 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5876 auto_connect);
5877
5878 return 0;
5879}
5880
Marcel Holtmann8afef092014-06-29 22:28:34 +02005881static void device_added(struct sock *sk, struct hci_dev *hdev,
5882 bdaddr_t *bdaddr, u8 type, u8 action)
5883{
5884 struct mgmt_ev_device_added ev;
5885
5886 bacpy(&ev.addr.bdaddr, bdaddr);
5887 ev.addr.type = type;
5888 ev.action = action;
5889
5890 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5891}
5892
Marcel Holtmann2faade52014-06-29 19:44:03 +02005893static int add_device(struct sock *sk, struct hci_dev *hdev,
5894 void *data, u16 len)
5895{
5896 struct mgmt_cp_add_device *cp = data;
5897 u8 auto_conn, addr_type;
5898 int err;
5899
5900 BT_DBG("%s", hdev->name);
5901
Johan Hedberg66593582014-07-09 12:59:14 +03005902 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005903 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005904 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5905 MGMT_STATUS_INVALID_PARAMS,
5906 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005907
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005908 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005909 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5910 MGMT_STATUS_INVALID_PARAMS,
5911 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005912
5913 hci_dev_lock(hdev);
5914
Johan Hedberg66593582014-07-09 12:59:14 +03005915 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005916 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005917 if (cp->action != 0x01) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02005918 err = mgmt_cmd_complete(sk, hdev->id,
5919 MGMT_OP_ADD_DEVICE,
5920 MGMT_STATUS_INVALID_PARAMS,
5921 &cp->addr, sizeof(cp->addr));
Johan Hedberg66593582014-07-09 12:59:14 +03005922 goto unlock;
5923 }
5924
5925 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5926 cp->addr.type);
5927 if (err)
5928 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005929
Johan Hedberg2f274982015-11-11 10:36:15 +02005930 hci_update_page_scan(hdev);
Johan Hedberga3974072014-07-09 12:59:15 +03005931
Johan Hedberg66593582014-07-09 12:59:14 +03005932 goto added;
5933 }
5934
Johan Hedberg85813a72015-10-21 18:02:59 +03005935 addr_type = le_addr_type(cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005936
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005937 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005938 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005939 else if (cp->action == 0x01)
5940 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005941 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005942 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005943
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02005944 /* Kernel internally uses conn_params with resolvable private
5945 * address, but Add Device allows only identity addresses.
5946 * Make sure it is enforced before calling
5947 * hci_conn_params_lookup.
5948 */
5949 if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02005950 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5951 MGMT_STATUS_INVALID_PARAMS,
5952 &cp->addr, sizeof(cp->addr));
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02005953 goto unlock;
5954 }
5955
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005956 /* If the connection parameters don't exist for this device,
5957 * they will be created and configured with defaults.
5958 */
Johan Hedberg51d7a942015-11-11 08:11:18 +02005959 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005960 auto_conn) < 0) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02005961 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5962 MGMT_STATUS_FAILED, &cp->addr,
5963 sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005964 goto unlock;
5965 }
5966
Johan Hedberg51d7a942015-11-11 08:11:18 +02005967 hci_update_background_scan(hdev);
5968
Johan Hedberg66593582014-07-09 12:59:14 +03005969added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005970 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5971
Johan Hedberg51d7a942015-11-11 08:11:18 +02005972 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5973 MGMT_STATUS_SUCCESS, &cp->addr,
5974 sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005975
5976unlock:
5977 hci_dev_unlock(hdev);
5978 return err;
5979}
5980
Marcel Holtmann8afef092014-06-29 22:28:34 +02005981static void device_removed(struct sock *sk, struct hci_dev *hdev,
5982 bdaddr_t *bdaddr, u8 type)
5983{
5984 struct mgmt_ev_device_removed ev;
5985
5986 bacpy(&ev.addr.bdaddr, bdaddr);
5987 ev.addr.type = type;
5988
5989 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5990}
5991
Marcel Holtmann2faade52014-06-29 19:44:03 +02005992static int remove_device(struct sock *sk, struct hci_dev *hdev,
5993 void *data, u16 len)
5994{
5995 struct mgmt_cp_remove_device *cp = data;
5996 int err;
5997
5998 BT_DBG("%s", hdev->name);
5999
6000 hci_dev_lock(hdev);
6001
6002 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006003 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006004 u8 addr_type;
6005
Johan Hedberg66593582014-07-09 12:59:14 +03006006 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006007 err = mgmt_cmd_complete(sk, hdev->id,
6008 MGMT_OP_REMOVE_DEVICE,
6009 MGMT_STATUS_INVALID_PARAMS,
6010 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006011 goto unlock;
6012 }
6013
Johan Hedberg66593582014-07-09 12:59:14 +03006014 if (cp->addr.type == BDADDR_BREDR) {
6015 err = hci_bdaddr_list_del(&hdev->whitelist,
6016 &cp->addr.bdaddr,
6017 cp->addr.type);
6018 if (err) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006019 err = mgmt_cmd_complete(sk, hdev->id,
6020 MGMT_OP_REMOVE_DEVICE,
6021 MGMT_STATUS_INVALID_PARAMS,
6022 &cp->addr,
6023 sizeof(cp->addr));
Johan Hedberg66593582014-07-09 12:59:14 +03006024 goto unlock;
6025 }
6026
Johan Hedberg51d7a942015-11-11 08:11:18 +02006027 hci_update_page_scan(hdev);
Johan Hedberga3974072014-07-09 12:59:15 +03006028
Johan Hedberg66593582014-07-09 12:59:14 +03006029 device_removed(sk, hdev, &cp->addr.bdaddr,
6030 cp->addr.type);
6031 goto complete;
6032 }
6033
Johan Hedberg85813a72015-10-21 18:02:59 +03006034 addr_type = le_addr_type(cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006035
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02006036 /* Kernel internally uses conn_params with resolvable private
6037 * address, but Remove Device allows only identity addresses.
6038 * Make sure it is enforced before calling
6039 * hci_conn_params_lookup.
6040 */
6041 if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006042 err = mgmt_cmd_complete(sk, hdev->id,
6043 MGMT_OP_REMOVE_DEVICE,
6044 MGMT_STATUS_INVALID_PARAMS,
6045 &cp->addr, sizeof(cp->addr));
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02006046 goto unlock;
6047 }
6048
Johan Hedbergc71593d2014-07-02 17:37:28 +03006049 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6050 addr_type);
6051 if (!params) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006052 err = mgmt_cmd_complete(sk, hdev->id,
6053 MGMT_OP_REMOVE_DEVICE,
6054 MGMT_STATUS_INVALID_PARAMS,
6055 &cp->addr, sizeof(cp->addr));
Johan Hedbergc71593d2014-07-02 17:37:28 +03006056 goto unlock;
6057 }
6058
Johan Hedberg679d2b62015-10-16 10:07:52 +03006059 if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
6060 params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006061 err = mgmt_cmd_complete(sk, hdev->id,
6062 MGMT_OP_REMOVE_DEVICE,
6063 MGMT_STATUS_INVALID_PARAMS,
6064 &cp->addr, sizeof(cp->addr));
Johan Hedbergc71593d2014-07-02 17:37:28 +03006065 goto unlock;
6066 }
6067
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006068 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006069 list_del(&params->list);
6070 kfree(params);
Johan Hedberg51d7a942015-11-11 08:11:18 +02006071 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006072
6073 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006074 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006075 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006076 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006077
Marcel Holtmann2faade52014-06-29 19:44:03 +02006078 if (cp->addr.type) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006079 err = mgmt_cmd_complete(sk, hdev->id,
6080 MGMT_OP_REMOVE_DEVICE,
6081 MGMT_STATUS_INVALID_PARAMS,
6082 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006083 goto unlock;
6084 }
6085
Johan Hedberg66593582014-07-09 12:59:14 +03006086 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6087 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6088 list_del(&b->list);
6089 kfree(b);
6090 }
6091
Johan Hedberg51d7a942015-11-11 08:11:18 +02006092 hci_update_page_scan(hdev);
Johan Hedberga3974072014-07-09 12:59:15 +03006093
Johan Hedberg19de0822014-07-06 13:06:51 +03006094 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6095 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6096 continue;
6097 device_removed(sk, hdev, &p->addr, p->addr_type);
Johan Hedberg679d2b62015-10-16 10:07:52 +03006098 if (p->explicit_connect) {
6099 p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
6100 continue;
6101 }
Johan Hedberg19de0822014-07-06 13:06:51 +03006102 list_del(&p->action);
6103 list_del(&p->list);
6104 kfree(p);
6105 }
6106
6107 BT_DBG("All LE connection parameters were removed");
6108
Johan Hedberg51d7a942015-11-11 08:11:18 +02006109 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006110 }
6111
Johan Hedberg66593582014-07-09 12:59:14 +03006112complete:
Johan Hedberg51d7a942015-11-11 08:11:18 +02006113 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
6114 MGMT_STATUS_SUCCESS, &cp->addr,
6115 sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006116unlock:
6117 hci_dev_unlock(hdev);
6118 return err;
6119}
6120
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006121static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6122 u16 len)
6123{
6124 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006125 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6126 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006127 u16 param_count, expected_len;
6128 int i;
6129
6130 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006131 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6132 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006133
6134 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006135 if (param_count > max_param_count) {
6136 BT_ERR("load_conn_param: too big param_count value %u",
6137 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006138 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6139 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006140 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006141
6142 expected_len = sizeof(*cp) + param_count *
6143 sizeof(struct mgmt_conn_param);
6144 if (expected_len != len) {
6145 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6146 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006147 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6148 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006149 }
6150
6151 BT_DBG("%s param_count %u", hdev->name, param_count);
6152
6153 hci_dev_lock(hdev);
6154
6155 hci_conn_params_clear_disabled(hdev);
6156
6157 for (i = 0; i < param_count; i++) {
6158 struct mgmt_conn_param *param = &cp->params[i];
6159 struct hci_conn_params *hci_param;
6160 u16 min, max, latency, timeout;
6161 u8 addr_type;
6162
6163 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6164 param->addr.type);
6165
6166 if (param->addr.type == BDADDR_LE_PUBLIC) {
6167 addr_type = ADDR_LE_DEV_PUBLIC;
6168 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6169 addr_type = ADDR_LE_DEV_RANDOM;
6170 } else {
6171 BT_ERR("Ignoring invalid connection parameters");
6172 continue;
6173 }
6174
6175 min = le16_to_cpu(param->min_interval);
6176 max = le16_to_cpu(param->max_interval);
6177 latency = le16_to_cpu(param->latency);
6178 timeout = le16_to_cpu(param->timeout);
6179
6180 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6181 min, max, latency, timeout);
6182
6183 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6184 BT_ERR("Ignoring invalid connection parameters");
6185 continue;
6186 }
6187
6188 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6189 addr_type);
6190 if (!hci_param) {
6191 BT_ERR("Failed to add connection parameters");
6192 continue;
6193 }
6194
6195 hci_param->conn_min_interval = min;
6196 hci_param->conn_max_interval = max;
6197 hci_param->conn_latency = latency;
6198 hci_param->supervision_timeout = timeout;
6199 }
6200
6201 hci_dev_unlock(hdev);
6202
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006203 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6204 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006205}
6206
Marcel Holtmanndbece372014-07-04 18:11:55 +02006207static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6208 void *data, u16 len)
6209{
6210 struct mgmt_cp_set_external_config *cp = data;
6211 bool changed;
6212 int err;
6213
6214 BT_DBG("%s", hdev->name);
6215
6216 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006217 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6218 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006219
6220 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006221 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6222 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006223
6224 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006225 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6226 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006227
6228 hci_dev_lock(hdev);
6229
6230 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006231 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006232 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006233 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006234
6235 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6236 if (err < 0)
6237 goto unlock;
6238
6239 if (!changed)
6240 goto unlock;
6241
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006242 err = new_options(hdev, sk);
6243
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006244 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006245 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006246
Marcel Holtmann516018a2015-03-13 02:11:04 -07006247 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006248 hci_dev_set_flag(hdev, HCI_CONFIG);
6249 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006250
6251 queue_work(hdev->req_workqueue, &hdev->power_on);
6252 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006253 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006254 mgmt_index_added(hdev);
6255 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006256 }
6257
6258unlock:
6259 hci_dev_unlock(hdev);
6260 return err;
6261}
6262
Marcel Holtmann9713c172014-07-06 12:11:15 +02006263static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6264 void *data, u16 len)
6265{
6266 struct mgmt_cp_set_public_address *cp = data;
6267 bool changed;
6268 int err;
6269
6270 BT_DBG("%s", hdev->name);
6271
6272 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006273 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6274 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006275
6276 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006277 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6278 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006279
6280 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006281 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6282 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006283
6284 hci_dev_lock(hdev);
6285
6286 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6287 bacpy(&hdev->public_addr, &cp->bdaddr);
6288
6289 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6290 if (err < 0)
6291 goto unlock;
6292
6293 if (!changed)
6294 goto unlock;
6295
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006296 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006297 err = new_options(hdev, sk);
6298
6299 if (is_configured(hdev)) {
6300 mgmt_index_removed(hdev);
6301
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006302 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006303
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006304 hci_dev_set_flag(hdev, HCI_CONFIG);
6305 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006306
6307 queue_work(hdev->req_workqueue, &hdev->power_on);
6308 }
6309
6310unlock:
6311 hci_dev_unlock(hdev);
6312 return err;
6313}
6314
Marcel Holtmannbea41602015-03-14 22:43:17 -07006315static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6316 u8 data_len)
6317{
6318 eir[eir_len++] = sizeof(type) + data_len;
6319 eir[eir_len++] = type;
6320 memcpy(&eir[eir_len], data, data_len);
6321 eir_len += data_len;
6322
6323 return eir_len;
6324}
6325
Johan Hedberg40f66c02015-04-07 21:52:22 +03006326static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
6327 u16 opcode, struct sk_buff *skb)
6328{
6329 const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
6330 struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
6331 u8 *h192, *r192, *h256, *r256;
6332 struct mgmt_pending_cmd *cmd;
6333 u16 eir_len;
6334 int err;
6335
6336 BT_DBG("%s status %u", hdev->name, status);
6337
6338 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
6339 if (!cmd)
6340 return;
6341
6342 mgmt_cp = cmd->param;
6343
6344 if (status) {
6345 status = mgmt_status(status);
6346 eir_len = 0;
6347
6348 h192 = NULL;
6349 r192 = NULL;
6350 h256 = NULL;
6351 r256 = NULL;
6352 } else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
6353 struct hci_rp_read_local_oob_data *rp;
6354
6355 if (skb->len != sizeof(*rp)) {
6356 status = MGMT_STATUS_FAILED;
6357 eir_len = 0;
6358 } else {
6359 status = MGMT_STATUS_SUCCESS;
6360 rp = (void *)skb->data;
6361
6362 eir_len = 5 + 18 + 18;
6363 h192 = rp->hash;
6364 r192 = rp->rand;
6365 h256 = NULL;
6366 r256 = NULL;
6367 }
6368 } else {
6369 struct hci_rp_read_local_oob_ext_data *rp;
6370
6371 if (skb->len != sizeof(*rp)) {
6372 status = MGMT_STATUS_FAILED;
6373 eir_len = 0;
6374 } else {
6375 status = MGMT_STATUS_SUCCESS;
6376 rp = (void *)skb->data;
6377
6378 if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
6379 eir_len = 5 + 18 + 18;
6380 h192 = NULL;
6381 r192 = NULL;
6382 } else {
6383 eir_len = 5 + 18 + 18 + 18 + 18;
6384 h192 = rp->hash192;
6385 r192 = rp->rand192;
6386 }
6387
6388 h256 = rp->hash256;
6389 r256 = rp->rand256;
6390 }
6391 }
6392
6393 mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
6394 if (!mgmt_rp)
6395 goto done;
6396
6397 if (status)
6398 goto send_rsp;
6399
6400 eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
6401 hdev->dev_class, 3);
6402
6403 if (h192 && r192) {
6404 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6405 EIR_SSP_HASH_C192, h192, 16);
6406 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6407 EIR_SSP_RAND_R192, r192, 16);
6408 }
6409
6410 if (h256 && r256) {
6411 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6412 EIR_SSP_HASH_C256, h256, 16);
6413 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6414 EIR_SSP_RAND_R256, r256, 16);
6415 }
6416
6417send_rsp:
6418 mgmt_rp->type = mgmt_cp->type;
6419 mgmt_rp->eir_len = cpu_to_le16(eir_len);
6420
6421 err = mgmt_cmd_complete(cmd->sk, hdev->id,
6422 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
6423 mgmt_rp, sizeof(*mgmt_rp) + eir_len);
6424 if (err < 0 || status)
6425 goto done;
6426
6427 hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
6428
6429 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6430 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
6431 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
6432done:
6433 kfree(mgmt_rp);
6434 mgmt_pending_remove(cmd);
6435}
6436
6437static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
6438 struct mgmt_cp_read_local_oob_ext_data *cp)
6439{
6440 struct mgmt_pending_cmd *cmd;
6441 struct hci_request req;
6442 int err;
6443
6444 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
6445 cp, sizeof(*cp));
6446 if (!cmd)
6447 return -ENOMEM;
6448
6449 hci_req_init(&req, hdev);
6450
6451 if (bredr_sc_enabled(hdev))
6452 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
6453 else
6454 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
6455
6456 err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
6457 if (err < 0) {
6458 mgmt_pending_remove(cmd);
6459 return err;
6460 }
6461
6462 return 0;
6463}
6464
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006465static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6466 void *data, u16 data_len)
6467{
6468 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6469 struct mgmt_rp_read_local_oob_ext_data *rp;
6470 size_t rp_len;
6471 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006472 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006473 int err;
6474
6475 BT_DBG("%s", hdev->name);
6476
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006477 if (hdev_is_powered(hdev)) {
6478 switch (cp->type) {
6479 case BIT(BDADDR_BREDR):
6480 status = mgmt_bredr_support(hdev);
6481 if (status)
6482 eir_len = 0;
6483 else
6484 eir_len = 5;
6485 break;
6486 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6487 status = mgmt_le_support(hdev);
6488 if (status)
6489 eir_len = 0;
6490 else
6491 eir_len = 9 + 3 + 18 + 18 + 3;
6492 break;
6493 default:
6494 status = MGMT_STATUS_INVALID_PARAMS;
6495 eir_len = 0;
6496 break;
6497 }
6498 } else {
6499 status = MGMT_STATUS_NOT_POWERED;
6500 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006501 }
6502
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006503 rp_len = sizeof(*rp) + eir_len;
6504 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006505 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006506 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006507
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006508 if (status)
6509 goto complete;
6510
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006511 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006512
6513 eir_len = 0;
6514 switch (cp->type) {
6515 case BIT(BDADDR_BREDR):
Johan Hedberg40f66c02015-04-07 21:52:22 +03006516 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
6517 err = read_local_ssp_oob_req(hdev, sk, cp);
6518 hci_dev_unlock(hdev);
6519 if (!err)
6520 goto done;
6521
6522 status = MGMT_STATUS_FAILED;
6523 goto complete;
6524 } else {
6525 eir_len = eir_append_data(rp->eir, eir_len,
6526 EIR_CLASS_OF_DEV,
6527 hdev->dev_class, 3);
6528 }
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006529 break;
6530 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006531 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6532 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006533 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006534 status = MGMT_STATUS_FAILED;
6535 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006536 }
6537
Marcel Holtmanne2135682015-04-02 12:00:58 -07006538 /* This should return the active RPA, but since the RPA
6539 * is only programmed on demand, it is really hard to fill
6540 * this in at the moment. For now disallow retrieving
6541 * local out-of-band data when privacy is in use.
6542 *
6543 * Returning the identity address will not help here since
6544 * pairing happens before the identity resolving key is
6545 * known and thus the connection establishment happens
6546 * based on the RPA and not the identity address.
6547 */
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006548 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
Marcel Holtmanne2135682015-04-02 12:00:58 -07006549 hci_dev_unlock(hdev);
6550 status = MGMT_STATUS_REJECTED;
6551 goto complete;
6552 }
6553
6554 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6555 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6556 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6557 bacmp(&hdev->static_addr, BDADDR_ANY))) {
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006558 memcpy(addr, &hdev->static_addr, 6);
6559 addr[6] = 0x01;
6560 } else {
6561 memcpy(addr, &hdev->bdaddr, 6);
6562 addr[6] = 0x00;
6563 }
6564
6565 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6566 addr, sizeof(addr));
6567
6568 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6569 role = 0x02;
6570 else
6571 role = 0x01;
6572
6573 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6574 &role, sizeof(role));
6575
Marcel Holtmann5082a592015-03-16 12:39:00 -07006576 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6577 eir_len = eir_append_data(rp->eir, eir_len,
6578 EIR_LE_SC_CONFIRM,
6579 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006580
Marcel Holtmann5082a592015-03-16 12:39:00 -07006581 eir_len = eir_append_data(rp->eir, eir_len,
6582 EIR_LE_SC_RANDOM,
6583 rand, sizeof(rand));
6584 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006585
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006586 flags = get_adv_discov_flags(hdev);
6587
6588 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6589 flags |= LE_AD_NO_BREDR;
6590
6591 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6592 &flags, sizeof(flags));
6593 break;
6594 }
6595
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006596 hci_dev_unlock(hdev);
6597
Marcel Holtmann72000df2015-03-16 16:11:21 -07006598 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6599
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006600 status = MGMT_STATUS_SUCCESS;
6601
6602complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006603 rp->type = cp->type;
6604 rp->eir_len = cpu_to_le16(eir_len);
6605
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006606 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006607 status, rp, sizeof(*rp) + eir_len);
6608 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006609 goto done;
6610
6611 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6612 rp, sizeof(*rp) + eir_len,
6613 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006614
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006615done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006616 kfree(rp);
6617
6618 return err;
6619}
6620
Arman Uguray089fa8c2015-03-25 18:53:45 -07006621static u32 get_supported_adv_flags(struct hci_dev *hdev)
6622{
6623 u32 flags = 0;
6624
6625 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6626 flags |= MGMT_ADV_FLAG_DISCOV;
6627 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6628 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6629
6630 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6631 flags |= MGMT_ADV_FLAG_TX_POWER;
6632
6633 return flags;
6634}
6635
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006636static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6637 void *data, u16 data_len)
6638{
6639 struct mgmt_rp_read_adv_features *rp;
6640 size_t rp_len;
Florian Grandel286e0c82015-06-18 03:16:38 +02006641 int err, i;
Arman Uguray24b4f382015-03-23 15:57:12 -07006642 bool instance;
Florian Grandel286e0c82015-06-18 03:16:38 +02006643 struct adv_info *adv_instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006644 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006645
6646 BT_DBG("%s", hdev->name);
6647
Arman Uguray089fa8c2015-03-25 18:53:45 -07006648 if (!lmp_le_capable(hdev))
6649 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6650 MGMT_STATUS_REJECTED);
6651
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006652 hci_dev_lock(hdev);
6653
6654 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006655
Arman Uguray24b4f382015-03-23 15:57:12 -07006656 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6657 if (instance)
Florian Grandel286e0c82015-06-18 03:16:38 +02006658 rp_len += hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006659
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006660 rp = kmalloc(rp_len, GFP_ATOMIC);
6661 if (!rp) {
6662 hci_dev_unlock(hdev);
6663 return -ENOMEM;
6664 }
6665
Arman Uguray089fa8c2015-03-25 18:53:45 -07006666 supported_flags = get_supported_adv_flags(hdev);
6667
6668 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006669 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6670 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Florian Grandeld2609b32015-06-18 03:16:34 +02006671 rp->max_instances = HCI_MAX_ADV_INSTANCES;
Arman Uguray24b4f382015-03-23 15:57:12 -07006672
Arman Uguray24b4f382015-03-23 15:57:12 -07006673 if (instance) {
Florian Grandel286e0c82015-06-18 03:16:38 +02006674 i = 0;
6675 list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
6676 if (i >= hdev->adv_instance_cnt)
6677 break;
6678
6679 rp->instance[i] = adv_instance->instance;
6680 i++;
6681 }
6682 rp->num_instances = hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006683 } else {
6684 rp->num_instances = 0;
6685 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006686
6687 hci_dev_unlock(hdev);
6688
6689 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6690 MGMT_STATUS_SUCCESS, rp, rp_len);
6691
6692 kfree(rp);
6693
6694 return err;
6695}
6696
Arman Uguray4117ed72015-03-23 15:57:14 -07006697static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006698 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006699{
Arman Uguray4117ed72015-03-23 15:57:14 -07006700 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006701 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006702 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006703 bool tx_power_managed = false;
Arman Uguray24b4f382015-03-23 15:57:12 -07006704
Marcel Holtmann31a32482015-11-19 16:16:42 +01006705 if (is_adv_data) {
6706 if (adv_flags & (MGMT_ADV_FLAG_DISCOV |
6707 MGMT_ADV_FLAG_LIMITED_DISCOV |
6708 MGMT_ADV_FLAG_MANAGED_FLAGS)) {
6709 flags_managed = true;
6710 max_len -= 3;
6711 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006712
Marcel Holtmann31a32482015-11-19 16:16:42 +01006713 if (adv_flags & MGMT_ADV_FLAG_TX_POWER) {
6714 tx_power_managed = true;
6715 max_len -= 3;
6716 }
Arman Uguray5507e352015-03-25 18:53:44 -07006717 }
6718
Arman Uguray4117ed72015-03-23 15:57:14 -07006719 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006720 return false;
6721
Arman Uguray4117ed72015-03-23 15:57:14 -07006722 /* Make sure that the data is correctly formatted. */
6723 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6724 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006725
Arman Ugurayb44133f2015-03-25 18:53:41 -07006726 if (flags_managed && data[i + 1] == EIR_FLAGS)
6727 return false;
6728
Arman Uguray5507e352015-03-25 18:53:44 -07006729 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6730 return false;
6731
Arman Uguray24b4f382015-03-23 15:57:12 -07006732 /* If the current field length would exceed the total data
6733 * length, then it's invalid.
6734 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006735 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006736 return false;
6737 }
6738
6739 return true;
6740}
6741
Arman Uguray24b4f382015-03-23 15:57:12 -07006742static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6743 u16 opcode)
6744{
6745 struct mgmt_pending_cmd *cmd;
Florian Grandelfffd38b2015-06-18 03:16:47 +02006746 struct mgmt_cp_add_advertising *cp;
Arman Uguray24b4f382015-03-23 15:57:12 -07006747 struct mgmt_rp_add_advertising rp;
Florian Grandelfffd38b2015-06-18 03:16:47 +02006748 struct adv_info *adv_instance, *n;
6749 u8 instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006750
6751 BT_DBG("status %d", status);
6752
6753 hci_dev_lock(hdev);
6754
6755 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6756
Florian Grandelfffd38b2015-06-18 03:16:47 +02006757 if (status)
Arman Uguray24b4f382015-03-23 15:57:12 -07006758 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
Florian Grandelfffd38b2015-06-18 03:16:47 +02006759
6760 list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
6761 if (!adv_instance->pending)
6762 continue;
6763
6764 if (!status) {
6765 adv_instance->pending = false;
6766 continue;
6767 }
6768
6769 instance = adv_instance->instance;
6770
6771 if (hdev->cur_adv_instance == instance)
6772 cancel_adv_timeout(hdev);
6773
6774 hci_remove_adv_instance(hdev, instance);
6775 advertising_removed(cmd ? cmd->sk : NULL, hdev, instance);
Arman Uguray24b4f382015-03-23 15:57:12 -07006776 }
6777
6778 if (!cmd)
6779 goto unlock;
6780
Florian Grandelfffd38b2015-06-18 03:16:47 +02006781 cp = cmd->param;
6782 rp.instance = cp->instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006783
6784 if (status)
6785 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6786 mgmt_status(status));
6787 else
6788 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6789 mgmt_status(status), &rp, sizeof(rp));
6790
6791 mgmt_pending_remove(cmd);
6792
6793unlock:
6794 hci_dev_unlock(hdev);
6795}
6796
Florian Grandel5d900e42015-06-18 03:16:35 +02006797void mgmt_adv_timeout_expired(struct hci_dev *hdev)
Arman Uguray912098a2015-03-23 15:57:15 -07006798{
Florian Grandel847818d2015-06-18 03:16:46 +02006799 u8 instance;
6800 struct hci_request req;
6801
Florian Grandel5d900e42015-06-18 03:16:35 +02006802 hdev->adv_instance_timeout = 0;
Arman Uguray912098a2015-03-23 15:57:15 -07006803
Florian Grandel847818d2015-06-18 03:16:46 +02006804 instance = get_current_adv_instance(hdev);
6805 if (instance == 0x00)
6806 return;
6807
Arman Uguray912098a2015-03-23 15:57:15 -07006808 hci_dev_lock(hdev);
Florian Grandel847818d2015-06-18 03:16:46 +02006809 hci_req_init(&req, hdev);
6810
6811 clear_adv_instance(hdev, &req, instance, false);
6812
6813 if (list_empty(&hdev->adv_instances))
6814 disable_advertising(&req);
6815
6816 if (!skb_queue_empty(&req.cmd_q))
6817 hci_req_run(&req, NULL);
6818
Arman Uguray912098a2015-03-23 15:57:15 -07006819 hci_dev_unlock(hdev);
6820}
6821
Arman Uguray24b4f382015-03-23 15:57:12 -07006822static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6823 void *data, u16 data_len)
6824{
6825 struct mgmt_cp_add_advertising *cp = data;
6826 struct mgmt_rp_add_advertising rp;
6827 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006828 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006829 u8 status;
Florian Grandelfffd38b2015-06-18 03:16:47 +02006830 u16 timeout, duration;
6831 unsigned int prev_instance_cnt = hdev->adv_instance_cnt;
6832 u8 schedule_instance = 0;
6833 struct adv_info *next_instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006834 int err;
6835 struct mgmt_pending_cmd *cmd;
6836 struct hci_request req;
6837
6838 BT_DBG("%s", hdev->name);
6839
6840 status = mgmt_le_support(hdev);
6841 if (status)
6842 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6843 status);
6844
Marcel Holtmannceff86a2015-11-19 16:16:41 +01006845 if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
6846 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6847 MGMT_STATUS_INVALID_PARAMS);
6848
Arman Uguray24b4f382015-03-23 15:57:12 -07006849 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006850 timeout = __le16_to_cpu(cp->timeout);
Florian Grandelfffd38b2015-06-18 03:16:47 +02006851 duration = __le16_to_cpu(cp->duration);
Arman Uguray24b4f382015-03-23 15:57:12 -07006852
Florian Grandelfffd38b2015-06-18 03:16:47 +02006853 /* The current implementation only supports a subset of the specified
6854 * flags.
Arman Uguray089fa8c2015-03-25 18:53:45 -07006855 */
6856 supported_flags = get_supported_adv_flags(hdev);
Florian Grandelfffd38b2015-06-18 03:16:47 +02006857 if (flags & ~supported_flags)
Arman Uguray24b4f382015-03-23 15:57:12 -07006858 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6859 MGMT_STATUS_INVALID_PARAMS);
6860
6861 hci_dev_lock(hdev);
6862
Arman Uguray912098a2015-03-23 15:57:15 -07006863 if (timeout && !hdev_is_powered(hdev)) {
6864 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6865 MGMT_STATUS_REJECTED);
6866 goto unlock;
6867 }
6868
Arman Uguray24b4f382015-03-23 15:57:12 -07006869 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006870 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006871 pending_find(MGMT_OP_SET_LE, hdev)) {
6872 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6873 MGMT_STATUS_BUSY);
6874 goto unlock;
6875 }
6876
Arman Ugurayb44133f2015-03-25 18:53:41 -07006877 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006878 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006879 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006880 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6881 MGMT_STATUS_INVALID_PARAMS);
6882 goto unlock;
6883 }
6884
Florian Grandelfffd38b2015-06-18 03:16:47 +02006885 err = hci_add_adv_instance(hdev, cp->instance, flags,
6886 cp->adv_data_len, cp->data,
6887 cp->scan_rsp_len,
6888 cp->data + cp->adv_data_len,
6889 timeout, duration);
6890 if (err < 0) {
6891 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6892 MGMT_STATUS_FAILED);
6893 goto unlock;
6894 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006895
Florian Grandelfffd38b2015-06-18 03:16:47 +02006896 /* Only trigger an advertising added event if a new instance was
6897 * actually added.
6898 */
6899 if (hdev->adv_instance_cnt > prev_instance_cnt)
6900 advertising_added(sk, hdev, cp->instance);
Arman Uguray24b4f382015-03-23 15:57:12 -07006901
Florian Grandelfffd38b2015-06-18 03:16:47 +02006902 hci_dev_set_flag(hdev, HCI_ADVERTISING_INSTANCE);
Arman Uguray24b4f382015-03-23 15:57:12 -07006903
Florian Grandelfffd38b2015-06-18 03:16:47 +02006904 if (hdev->cur_adv_instance == cp->instance) {
6905 /* If the currently advertised instance is being changed then
6906 * cancel the current advertising and schedule the next
6907 * instance. If there is only one instance then the overridden
6908 * advertising data will be visible right away.
6909 */
6910 cancel_adv_timeout(hdev);
Arman Uguray912098a2015-03-23 15:57:15 -07006911
Florian Grandelfffd38b2015-06-18 03:16:47 +02006912 next_instance = hci_get_next_instance(hdev, cp->instance);
6913 if (next_instance)
6914 schedule_instance = next_instance->instance;
6915 } else if (!hdev->adv_instance_timeout) {
6916 /* Immediately advertise the new instance if no other
6917 * instance is currently being advertised.
6918 */
6919 schedule_instance = cp->instance;
6920 }
Arman Uguray912098a2015-03-23 15:57:15 -07006921
Florian Grandelfffd38b2015-06-18 03:16:47 +02006922 /* If the HCI_ADVERTISING flag is set or the device isn't powered or
6923 * there is no instance to be advertised then we have no HCI
6924 * communication to make. Simply return.
Arman Uguray24b4f382015-03-23 15:57:12 -07006925 */
6926 if (!hdev_is_powered(hdev) ||
Florian Grandelfffd38b2015-06-18 03:16:47 +02006927 hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
6928 !schedule_instance) {
6929 rp.instance = cp->instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006930 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6931 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6932 goto unlock;
6933 }
6934
6935 /* We're good to go, update advertising data, parameters, and start
6936 * advertising.
6937 */
6938 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6939 data_len);
6940 if (!cmd) {
6941 err = -ENOMEM;
6942 goto unlock;
6943 }
6944
6945 hci_req_init(&req, hdev);
6946
Florian Grandelfffd38b2015-06-18 03:16:47 +02006947 err = schedule_adv_instance(&req, schedule_instance, true);
Arman Uguray24b4f382015-03-23 15:57:12 -07006948
Florian Grandelfffd38b2015-06-18 03:16:47 +02006949 if (!err)
6950 err = hci_req_run(&req, add_advertising_complete);
6951
Arman Uguray24b4f382015-03-23 15:57:12 -07006952 if (err < 0)
6953 mgmt_pending_remove(cmd);
6954
6955unlock:
6956 hci_dev_unlock(hdev);
6957
6958 return err;
6959}
6960
Arman Ugurayda9293352015-03-23 15:57:13 -07006961static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6962 u16 opcode)
6963{
6964 struct mgmt_pending_cmd *cmd;
Florian Grandel01948332015-06-18 03:16:48 +02006965 struct mgmt_cp_remove_advertising *cp;
Arman Ugurayda9293352015-03-23 15:57:13 -07006966 struct mgmt_rp_remove_advertising rp;
6967
6968 BT_DBG("status %d", status);
6969
6970 hci_dev_lock(hdev);
6971
6972 /* A failure status here only means that we failed to disable
6973 * advertising. Otherwise, the advertising instance has been removed,
6974 * so report success.
6975 */
6976 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6977 if (!cmd)
6978 goto unlock;
6979
Florian Grandel01948332015-06-18 03:16:48 +02006980 cp = cmd->param;
6981 rp.instance = cp->instance;
Arman Ugurayda9293352015-03-23 15:57:13 -07006982
6983 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6984 &rp, sizeof(rp));
6985 mgmt_pending_remove(cmd);
6986
6987unlock:
6988 hci_dev_unlock(hdev);
6989}
6990
6991static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6992 void *data, u16 data_len)
6993{
6994 struct mgmt_cp_remove_advertising *cp = data;
6995 struct mgmt_rp_remove_advertising rp;
Arman Ugurayda9293352015-03-23 15:57:13 -07006996 struct mgmt_pending_cmd *cmd;
6997 struct hci_request req;
Johan Hedberg952497b2015-06-18 21:05:31 +03006998 int err;
Arman Ugurayda9293352015-03-23 15:57:13 -07006999
7000 BT_DBG("%s", hdev->name);
7001
Arman Ugurayda9293352015-03-23 15:57:13 -07007002 hci_dev_lock(hdev);
7003
Johan Hedberg952497b2015-06-18 21:05:31 +03007004 if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {
Florian Grandel01948332015-06-18 03:16:48 +02007005 err = mgmt_cmd_status(sk, hdev->id,
7006 MGMT_OP_REMOVE_ADVERTISING,
7007 MGMT_STATUS_INVALID_PARAMS);
7008 goto unlock;
7009 }
7010
Arman Ugurayda9293352015-03-23 15:57:13 -07007011 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
7012 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
7013 pending_find(MGMT_OP_SET_LE, hdev)) {
7014 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7015 MGMT_STATUS_BUSY);
7016 goto unlock;
7017 }
7018
7019 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
7020 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7021 MGMT_STATUS_INVALID_PARAMS);
7022 goto unlock;
7023 }
7024
Florian Grandel01948332015-06-18 03:16:48 +02007025 hci_req_init(&req, hdev);
Arman Uguray912098a2015-03-23 15:57:15 -07007026
Florian Grandel01948332015-06-18 03:16:48 +02007027 clear_adv_instance(hdev, &req, cp->instance, true);
Arman Ugurayda9293352015-03-23 15:57:13 -07007028
Florian Grandel01948332015-06-18 03:16:48 +02007029 if (list_empty(&hdev->adv_instances))
7030 disable_advertising(&req);
Arman Ugurayda9293352015-03-23 15:57:13 -07007031
Florian Grandel01948332015-06-18 03:16:48 +02007032 /* If no HCI commands have been collected so far or the HCI_ADVERTISING
7033 * flag is set or the device isn't powered then we have no HCI
7034 * communication to make. Simply return.
Arman Ugurayda9293352015-03-23 15:57:13 -07007035 */
Florian Grandel01948332015-06-18 03:16:48 +02007036 if (skb_queue_empty(&req.cmd_q) ||
7037 !hdev_is_powered(hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07007038 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Florian Grandel01948332015-06-18 03:16:48 +02007039 rp.instance = cp->instance;
Arman Ugurayda9293352015-03-23 15:57:13 -07007040 err = mgmt_cmd_complete(sk, hdev->id,
7041 MGMT_OP_REMOVE_ADVERTISING,
7042 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7043 goto unlock;
7044 }
7045
7046 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
7047 data_len);
7048 if (!cmd) {
7049 err = -ENOMEM;
7050 goto unlock;
7051 }
7052
Arman Ugurayda9293352015-03-23 15:57:13 -07007053 err = hci_req_run(&req, remove_advertising_complete);
7054 if (err < 0)
7055 mgmt_pending_remove(cmd);
7056
7057unlock:
7058 hci_dev_unlock(hdev);
7059
7060 return err;
7061}
7062
Marcel Holtmann40b25fe2015-11-19 16:16:43 +01007063static u8 tlv_data_max_len(u32 adv_flags, bool is_adv_data)
7064{
7065 u8 max_len = HCI_MAX_AD_LENGTH;
7066
7067 if (is_adv_data) {
7068 if (adv_flags & (MGMT_ADV_FLAG_DISCOV |
7069 MGMT_ADV_FLAG_LIMITED_DISCOV |
7070 MGMT_ADV_FLAG_MANAGED_FLAGS))
7071 max_len -= 3;
7072
7073 if (adv_flags & MGMT_ADV_FLAG_TX_POWER)
7074 max_len -= 3;
7075 }
7076
7077 return max_len;
7078}
7079
7080static int get_adv_size_info(struct sock *sk, struct hci_dev *hdev,
7081 void *data, u16 data_len)
7082{
7083 struct mgmt_cp_get_adv_size_info *cp = data;
7084 struct mgmt_rp_get_adv_size_info rp;
7085 u32 flags, supported_flags;
7086 int err;
7087
7088 BT_DBG("%s", hdev->name);
7089
7090 if (!lmp_le_capable(hdev))
7091 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
7092 MGMT_STATUS_REJECTED);
7093
7094 if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
7095 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
7096 MGMT_STATUS_INVALID_PARAMS);
7097
7098 flags = __le32_to_cpu(cp->flags);
7099
7100 /* The current implementation only supports a subset of the specified
7101 * flags.
7102 */
7103 supported_flags = get_supported_adv_flags(hdev);
7104 if (flags & ~supported_flags)
7105 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
7106 MGMT_STATUS_INVALID_PARAMS);
7107
7108 rp.instance = cp->instance;
7109 rp.flags = cp->flags;
7110 rp.max_adv_data_len = tlv_data_max_len(flags, true);
7111 rp.max_scan_rsp_len = tlv_data_max_len(flags, false);
7112
7113 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
7114 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7115
7116 return err;
7117}
7118
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007119static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007120 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007121 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007122 HCI_MGMT_NO_HDEV |
7123 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007124 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007125 HCI_MGMT_NO_HDEV |
7126 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007127 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007128 HCI_MGMT_NO_HDEV |
7129 HCI_MGMT_UNTRUSTED },
7130 { read_controller_info, MGMT_READ_INFO_SIZE,
7131 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007132 { set_powered, MGMT_SETTING_SIZE },
7133 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7134 { set_connectable, MGMT_SETTING_SIZE },
7135 { set_fast_connectable, MGMT_SETTING_SIZE },
7136 { set_bondable, MGMT_SETTING_SIZE },
7137 { set_link_security, MGMT_SETTING_SIZE },
7138 { set_ssp, MGMT_SETTING_SIZE },
7139 { set_hs, MGMT_SETTING_SIZE },
7140 { set_le, MGMT_SETTING_SIZE },
7141 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7142 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7143 { add_uuid, MGMT_ADD_UUID_SIZE },
7144 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007145 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7146 HCI_MGMT_VAR_LEN },
7147 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7148 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007149 { disconnect, MGMT_DISCONNECT_SIZE },
7150 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7151 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7152 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7153 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7154 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7155 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7156 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7157 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7158 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7159 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7160 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007161 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7162 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7163 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007164 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7165 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7166 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7167 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7168 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7169 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7170 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7171 { set_advertising, MGMT_SETTING_SIZE },
7172 { set_bredr, MGMT_SETTING_SIZE },
7173 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7174 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7175 { set_secure_conn, MGMT_SETTING_SIZE },
7176 { set_debug_keys, MGMT_SETTING_SIZE },
7177 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007178 { load_irks, MGMT_LOAD_IRKS_SIZE,
7179 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007180 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7181 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7182 { add_device, MGMT_ADD_DEVICE_SIZE },
7183 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007184 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7185 HCI_MGMT_VAR_LEN },
7186 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007187 HCI_MGMT_NO_HDEV |
7188 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007189 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007190 HCI_MGMT_UNCONFIGURED |
7191 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007192 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7193 HCI_MGMT_UNCONFIGURED },
7194 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7195 HCI_MGMT_UNCONFIGURED },
7196 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7197 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007198 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007199 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007200 HCI_MGMT_NO_HDEV |
7201 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007202 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007203 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7204 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007205 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Marcel Holtmann40b25fe2015-11-19 16:16:43 +01007206 { get_adv_size_info, MGMT_GET_ADV_SIZE_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007207};
7208
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007209void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007210{
Marcel Holtmannced85542015-03-14 19:27:56 -07007211 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007212
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007213 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7214 return;
7215
Marcel Holtmannf9207332015-03-14 19:27:55 -07007216 switch (hdev->dev_type) {
7217 case HCI_BREDR:
7218 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7219 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7220 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007221 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007222 } else {
7223 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7224 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007225 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007226 }
7227 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007228 case HCI_AMP:
7229 ev.type = 0x02;
7230 break;
7231 default:
7232 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007233 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007234
7235 ev.bus = hdev->bus;
7236
7237 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7238 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007239}
7240
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007241void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007242{
Marcel Holtmannced85542015-03-14 19:27:56 -07007243 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007244 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007245
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007246 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7247 return;
7248
Marcel Holtmannf9207332015-03-14 19:27:55 -07007249 switch (hdev->dev_type) {
7250 case HCI_BREDR:
7251 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007252
Marcel Holtmannf9207332015-03-14 19:27:55 -07007253 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7254 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7255 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007256 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007257 } else {
7258 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7259 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007260 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007261 }
7262 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007263 case HCI_AMP:
7264 ev.type = 0x02;
7265 break;
7266 default:
7267 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007268 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007269
7270 ev.bus = hdev->bus;
7271
7272 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7273 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007274}
7275
Andre Guedes6046dc32014-02-26 20:21:51 -03007276/* This function requires the caller holds hdev->lock */
Johan Hedbergaf02dd42015-11-11 08:11:21 +02007277static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03007278{
7279 struct hci_conn_params *p;
7280
7281 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007282 /* Needed for AUTO_OFF case where might not "really"
7283 * have been powered off.
7284 */
7285 list_del_init(&p->action);
7286
7287 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007288 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007289 case HCI_AUTO_CONN_ALWAYS:
7290 list_add(&p->action, &hdev->pend_le_conns);
7291 break;
7292 case HCI_AUTO_CONN_REPORT:
7293 list_add(&p->action, &hdev->pend_le_reports);
7294 break;
7295 default:
7296 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007297 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007298 }
7299}
7300
Marcel Holtmann1904a852015-01-11 13:50:44 -08007301static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007302{
7303 struct cmd_lookup match = { NULL, hdev };
7304
7305 BT_DBG("status 0x%02x", status);
7306
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007307 if (!status) {
7308 /* Register the available SMP channels (BR/EDR and LE) only
7309 * when successfully powering on the controller. This late
7310 * registration is required so that LE SMP can clearly
7311 * decide if the public address or static address is used.
7312 */
7313 smp_register(hdev);
Johan Hedbergaf02dd42015-11-11 08:11:21 +02007314
7315 restart_le_actions(hdev);
7316 hci_update_background_scan(hdev);
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007317 }
7318
Johan Hedberg229ab392013-03-15 17:06:53 -05007319 hci_dev_lock(hdev);
7320
7321 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7322
7323 new_settings(hdev, match.sk);
7324
7325 hci_dev_unlock(hdev);
7326
7327 if (match.sk)
7328 sock_put(match.sk);
7329}
7330
Johan Hedberg70da6242013-03-15 17:06:51 -05007331static int powered_update_hci(struct hci_dev *hdev)
7332{
Johan Hedberg890ea892013-03-15 17:06:52 -05007333 struct hci_request req;
Florian Grandel320b3bf2015-06-18 03:16:49 +02007334 struct adv_info *adv_instance;
Johan Hedberg70da6242013-03-15 17:06:51 -05007335 u8 link_sec;
7336
Johan Hedberg890ea892013-03-15 17:06:52 -05007337 hci_req_init(&req, hdev);
7338
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007339 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007340 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007341 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007342
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007343 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007344
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007345 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7346 u8 support = 0x01;
7347
7348 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7349 sizeof(support), &support);
7350 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007351 }
7352
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007353 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007354 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007355 struct hci_cp_write_le_host_supported cp;
7356
Marcel Holtmann32226e42014-07-24 20:04:16 +02007357 cp.le = 0x01;
7358 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007359
7360 /* Check first if we already have the right
7361 * host state (host features set)
7362 */
7363 if (cp.le != lmp_host_le_capable(hdev) ||
7364 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007365 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7366 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007367 }
7368
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007369 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007370 /* Make sure the controller has a good default for
7371 * advertising data. This also applies to the case
7372 * where BR/EDR was toggled during the AUTO_OFF phase.
7373 */
Florian Grandel320b3bf2015-06-18 03:16:49 +02007374 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
7375 (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7376 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007377 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007378 update_scan_rsp_data(&req);
7379 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007380
Florian Grandel320b3bf2015-06-18 03:16:49 +02007381 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
7382 hdev->cur_adv_instance == 0x00 &&
7383 !list_empty(&hdev->adv_instances)) {
7384 adv_instance = list_first_entry(&hdev->adv_instances,
7385 struct adv_info, list);
7386 hdev->cur_adv_instance = adv_instance->instance;
7387 }
7388
7389 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007390 enable_advertising(&req);
Florian Grandel320b3bf2015-06-18 03:16:49 +02007391 else if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
7392 hdev->cur_adv_instance)
7393 schedule_adv_instance(&req, hdev->cur_adv_instance,
7394 true);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007395 }
7396
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007397 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007398 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007399 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7400 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007401
7402 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007403 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007404 write_fast_connectable(&req, true);
7405 else
7406 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007407 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007408 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007409 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007410 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007411 }
7412
Johan Hedberg229ab392013-03-15 17:06:53 -05007413 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007414}
7415
Johan Hedberg744cf192011-11-08 20:40:14 +02007416int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007417{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007418 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007419 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007420 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007421
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007422 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007423 return 0;
7424
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007425 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007426 if (powered_update_hci(hdev) == 0)
7427 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007428
Johan Hedberg229ab392013-03-15 17:06:53 -05007429 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7430 &match);
7431 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007432 }
7433
Johan Hedberg229ab392013-03-15 17:06:53 -05007434 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007435
7436 /* If the power off is because of hdev unregistration let
7437 * use the appropriate INVALID_INDEX status. Otherwise use
7438 * NOT_POWERED. We cover both scenarios here since later in
7439 * mgmt_index_removed() any hci_conn callbacks will have already
7440 * been triggered, potentially causing misleading DISCONNECTED
7441 * status responses.
7442 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007443 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007444 status = MGMT_STATUS_INVALID_INDEX;
7445 else
7446 status = MGMT_STATUS_NOT_POWERED;
7447
7448 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007449
7450 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007451 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7452 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007453
7454new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007455 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007456
7457 if (match.sk)
7458 sock_put(match.sk);
7459
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007460 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007461}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007462
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007463void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007464{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007465 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007466 u8 status;
7467
Johan Hedberg333ae952015-03-17 13:48:47 +02007468 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007469 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007470 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007471
7472 if (err == -ERFKILL)
7473 status = MGMT_STATUS_RFKILLED;
7474 else
7475 status = MGMT_STATUS_FAILED;
7476
Johan Hedberga69e8372015-03-06 21:08:53 +02007477 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007478
7479 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007480}
7481
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007482void mgmt_discoverable_timeout(struct hci_dev *hdev)
7483{
7484 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007485
7486 hci_dev_lock(hdev);
7487
7488 /* When discoverable timeout triggers, then just make sure
7489 * the limited discoverable flag is cleared. Even in the case
7490 * of a timeout triggered from general discoverable, it is
7491 * safe to unconditionally clear the flag.
7492 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007493 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7494 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007495
7496 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007497 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007498 u8 scan = SCAN_PAGE;
7499 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7500 sizeof(scan), &scan);
7501 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007502 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007503
7504 /* Advertising instances don't use the global discoverable setting, so
7505 * only update AD if advertising was enabled using Set Advertising.
7506 */
7507 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7508 update_adv_data(&req);
7509
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007510 hci_req_run(&req, NULL);
7511
7512 hdev->discov_timeout = 0;
7513
Johan Hedberg9a43e252013-10-20 19:00:07 +03007514 new_settings(hdev, NULL);
7515
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007516 hci_dev_unlock(hdev);
7517}
7518
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007519void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7520 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007521{
Johan Hedberg86742e12011-11-07 23:13:38 +02007522 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007523
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007524 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007525
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007526 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007527 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007528 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007529 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007530 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007531 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007532
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007533 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007534}
Johan Hedbergf7520542011-01-20 12:34:39 +02007535
Johan Hedbergd7b25452014-05-23 13:19:53 +03007536static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7537{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007538 switch (ltk->type) {
7539 case SMP_LTK:
7540 case SMP_LTK_SLAVE:
7541 if (ltk->authenticated)
7542 return MGMT_LTK_AUTHENTICATED;
7543 return MGMT_LTK_UNAUTHENTICATED;
7544 case SMP_LTK_P256:
7545 if (ltk->authenticated)
7546 return MGMT_LTK_P256_AUTH;
7547 return MGMT_LTK_P256_UNAUTH;
7548 case SMP_LTK_P256_DEBUG:
7549 return MGMT_LTK_P256_DEBUG;
7550 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007551
7552 return MGMT_LTK_UNAUTHENTICATED;
7553}
7554
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007555void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007556{
7557 struct mgmt_ev_new_long_term_key ev;
7558
7559 memset(&ev, 0, sizeof(ev));
7560
Marcel Holtmann5192d302014-02-19 17:11:58 -08007561 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007562 * without providing an identity resolving key don't require
Marcel Holtmann5192d302014-02-19 17:11:58 -08007563 * to store long term keys. Their addresses will change the
7564 * next time around.
7565 *
7566 * Only when a remote device provides an identity address
7567 * make sure the long term key is stored. If the remote
7568 * identity is known, the long term keys are internally
7569 * mapped to the identity address. So allow static random
7570 * and public addresses here.
7571 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007572 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7573 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7574 ev.store_hint = 0x00;
7575 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007576 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007577
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007578 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007579 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007580 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007581 ev.key.enc_size = key->enc_size;
7582 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007583 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007584
Johan Hedberg2ceba532014-06-16 19:25:16 +03007585 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007586 ev.key.master = 1;
7587
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007588 /* Make sure we copy only the significant bytes based on the
7589 * encryption key size, and set the rest of the value to zeroes.
7590 */
Jakub Pawlowskicb922052015-08-05 23:16:29 +02007591 memcpy(ev.key.val, key->val, key->enc_size);
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007592 memset(ev.key.val + key->enc_size, 0,
7593 sizeof(ev.key.val) - key->enc_size);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007594
Marcel Holtmann083368f2013-10-15 14:26:29 -07007595 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007596}
7597
Johan Hedbergcad20c22015-10-12 13:36:19 +02007598void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk, bool persistent)
Johan Hedberg95fbac82014-02-19 15:18:31 +02007599{
7600 struct mgmt_ev_new_irk ev;
7601
7602 memset(&ev, 0, sizeof(ev));
7603
Johan Hedbergcad20c22015-10-12 13:36:19 +02007604 ev.store_hint = persistent;
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007605
Johan Hedberg95fbac82014-02-19 15:18:31 +02007606 bacpy(&ev.rpa, &irk->rpa);
7607 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7608 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7609 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7610
7611 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7612}
7613
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007614void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7615 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007616{
7617 struct mgmt_ev_new_csrk ev;
7618
7619 memset(&ev, 0, sizeof(ev));
7620
7621 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007622 * without providing an identity resolving key don't require
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007623 * to store signature resolving keys. Their addresses will change
7624 * the next time around.
7625 *
7626 * Only when a remote device provides an identity address
7627 * make sure the signature resolving key is stored. So allow
7628 * static random and public addresses here.
7629 */
7630 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7631 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7632 ev.store_hint = 0x00;
7633 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007634 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007635
7636 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7637 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007638 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007639 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7640
7641 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7642}
7643
Andre Guedesffb5a8272014-07-01 18:10:11 -03007644void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007645 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7646 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007647{
7648 struct mgmt_ev_new_conn_param ev;
7649
Johan Hedbergc103aea2014-07-02 17:37:34 +03007650 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7651 return;
7652
Andre Guedesffb5a8272014-07-01 18:10:11 -03007653 memset(&ev, 0, sizeof(ev));
7654 bacpy(&ev.addr.bdaddr, bdaddr);
7655 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007656 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007657 ev.min_interval = cpu_to_le16(min_interval);
7658 ev.max_interval = cpu_to_le16(max_interval);
7659 ev.latency = cpu_to_le16(latency);
7660 ev.timeout = cpu_to_le16(timeout);
7661
7662 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7663}
7664
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007665void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7666 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007667{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007668 char buf[512];
7669 struct mgmt_ev_device_connected *ev = (void *) buf;
7670 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007671
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007672 bacpy(&ev->addr.bdaddr, &conn->dst);
7673 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007674
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007675 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007676
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007677 /* We must ensure that the EIR Data fields are ordered and
7678 * unique. Keep it simple for now and avoid the problem by not
7679 * adding any BR/EDR data to the LE adv.
7680 */
7681 if (conn->le_adv_data_len > 0) {
7682 memcpy(&ev->eir[eir_len],
7683 conn->le_adv_data, conn->le_adv_data_len);
7684 eir_len = conn->le_adv_data_len;
7685 } else {
7686 if (name_len > 0)
7687 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7688 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007689
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007690 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007691 eir_len = eir_append_data(ev->eir, eir_len,
7692 EIR_CLASS_OF_DEV,
7693 conn->dev_class, 3);
7694 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007695
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007696 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007697
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007698 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7699 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007700}
7701
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007702static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007703{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007704 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007705
Johan Hedbergf5818c22014-12-05 13:36:02 +02007706 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007707
7708 *sk = cmd->sk;
7709 sock_hold(*sk);
7710
Johan Hedberga664b5b2011-02-19 12:06:02 -03007711 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007712}
7713
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007714static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007715{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007716 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007717 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007718
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007719 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7720
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007721 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007722 mgmt_pending_remove(cmd);
7723}
7724
Johan Hedberg84c61d92014-08-01 11:13:30 +03007725bool mgmt_powering_down(struct hci_dev *hdev)
7726{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007727 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007728 struct mgmt_mode *cp;
7729
Johan Hedberg333ae952015-03-17 13:48:47 +02007730 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007731 if (!cmd)
7732 return false;
7733
7734 cp = cmd->param;
7735 if (!cp->val)
7736 return true;
7737
7738 return false;
7739}
7740
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007741void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007742 u8 link_type, u8 addr_type, u8 reason,
7743 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007744{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007745 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007746 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007747
Johan Hedberg84c61d92014-08-01 11:13:30 +03007748 /* The connection is still in hci_conn_hash so test for 1
7749 * instead of 0 to know if this is the last one.
7750 */
7751 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7752 cancel_delayed_work(&hdev->power_off);
7753 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007754 }
7755
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007756 if (!mgmt_connected)
7757 return;
7758
Andre Guedes57eb7762013-10-30 19:01:41 -03007759 if (link_type != ACL_LINK && link_type != LE_LINK)
7760 return;
7761
Johan Hedberg744cf192011-11-08 20:40:14 +02007762 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007763
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007764 bacpy(&ev.addr.bdaddr, bdaddr);
7765 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7766 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007767
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007768 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007769
7770 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007771 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007772
Johan Hedberg124f6e32012-02-09 13:50:12 +02007773 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007774 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007775}
7776
Marcel Holtmann78929242013-10-06 23:55:47 -07007777void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7778 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007779{
Andre Guedes3655bba2013-10-30 19:01:40 -03007780 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7781 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007782 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007783
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007784 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7785 hdev);
7786
Johan Hedberg333ae952015-03-17 13:48:47 +02007787 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007788 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007789 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007790
Andre Guedes3655bba2013-10-30 19:01:40 -03007791 cp = cmd->param;
7792
7793 if (bacmp(bdaddr, &cp->addr.bdaddr))
7794 return;
7795
7796 if (cp->addr.type != bdaddr_type)
7797 return;
7798
Johan Hedbergf5818c22014-12-05 13:36:02 +02007799 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007800 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007801}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007802
Marcel Holtmann445608d2013-10-06 23:55:48 -07007803void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7804 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007805{
7806 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007807
Johan Hedberg84c61d92014-08-01 11:13:30 +03007808 /* The connection is still in hci_conn_hash so test for 1
7809 * instead of 0 to know if this is the last one.
7810 */
7811 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7812 cancel_delayed_work(&hdev->power_off);
7813 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007814 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007815
Johan Hedberg4c659c32011-11-07 23:13:39 +02007816 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007817 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007818 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007819
Marcel Holtmann445608d2013-10-06 23:55:48 -07007820 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007821}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007822
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007823void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007824{
7825 struct mgmt_ev_pin_code_request ev;
7826
Johan Hedbergd8457692012-02-17 14:24:57 +02007827 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007828 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007829 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007830
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007831 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007832}
7833
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007834void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7835 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007836{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007837 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007838
Johan Hedberg333ae952015-03-17 13:48:47 +02007839 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007840 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007841 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007842
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007843 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007844 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007845}
7846
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007847void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7848 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007849{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007850 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007851
Johan Hedberg333ae952015-03-17 13:48:47 +02007852 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007853 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007854 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007855
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007856 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007857 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007858}
Johan Hedberga5c29682011-02-19 12:05:57 -03007859
Johan Hedberg744cf192011-11-08 20:40:14 +02007860int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007861 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007862 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007863{
7864 struct mgmt_ev_user_confirm_request ev;
7865
Johan Hedberg744cf192011-11-08 20:40:14 +02007866 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007867
Johan Hedberg272d90d2012-02-09 15:26:12 +02007868 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007869 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007870 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007871 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007872
Johan Hedberg744cf192011-11-08 20:40:14 +02007873 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007874 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007875}
7876
Johan Hedberg272d90d2012-02-09 15:26:12 +02007877int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007878 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007879{
7880 struct mgmt_ev_user_passkey_request ev;
7881
7882 BT_DBG("%s", hdev->name);
7883
Johan Hedberg272d90d2012-02-09 15:26:12 +02007884 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007885 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007886
7887 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007888 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007889}
7890
Brian Gix0df4c182011-11-16 13:53:13 -08007891static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007892 u8 link_type, u8 addr_type, u8 status,
7893 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007894{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007895 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007896
Johan Hedberg333ae952015-03-17 13:48:47 +02007897 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007898 if (!cmd)
7899 return -ENOENT;
7900
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007901 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007902 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007903
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007904 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007905}
7906
Johan Hedberg744cf192011-11-08 20:40:14 +02007907int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007908 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007909{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007910 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007911 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007912}
7913
Johan Hedberg272d90d2012-02-09 15:26:12 +02007914int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007915 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007916{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007917 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007918 status,
7919 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007920}
Johan Hedberg2a611692011-02-19 12:06:00 -03007921
Brian Gix604086b2011-11-23 08:28:33 -08007922int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007923 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007924{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007925 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007926 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007927}
7928
Johan Hedberg272d90d2012-02-09 15:26:12 +02007929int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007930 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007931{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007932 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007933 status,
7934 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007935}
7936
Johan Hedberg92a25252012-09-06 18:39:26 +03007937int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7938 u8 link_type, u8 addr_type, u32 passkey,
7939 u8 entered)
7940{
7941 struct mgmt_ev_passkey_notify ev;
7942
7943 BT_DBG("%s", hdev->name);
7944
7945 bacpy(&ev.addr.bdaddr, bdaddr);
7946 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7947 ev.passkey = __cpu_to_le32(passkey);
7948 ev.entered = entered;
7949
7950 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7951}
7952
Johan Hedberge1e930f2014-09-08 17:09:49 -07007953void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007954{
7955 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007956 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007957 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007958
Johan Hedberge1e930f2014-09-08 17:09:49 -07007959 bacpy(&ev.addr.bdaddr, &conn->dst);
7960 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7961 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007962
Johan Hedberge1e930f2014-09-08 17:09:49 -07007963 cmd = find_pairing(conn);
7964
7965 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7966 cmd ? cmd->sk : NULL);
7967
Johan Hedberga511b352014-12-11 21:45:45 +02007968 if (cmd) {
7969 cmd->cmd_complete(cmd, status);
7970 mgmt_pending_remove(cmd);
7971 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007972}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007973
Marcel Holtmann464996a2013-10-15 14:26:24 -07007974void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007975{
7976 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007977 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007978
7979 if (status) {
7980 u8 mgmt_err = mgmt_status(status);
7981 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007982 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007983 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007984 }
7985
Marcel Holtmann464996a2013-10-15 14:26:24 -07007986 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007987 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007988 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007989 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007990
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007991 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007992 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007993
Johan Hedberg47990ea2012-02-22 11:58:37 +02007994 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007995 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007996
7997 if (match.sk)
7998 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007999}
8000
Johan Hedberg890ea892013-03-15 17:06:52 -05008001static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02008002{
Johan Hedberg890ea892013-03-15 17:06:52 -05008003 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008004 struct hci_cp_write_eir cp;
8005
Johan Hedberg976eb202012-10-24 21:12:01 +03008006 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05008007 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008008
Johan Hedbergc80da272012-02-22 15:38:48 +02008009 memset(hdev->eir, 0, sizeof(hdev->eir));
8010
Johan Hedbergcacaf522012-02-21 00:52:42 +02008011 memset(&cp, 0, sizeof(cp));
8012
Johan Hedberg890ea892013-03-15 17:06:52 -05008013 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02008014}
8015
Marcel Holtmann3e248562013-10-15 14:26:25 -07008016void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008017{
8018 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05008019 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008020 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008021
8022 if (status) {
8023 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008024
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008025 if (enable && hci_dev_test_and_clear_flag(hdev,
8026 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008027 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008028 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008029 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008030
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008031 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
8032 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008033 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008034 }
8035
8036 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07008037 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008038 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008039 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008040 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008041 changed = hci_dev_test_and_clear_flag(hdev,
8042 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008043 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008044 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008045 }
8046
8047 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
8048
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008049 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07008050 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008051
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02008052 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008053 sock_put(match.sk);
8054
Johan Hedberg890ea892013-03-15 17:06:52 -05008055 hci_req_init(&req, hdev);
8056
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008057 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
8058 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03008059 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
8060 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05008061 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008062 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05008063 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008064 }
Johan Hedberg890ea892013-03-15 17:06:52 -05008065
8066 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008067}
8068
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008069static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02008070{
8071 struct cmd_lookup *match = data;
8072
Johan Hedberg90e70452012-02-23 23:09:40 +02008073 if (match->sk == NULL) {
8074 match->sk = cmd->sk;
8075 sock_hold(match->sk);
8076 }
Johan Hedberg90e70452012-02-23 23:09:40 +02008077}
8078
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07008079void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
8080 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008081{
Johan Hedberg90e70452012-02-23 23:09:40 +02008082 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008083
Johan Hedberg92da6092013-03-15 17:06:55 -05008084 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
8085 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
8086 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02008087
8088 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008089 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
8090 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02008091
8092 if (match.sk)
8093 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008094}
8095
Marcel Holtmann7667da32013-10-15 14:26:27 -07008096void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02008097{
Johan Hedbergb312b1612011-03-16 14:29:37 +02008098 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008099 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008100
Johan Hedberg13928972013-03-15 17:07:00 -05008101 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07008102 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008103
8104 memset(&ev, 0, sizeof(ev));
8105 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008106 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008107
Johan Hedberg333ae952015-03-17 13:48:47 +02008108 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05008109 if (!cmd) {
8110 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02008111
Johan Hedberg13928972013-03-15 17:07:00 -05008112 /* If this is a HCI command related to powering on the
8113 * HCI dev don't send any mgmt signals.
8114 */
Johan Hedberg333ae952015-03-17 13:48:47 +02008115 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07008116 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008117 }
8118
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008119 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
8120 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008121}
Szymon Jancc35938b2011-03-22 13:12:21 +01008122
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008123static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
8124{
8125 int i;
8126
8127 for (i = 0; i < uuid_count; i++) {
8128 if (!memcmp(uuid, uuids[i], 16))
8129 return true;
8130 }
8131
8132 return false;
8133}
8134
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008135static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
8136{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008137 u16 parsed = 0;
8138
8139 while (parsed < eir_len) {
8140 u8 field_len = eir[0];
8141 u8 uuid[16];
8142 int i;
8143
8144 if (field_len == 0)
8145 break;
8146
8147 if (eir_len - parsed < field_len + 1)
8148 break;
8149
8150 switch (eir[1]) {
8151 case EIR_UUID16_ALL:
8152 case EIR_UUID16_SOME:
8153 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008154 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008155 uuid[13] = eir[i + 3];
8156 uuid[12] = eir[i + 2];
8157 if (has_uuid(uuid, uuid_count, uuids))
8158 return true;
8159 }
8160 break;
8161 case EIR_UUID32_ALL:
8162 case EIR_UUID32_SOME:
8163 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008164 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008165 uuid[15] = eir[i + 5];
8166 uuid[14] = eir[i + 4];
8167 uuid[13] = eir[i + 3];
8168 uuid[12] = eir[i + 2];
8169 if (has_uuid(uuid, uuid_count, uuids))
8170 return true;
8171 }
8172 break;
8173 case EIR_UUID128_ALL:
8174 case EIR_UUID128_SOME:
8175 for (i = 0; i + 17 <= field_len; i += 16) {
8176 memcpy(uuid, eir + i + 2, 16);
8177 if (has_uuid(uuid, uuid_count, uuids))
8178 return true;
8179 }
8180 break;
8181 }
8182
8183 parsed += field_len + 1;
8184 eir += field_len + 1;
8185 }
8186
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008187 return false;
8188}
8189
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008190static void restart_le_scan(struct hci_dev *hdev)
8191{
8192 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008193 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008194 return;
8195
8196 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8197 hdev->discovery.scan_start +
8198 hdev->discovery.scan_duration))
8199 return;
8200
Johan Hedberg7c1fbed2015-11-11 08:11:23 +02008201 queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_restart,
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008202 DISCOV_LE_RESTART_DELAY);
8203}
8204
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008205static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8206 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8207{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008208 /* If a RSSI threshold has been specified, and
8209 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8210 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8211 * is set, let it through for further processing, as we might need to
8212 * restart the scan.
8213 *
8214 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8215 * the results are also dropped.
8216 */
8217 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8218 (rssi == HCI_RSSI_INVALID ||
8219 (rssi < hdev->discovery.rssi &&
8220 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8221 return false;
8222
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008223 if (hdev->discovery.uuid_count != 0) {
8224 /* If a list of UUIDs is provided in filter, results with no
8225 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008226 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008227 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8228 hdev->discovery.uuids) &&
8229 !eir_has_uuids(scan_rsp, scan_rsp_len,
8230 hdev->discovery.uuid_count,
8231 hdev->discovery.uuids))
8232 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008233 }
8234
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008235 /* If duplicate filtering does not report RSSI changes, then restart
8236 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008237 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008238 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8239 restart_le_scan(hdev);
8240
8241 /* Validate RSSI value against the RSSI threshold once more. */
8242 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8243 rssi < hdev->discovery.rssi)
8244 return false;
8245 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008246
8247 return true;
8248}
8249
Marcel Holtmann901801b2013-10-06 23:55:51 -07008250void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008251 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8252 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008253{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008254 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008255 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008256 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008257
Johan Hedberg75ce2082014-07-02 22:42:01 +03008258 /* Don't send events for a non-kernel initiated discovery. With
8259 * LE one exception is if we have pend_le_reports > 0 in which
8260 * case we're doing passive scanning and want these events.
8261 */
8262 if (!hci_discovery_active(hdev)) {
8263 if (link_type == ACL_LINK)
8264 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008265 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008266 return;
8267 }
Andre Guedes12602d02013-04-30 15:29:40 -03008268
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008269 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008270 /* We are using service discovery */
8271 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8272 scan_rsp_len))
8273 return;
8274 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008275
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008276 /* Make sure that the buffer is big enough. The 5 extra bytes
8277 * are for the potential CoD field.
8278 */
8279 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008280 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008281
Johan Hedberg1dc06092012-01-15 21:01:23 +02008282 memset(buf, 0, sizeof(buf));
8283
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008284 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8285 * RSSI value was reported as 0 when not available. This behavior
8286 * is kept when using device discovery. This is required for full
8287 * backwards compatibility with the API.
8288 *
8289 * However when using service discovery, the value 127 will be
8290 * returned when the RSSI is not available.
8291 */
Szymon Janc91200e92015-01-22 16:57:05 +01008292 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8293 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008294 rssi = 0;
8295
Johan Hedberg841c5642014-07-07 12:45:54 +03008296 bacpy(&ev->addr.bdaddr, bdaddr);
8297 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008298 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008299 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008300
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008301 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008302 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008303 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008304
Johan Hedberg1dc06092012-01-15 21:01:23 +02008305 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8306 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008307 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008308
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008309 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008310 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008311 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008312
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008313 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8314 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008315
Marcel Holtmann901801b2013-10-06 23:55:51 -07008316 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008317}
Johan Hedberga88a9652011-03-30 13:18:12 +03008318
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008319void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8320 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008321{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008322 struct mgmt_ev_device_found *ev;
8323 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8324 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008325
Johan Hedbergb644ba32012-01-17 21:48:47 +02008326 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008327
Johan Hedbergb644ba32012-01-17 21:48:47 +02008328 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008329
Johan Hedbergb644ba32012-01-17 21:48:47 +02008330 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008331 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008332 ev->rssi = rssi;
8333
8334 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008335 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008336
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008337 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008338
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008339 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008340}
Johan Hedberg314b2382011-04-27 10:29:57 -04008341
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008342void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008343{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008344 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008345
Andre Guedes343fb142011-11-22 17:14:19 -03008346 BT_DBG("%s discovering %u", hdev->name, discovering);
8347
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008348 memset(&ev, 0, sizeof(ev));
8349 ev.type = hdev->discovery.type;
8350 ev.discovering = discovering;
8351
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008352 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008353}
Antti Julku5e762442011-08-25 16:48:02 +03008354
Marcel Holtmann1904a852015-01-11 13:50:44 -08008355static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008356{
8357 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008358}
8359
8360void mgmt_reenable_advertising(struct hci_dev *hdev)
8361{
8362 struct hci_request req;
Florian Grandeleb6f95f2015-06-18 03:16:51 +02008363 u8 instance;
Marcel Holtmann5976e602013-10-06 04:08:14 -07008364
Arman Uguray24b4f382015-03-23 15:57:12 -07008365 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8366 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008367 return;
8368
Florian Grandeleb6f95f2015-06-18 03:16:51 +02008369 instance = get_current_adv_instance(hdev);
8370
Marcel Holtmann5976e602013-10-06 04:08:14 -07008371 hci_req_init(&req, hdev);
Florian Grandeleb6f95f2015-06-18 03:16:51 +02008372
8373 if (instance) {
8374 schedule_adv_instance(&req, instance, true);
8375 } else {
8376 update_adv_data(&req);
8377 update_scan_rsp_data(&req);
8378 enable_advertising(&req);
8379 }
8380
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008381 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008382}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008383
8384static struct hci_mgmt_chan chan = {
8385 .channel = HCI_CHANNEL_CONTROL,
8386 .handler_count = ARRAY_SIZE(mgmt_handlers),
8387 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008388 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008389};
8390
8391int mgmt_init(void)
8392{
8393 return hci_mgmt_chan_register(&chan);
8394}
8395
8396void mgmt_exit(void)
8397{
8398 hci_mgmt_chan_unregister(&chan);
8399}