blob: eca203e891d2080eff2478d8d96956d1bf068be4 [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,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200105};
106
107static const u16 mgmt_events[] = {
108 MGMT_EV_CONTROLLER_ERROR,
109 MGMT_EV_INDEX_ADDED,
110 MGMT_EV_INDEX_REMOVED,
111 MGMT_EV_NEW_SETTINGS,
112 MGMT_EV_CLASS_OF_DEV_CHANGED,
113 MGMT_EV_LOCAL_NAME_CHANGED,
114 MGMT_EV_NEW_LINK_KEY,
115 MGMT_EV_NEW_LONG_TERM_KEY,
116 MGMT_EV_DEVICE_CONNECTED,
117 MGMT_EV_DEVICE_DISCONNECTED,
118 MGMT_EV_CONNECT_FAILED,
119 MGMT_EV_PIN_CODE_REQUEST,
120 MGMT_EV_USER_CONFIRM_REQUEST,
121 MGMT_EV_USER_PASSKEY_REQUEST,
122 MGMT_EV_AUTH_FAILED,
123 MGMT_EV_DEVICE_FOUND,
124 MGMT_EV_DISCOVERING,
125 MGMT_EV_DEVICE_BLOCKED,
126 MGMT_EV_DEVICE_UNBLOCKED,
127 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300128 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800129 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700130 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200131 MGMT_EV_DEVICE_ADDED,
132 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300133 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200134 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd3896b2014-07-02 21:30:55 +0200135 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200136 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700137 MGMT_EV_EXT_INDEX_ADDED,
138 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700139 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Arman Uguray24b4f382015-03-23 15:57:12 -0700140 MGMT_EV_ADVERTISING_ADDED,
141 MGMT_EV_ADVERTISING_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200142};
143
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700144static const u16 mgmt_untrusted_commands[] = {
145 MGMT_OP_READ_INDEX_LIST,
146 MGMT_OP_READ_INFO,
147 MGMT_OP_READ_UNCONF_INDEX_LIST,
148 MGMT_OP_READ_CONFIG_INFO,
149 MGMT_OP_READ_EXT_INDEX_LIST,
150};
151
152static const u16 mgmt_untrusted_events[] = {
153 MGMT_EV_INDEX_ADDED,
154 MGMT_EV_INDEX_REMOVED,
155 MGMT_EV_NEW_SETTINGS,
156 MGMT_EV_CLASS_OF_DEV_CHANGED,
157 MGMT_EV_LOCAL_NAME_CHANGED,
158 MGMT_EV_UNCONF_INDEX_ADDED,
159 MGMT_EV_UNCONF_INDEX_REMOVED,
160 MGMT_EV_NEW_CONFIG_OPTIONS,
161 MGMT_EV_EXT_INDEX_ADDED,
162 MGMT_EV_EXT_INDEX_REMOVED,
163};
164
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800165#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200166
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200167#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
168 "\x00\x00\x00\x00\x00\x00\x00\x00"
169
Johan Hedbergca69b792011-11-11 18:10:00 +0200170/* HCI to MGMT error code conversion table */
171static u8 mgmt_status_table[] = {
172 MGMT_STATUS_SUCCESS,
173 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
174 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
175 MGMT_STATUS_FAILED, /* Hardware Failure */
176 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
177 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200178 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200179 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
180 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
181 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
182 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
183 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
184 MGMT_STATUS_BUSY, /* Command Disallowed */
185 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
186 MGMT_STATUS_REJECTED, /* Rejected Security */
187 MGMT_STATUS_REJECTED, /* Rejected Personal */
188 MGMT_STATUS_TIMEOUT, /* Host Timeout */
189 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
190 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
191 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
192 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
193 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
194 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
195 MGMT_STATUS_BUSY, /* Repeated Attempts */
196 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
197 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
198 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
199 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
200 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
201 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
202 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
203 MGMT_STATUS_FAILED, /* Unspecified Error */
204 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
205 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
206 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
207 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
208 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
209 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
210 MGMT_STATUS_FAILED, /* Unit Link Key Used */
211 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
212 MGMT_STATUS_TIMEOUT, /* Instant Passed */
213 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
214 MGMT_STATUS_FAILED, /* Transaction Collision */
215 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
216 MGMT_STATUS_REJECTED, /* QoS Rejected */
217 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
218 MGMT_STATUS_REJECTED, /* Insufficient Security */
219 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
220 MGMT_STATUS_BUSY, /* Role Switch Pending */
221 MGMT_STATUS_FAILED, /* Slot Violation */
222 MGMT_STATUS_FAILED, /* Role Switch Failed */
223 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
224 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
225 MGMT_STATUS_BUSY, /* Host Busy Pairing */
226 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
227 MGMT_STATUS_BUSY, /* Controller Busy */
228 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
229 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
230 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
231 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
232 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
233};
234
235static u8 mgmt_status(u8 hci_status)
236{
237 if (hci_status < ARRAY_SIZE(mgmt_status_table))
238 return mgmt_status_table[hci_status];
239
240 return MGMT_STATUS_FAILED;
241}
242
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700243static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
244 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700245{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700246 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
247 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700248}
249
Marcel Holtmann72000df2015-03-16 16:11:21 -0700250static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
251 u16 len, int flag, struct sock *skip_sk)
252{
253 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
254 flag, skip_sk);
255}
256
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700257static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
258 u16 len, struct sock *skip_sk)
259{
260 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
261 HCI_MGMT_GENERIC_EVENTS, skip_sk);
262}
263
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200264static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
265 struct sock *skip_sk)
266{
267 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700268 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200269}
270
Johan Hedberg85813a72015-10-21 18:02:59 +0300271static u8 le_addr_type(u8 mgmt_addr_type)
272{
273 if (mgmt_addr_type == BDADDR_LE_PUBLIC)
274 return ADDR_LE_DEV_PUBLIC;
275 else
276 return ADDR_LE_DEV_RANDOM;
277}
278
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300279static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
280 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200281{
282 struct mgmt_rp_read_version rp;
283
284 BT_DBG("sock %p", sk);
285
286 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700287 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200288
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200289 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
290 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200291}
292
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300293static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
294 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200295{
296 struct mgmt_rp_read_commands *rp;
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700297 u16 num_commands, num_events;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200298 size_t rp_size;
299 int i, err;
300
301 BT_DBG("sock %p", sk);
302
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700303 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
304 num_commands = ARRAY_SIZE(mgmt_commands);
305 num_events = ARRAY_SIZE(mgmt_events);
306 } else {
307 num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
308 num_events = ARRAY_SIZE(mgmt_untrusted_events);
309 }
310
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
312
313 rp = kmalloc(rp_size, GFP_KERNEL);
314 if (!rp)
315 return -ENOMEM;
316
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700317 rp->num_commands = cpu_to_le16(num_commands);
318 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200319
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700320 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
321 __le16 *opcode = rp->opcodes;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200322
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700323 for (i = 0; i < num_commands; i++, opcode++)
324 put_unaligned_le16(mgmt_commands[i], opcode);
325
326 for (i = 0; i < num_events; i++, opcode++)
327 put_unaligned_le16(mgmt_events[i], opcode);
328 } else {
329 __le16 *opcode = rp->opcodes;
330
331 for (i = 0; i < num_commands; i++, opcode++)
332 put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
333
334 for (i = 0; i < num_events; i++, opcode++)
335 put_unaligned_le16(mgmt_untrusted_events[i], opcode);
336 }
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200337
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200338 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
339 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200340 kfree(rp);
341
342 return err;
343}
344
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300345static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
346 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200347{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200348 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200349 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200350 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200351 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300352 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200353
354 BT_DBG("sock %p", sk);
355
356 read_lock(&hci_dev_list_lock);
357
358 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300359 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200360 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700361 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700362 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363 }
364
Johan Hedberga38528f2011-01-22 06:46:43 +0200365 rp_len = sizeof(*rp) + (2 * count);
366 rp = kmalloc(rp_len, GFP_ATOMIC);
367 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100368 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200369 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100370 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200371
Johan Hedberg476e44c2012-10-19 20:10:46 +0300372 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700374 if (hci_dev_test_flag(d, HCI_SETUP) ||
375 hci_dev_test_flag(d, HCI_CONFIG) ||
376 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200377 continue;
378
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200379 /* Devices marked as raw-only are neither configured
380 * nor unconfigured controllers.
381 */
382 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700383 continue;
384
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200385 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700386 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700387 rp->index[count++] = cpu_to_le16(d->id);
388 BT_DBG("Added hci%u", d->id);
389 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200390 }
391
Johan Hedberg476e44c2012-10-19 20:10:46 +0300392 rp->num_controllers = cpu_to_le16(count);
393 rp_len = sizeof(*rp) + (2 * count);
394
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200395 read_unlock(&hci_dev_list_lock);
396
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200397 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
398 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200399
Johan Hedberga38528f2011-01-22 06:46:43 +0200400 kfree(rp);
401
402 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200403}
404
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200405static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
406 void *data, u16 data_len)
407{
408 struct mgmt_rp_read_unconf_index_list *rp;
409 struct hci_dev *d;
410 size_t rp_len;
411 u16 count;
412 int err;
413
414 BT_DBG("sock %p", sk);
415
416 read_lock(&hci_dev_list_lock);
417
418 count = 0;
419 list_for_each_entry(d, &hci_dev_list, list) {
420 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700421 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200422 count++;
423 }
424
425 rp_len = sizeof(*rp) + (2 * count);
426 rp = kmalloc(rp_len, GFP_ATOMIC);
427 if (!rp) {
428 read_unlock(&hci_dev_list_lock);
429 return -ENOMEM;
430 }
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700434 if (hci_dev_test_flag(d, HCI_SETUP) ||
435 hci_dev_test_flag(d, HCI_CONFIG) ||
436 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200437 continue;
438
439 /* Devices marked as raw-only are neither configured
440 * nor unconfigured controllers.
441 */
442 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
443 continue;
444
445 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700446 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200447 rp->index[count++] = cpu_to_le16(d->id);
448 BT_DBG("Added hci%u", d->id);
449 }
450 }
451
452 rp->num_controllers = cpu_to_le16(count);
453 rp_len = sizeof(*rp) + (2 * count);
454
455 read_unlock(&hci_dev_list_lock);
456
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200457 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
458 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200459
460 kfree(rp);
461
462 return err;
463}
464
Marcel Holtmann96f14742015-03-14 19:27:57 -0700465static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
466 void *data, u16 data_len)
467{
468 struct mgmt_rp_read_ext_index_list *rp;
469 struct hci_dev *d;
470 size_t rp_len;
471 u16 count;
472 int err;
473
474 BT_DBG("sock %p", sk);
475
476 read_lock(&hci_dev_list_lock);
477
478 count = 0;
479 list_for_each_entry(d, &hci_dev_list, list) {
480 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
481 count++;
482 }
483
484 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
485 rp = kmalloc(rp_len, GFP_ATOMIC);
486 if (!rp) {
487 read_unlock(&hci_dev_list_lock);
488 return -ENOMEM;
489 }
490
491 count = 0;
492 list_for_each_entry(d, &hci_dev_list, list) {
493 if (hci_dev_test_flag(d, HCI_SETUP) ||
494 hci_dev_test_flag(d, HCI_CONFIG) ||
495 hci_dev_test_flag(d, HCI_USER_CHANNEL))
496 continue;
497
498 /* Devices marked as raw-only are neither configured
499 * nor unconfigured controllers.
500 */
501 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
502 continue;
503
504 if (d->dev_type == HCI_BREDR) {
505 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
506 rp->entry[count].type = 0x01;
507 else
508 rp->entry[count].type = 0x00;
509 } else if (d->dev_type == HCI_AMP) {
510 rp->entry[count].type = 0x02;
511 } else {
512 continue;
513 }
514
515 rp->entry[count].bus = d->bus;
516 rp->entry[count++].index = cpu_to_le16(d->id);
517 BT_DBG("Added hci%u", d->id);
518 }
519
520 rp->num_controllers = cpu_to_le16(count);
521 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
522
523 read_unlock(&hci_dev_list_lock);
524
525 /* If this command is called at least once, then all the
526 * default index and unconfigured index events are disabled
527 * and from now on only extended index events are used.
528 */
529 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
530 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
531 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
532
533 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
534 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
535
536 kfree(rp);
537
538 return err;
539}
540
Marcel Holtmanndbece372014-07-04 18:11:55 +0200541static bool is_configured(struct hci_dev *hdev)
542{
543 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700544 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200545 return false;
546
547 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
548 !bacmp(&hdev->public_addr, BDADDR_ANY))
549 return false;
550
551 return true;
552}
553
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200554static __le32 get_missing_options(struct hci_dev *hdev)
555{
556 u32 options = 0;
557
Marcel Holtmanndbece372014-07-04 18:11:55 +0200558 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700559 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200560 options |= MGMT_OPTION_EXTERNAL_CONFIG;
561
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200562 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
563 !bacmp(&hdev->public_addr, BDADDR_ANY))
564 options |= MGMT_OPTION_PUBLIC_ADDRESS;
565
566 return cpu_to_le32(options);
567}
568
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200569static int new_options(struct hci_dev *hdev, struct sock *skip)
570{
571 __le32 options = get_missing_options(hdev);
572
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700573 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
574 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200575}
576
Marcel Holtmanndbece372014-07-04 18:11:55 +0200577static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
578{
579 __le32 options = get_missing_options(hdev);
580
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200581 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
582 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200583}
584
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585static int read_config_info(struct sock *sk, struct hci_dev *hdev,
586 void *data, u16 data_len)
587{
588 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200589 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200590
591 BT_DBG("sock %p %s", sk, hdev->name);
592
593 hci_dev_lock(hdev);
594
595 memset(&rp, 0, sizeof(rp));
596 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200597
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200598 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
599 options |= MGMT_OPTION_EXTERNAL_CONFIG;
600
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200601 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200602 options |= MGMT_OPTION_PUBLIC_ADDRESS;
603
604 rp.supported_options = cpu_to_le32(options);
605 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200606
607 hci_dev_unlock(hdev);
608
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200609 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
610 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200611}
612
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200614{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200615 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200616
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300618 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800619 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300620 settings |= MGMT_SETTING_CONNECTABLE;
621 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200622
Andre Guedesed3fa312012-07-24 15:03:46 -0300623 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500624 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
625 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200626 settings |= MGMT_SETTING_BREDR;
627 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700628
629 if (lmp_ssp_capable(hdev)) {
630 settings |= MGMT_SETTING_SSP;
631 settings |= MGMT_SETTING_HS;
632 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800633
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800634 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800635 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700636 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100637
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300638 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200639 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300640 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300641 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200642 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800643 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300644 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200645
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200646 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
647 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200648 settings |= MGMT_SETTING_CONFIGURATION;
649
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200650 return settings;
651}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200652
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200653static u32 get_current_settings(struct hci_dev *hdev)
654{
655 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200656
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200657 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100658 settings |= MGMT_SETTING_POWERED;
659
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700660 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200661 settings |= MGMT_SETTING_CONNECTABLE;
662
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700663 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500664 settings |= MGMT_SETTING_FAST_CONNECTABLE;
665
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700666 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200667 settings |= MGMT_SETTING_DISCOVERABLE;
668
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700669 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300670 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700672 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200673 settings |= MGMT_SETTING_BREDR;
674
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700675 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200676 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200677
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700678 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200679 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200680
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700681 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200682 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200683
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700684 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200685 settings |= MGMT_SETTING_HS;
686
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700687 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300688 settings |= MGMT_SETTING_ADVERTISING;
689
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700690 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800691 settings |= MGMT_SETTING_SECURE_CONN;
692
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700693 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800694 settings |= MGMT_SETTING_DEBUG_KEYS;
695
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700696 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200697 settings |= MGMT_SETTING_PRIVACY;
698
Marcel Holtmann93690c22015-03-06 10:11:21 -0800699 /* The current setting for static address has two purposes. The
700 * first is to indicate if the static address will be used and
701 * the second is to indicate if it is actually set.
702 *
703 * This means if the static address is not configured, this flag
Marcel Holtmann08dc0e982015-03-25 18:32:13 -0700704 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 * address is actually used decides if the flag is set or not.
706 *
707 * For single mode LE only controllers and dual-mode controllers
708 * with BR/EDR disabled, the existence of the static address will
709 * be evaluated.
710 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700711 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700712 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800713 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
714 if (bacmp(&hdev->static_addr, BDADDR_ANY))
715 settings |= MGMT_SETTING_STATIC_ADDRESS;
716 }
717
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200718 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200719}
720
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300721#define PNP_INFO_SVCLASS_ID 0x1200
722
Johan Hedberg213202e2013-01-27 00:31:33 +0200723static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
724{
725 u8 *ptr = data, *uuids_start = NULL;
726 struct bt_uuid *uuid;
727
728 if (len < 4)
729 return ptr;
730
731 list_for_each_entry(uuid, &hdev->uuids, list) {
732 u16 uuid16;
733
734 if (uuid->size != 16)
735 continue;
736
737 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
738 if (uuid16 < 0x1100)
739 continue;
740
741 if (uuid16 == PNP_INFO_SVCLASS_ID)
742 continue;
743
744 if (!uuids_start) {
745 uuids_start = ptr;
746 uuids_start[0] = 1;
747 uuids_start[1] = EIR_UUID16_ALL;
748 ptr += 2;
749 }
750
751 /* Stop if not enough space to put next UUID */
752 if ((ptr - data) + sizeof(u16) > len) {
753 uuids_start[1] = EIR_UUID16_SOME;
754 break;
755 }
756
757 *ptr++ = (uuid16 & 0x00ff);
758 *ptr++ = (uuid16 & 0xff00) >> 8;
759 uuids_start[0] += sizeof(uuid16);
760 }
761
762 return ptr;
763}
764
Johan Hedbergcdf19632013-01-27 00:31:34 +0200765static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
766{
767 u8 *ptr = data, *uuids_start = NULL;
768 struct bt_uuid *uuid;
769
770 if (len < 6)
771 return ptr;
772
773 list_for_each_entry(uuid, &hdev->uuids, list) {
774 if (uuid->size != 32)
775 continue;
776
777 if (!uuids_start) {
778 uuids_start = ptr;
779 uuids_start[0] = 1;
780 uuids_start[1] = EIR_UUID32_ALL;
781 ptr += 2;
782 }
783
784 /* Stop if not enough space to put next UUID */
785 if ((ptr - data) + sizeof(u32) > len) {
786 uuids_start[1] = EIR_UUID32_SOME;
787 break;
788 }
789
790 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
791 ptr += sizeof(u32);
792 uuids_start[0] += sizeof(u32);
793 }
794
795 return ptr;
796}
797
Johan Hedbergc00d5752013-01-27 00:31:35 +0200798static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
799{
800 u8 *ptr = data, *uuids_start = NULL;
801 struct bt_uuid *uuid;
802
803 if (len < 18)
804 return ptr;
805
806 list_for_each_entry(uuid, &hdev->uuids, list) {
807 if (uuid->size != 128)
808 continue;
809
810 if (!uuids_start) {
811 uuids_start = ptr;
812 uuids_start[0] = 1;
813 uuids_start[1] = EIR_UUID128_ALL;
814 ptr += 2;
815 }
816
817 /* Stop if not enough space to put next UUID */
818 if ((ptr - data) + 16 > len) {
819 uuids_start[1] = EIR_UUID128_SOME;
820 break;
821 }
822
823 memcpy(ptr, uuid->uuid, 16);
824 ptr += 16;
825 uuids_start[0] += 16;
826 }
827
828 return ptr;
829}
830
Johan Hedberg333ae952015-03-17 13:48:47 +0200831static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
832{
833 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
834}
835
Johan Hedberg333ae952015-03-17 13:48:47 +0200836static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
837 struct hci_dev *hdev,
838 const void *data)
839{
840 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
841}
842
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200843static u8 get_current_adv_instance(struct hci_dev *hdev)
844{
845 /* The "Set Advertising" setting supersedes the "Add Advertising"
846 * setting. Here we set the advertising data based on which
847 * setting was set. When neither apply, default to the global settings,
848 * represented by instance "0".
849 */
850 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
851 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Florian Grandel3ff37e62015-06-18 03:16:39 +0200852 return hdev->cur_adv_instance;
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200853
854 return 0x00;
855}
856
Arman Uguray4117ed72015-03-23 15:57:14 -0700857static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700858{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700859 u8 ad_len = 0;
860 size_t name_len;
861
862 name_len = strlen(hdev->dev_name);
863 if (name_len > 0) {
864 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
865
866 if (name_len > max_len) {
867 name_len = max_len;
868 ptr[1] = EIR_NAME_SHORT;
869 } else
870 ptr[1] = EIR_NAME_COMPLETE;
871
872 ptr[0] = name_len + 1;
873
874 memcpy(ptr + 2, hdev->dev_name, name_len);
875
876 ad_len += (name_len + 2);
877 ptr += (name_len + 2);
878 }
879
880 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700881}
882
Florian Grandelca21fbe2015-06-18 03:16:43 +0200883static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
884 u8 *ptr)
Arman Uguray4117ed72015-03-23 15:57:14 -0700885{
Florian Grandelca21fbe2015-06-18 03:16:43 +0200886 struct adv_info *adv_instance;
887
888 adv_instance = hci_find_adv_instance(hdev, instance);
889 if (!adv_instance)
890 return 0;
891
Arman Uguray4117ed72015-03-23 15:57:14 -0700892 /* TODO: Set the appropriate entries based on advertising instance flags
893 * here once flags other than 0 are supported.
894 */
Florian Grandelca21fbe2015-06-18 03:16:43 +0200895 memcpy(ptr, adv_instance->scan_rsp_data,
896 adv_instance->scan_rsp_len);
Arman Uguray4117ed72015-03-23 15:57:14 -0700897
Florian Grandelca21fbe2015-06-18 03:16:43 +0200898 return adv_instance->scan_rsp_len;
Arman Uguray4117ed72015-03-23 15:57:14 -0700899}
900
Florian Grandelefae0022015-06-18 03:16:37 +0200901static void update_inst_scan_rsp_data(struct hci_request *req, u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700902{
903 struct hci_dev *hdev = req->hdev;
904 struct hci_cp_le_set_scan_rsp_data cp;
905 u8 len;
906
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700907 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700908 return;
909
910 memset(&cp, 0, sizeof(cp));
911
Arman Uguray4117ed72015-03-23 15:57:14 -0700912 if (instance)
Florian Grandelca21fbe2015-06-18 03:16:43 +0200913 len = create_instance_scan_rsp_data(hdev, instance, cp.data);
Arman Uguray4117ed72015-03-23 15:57:14 -0700914 else
915 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700916
Johan Hedbergeb438b52013-10-16 15:31:07 +0300917 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700918 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700919 return;
920
Johan Hedbergeb438b52013-10-16 15:31:07 +0300921 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
922 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700923
924 cp.length = len;
925
926 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
927}
928
Arman Uguray4117ed72015-03-23 15:57:14 -0700929static void update_scan_rsp_data(struct hci_request *req)
930{
Florian Grandelefae0022015-06-18 03:16:37 +0200931 update_inst_scan_rsp_data(req, get_current_adv_instance(req->hdev));
Arman Uguray4117ed72015-03-23 15:57:14 -0700932}
933
Johan Hedberg9a43e252013-10-20 19:00:07 +0300934static u8 get_adv_discov_flags(struct hci_dev *hdev)
935{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200936 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300937
938 /* If there's a pending mgmt command the flags will not yet have
939 * their final values, so check for this first.
940 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200941 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300942 if (cmd) {
943 struct mgmt_mode *cp = cmd->param;
944 if (cp->val == 0x01)
945 return LE_AD_GENERAL;
946 else if (cp->val == 0x02)
947 return LE_AD_LIMITED;
948 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700949 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300950 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700951 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300952 return LE_AD_GENERAL;
953 }
954
955 return 0;
956}
957
Arman Uguraye7a685d2015-03-25 18:53:40 -0700958static bool get_connectable(struct hci_dev *hdev)
959{
960 struct mgmt_pending_cmd *cmd;
961
962 /* If there's a pending mgmt command the flag will not yet have
963 * it's final value, so check for this first.
964 */
965 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
966 if (cmd) {
967 struct mgmt_mode *cp = cmd->param;
968
969 return cp->val;
970 }
971
972 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
973}
974
975static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
976{
977 u32 flags;
Florian Grandel411b4122015-06-18 03:16:40 +0200978 struct adv_info *adv_instance;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700979
Florian Grandelbea28e62015-06-18 03:16:41 +0200980 if (instance == 0x00) {
981 /* Instance 0 always manages the "Tx Power" and "Flags"
982 * fields
983 */
984 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700985
Florian Grandelbea28e62015-06-18 03:16:41 +0200986 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting
987 * corresponds to the "connectable" instance flag.
988 */
989 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
990 flags |= MGMT_ADV_FLAG_CONNECTABLE;
Florian Grandel411b4122015-06-18 03:16:40 +0200991
Florian Grandelbea28e62015-06-18 03:16:41 +0200992 return flags;
Florian Grandel411b4122015-06-18 03:16:40 +0200993 }
Arman Uguraye7a685d2015-03-25 18:53:40 -0700994
Florian Grandelbea28e62015-06-18 03:16:41 +0200995 adv_instance = hci_find_adv_instance(hdev, instance);
Arman Uguraye7a685d2015-03-25 18:53:40 -0700996
Florian Grandelbea28e62015-06-18 03:16:41 +0200997 /* Return 0 when we got an invalid instance identifier. */
998 if (!adv_instance)
999 return 0;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001000
Florian Grandelbea28e62015-06-18 03:16:41 +02001001 return adv_instance->flags;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001002}
1003
Florian Grandel7b683b72015-06-18 03:16:42 +02001004static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
Arman Ugurayc7d48832015-03-28 12:38:59 -07001005{
Florian Grandel7b683b72015-06-18 03:16:42 +02001006 u8 instance = get_current_adv_instance(hdev);
1007 struct adv_info *adv_instance;
1008
1009 /* Ignore instance 0 */
1010 if (instance == 0x00)
1011 return 0;
1012
1013 adv_instance = hci_find_adv_instance(hdev, instance);
1014 if (!adv_instance)
Arman Ugurayc7d48832015-03-28 12:38:59 -07001015 return 0;
1016
1017 /* TODO: Take into account the "appearance" and "local-name" flags here.
1018 * These are currently being ignored as they are not supported.
1019 */
Florian Grandel7b683b72015-06-18 03:16:42 +02001020 return adv_instance->scan_rsp_len;
Arman Ugurayc7d48832015-03-28 12:38:59 -07001021}
1022
Arman Ugurayfdf51782015-03-25 18:53:46 -07001023static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1024{
Florian Grandelf63ba242015-06-18 03:16:44 +02001025 struct adv_info *adv_instance = NULL;
Arman Ugurayfdf51782015-03-25 18:53:46 -07001026 u8 ad_len = 0, flags = 0;
Florian Grandelf63ba242015-06-18 03:16:44 +02001027 u32 instance_flags;
1028
1029 /* Return 0 when the current instance identifier is invalid. */
1030 if (instance) {
1031 adv_instance = hci_find_adv_instance(hdev, instance);
1032 if (!adv_instance)
1033 return 0;
1034 }
1035
1036 instance_flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfdf51782015-03-25 18:53:46 -07001037
1038 /* The Add Advertising command allows userspace to set both the general
1039 * and limited discoverable flags.
1040 */
1041 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1042 flags |= LE_AD_GENERAL;
1043
1044 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1045 flags |= LE_AD_LIMITED;
1046
1047 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1048 /* If a discovery flag wasn't provided, simply use the global
1049 * settings.
1050 */
1051 if (!flags)
1052 flags |= get_adv_discov_flags(hdev);
1053
1054 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1055 flags |= LE_AD_NO_BREDR;
1056
1057 /* If flags would still be empty, then there is no need to
1058 * include the "Flags" AD field".
1059 */
1060 if (flags) {
1061 ptr[0] = 0x02;
1062 ptr[1] = EIR_FLAGS;
1063 ptr[2] = flags;
1064
1065 ad_len += 3;
1066 ptr += 3;
1067 }
1068 }
1069
Florian Grandelf63ba242015-06-18 03:16:44 +02001070 if (adv_instance) {
1071 memcpy(ptr, adv_instance->adv_data,
1072 adv_instance->adv_data_len);
1073 ad_len += adv_instance->adv_data_len;
1074 ptr += adv_instance->adv_data_len;
Marcel Holtmann38c8af62015-04-03 13:23:12 -07001075 }
1076
Arman Ugurayfdf51782015-03-25 18:53:46 -07001077 /* Provide Tx Power only if we can provide a valid value for it */
1078 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1079 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1080 ptr[0] = 0x02;
1081 ptr[1] = EIR_TX_POWER;
1082 ptr[2] = (u8)hdev->adv_tx_power;
1083
1084 ad_len += 3;
1085 ptr += 3;
1086 }
1087
Arman Ugurayfdf51782015-03-25 18:53:46 -07001088 return ad_len;
1089}
1090
Florian Grandelefae0022015-06-18 03:16:37 +02001091static void update_inst_adv_data(struct hci_request *req, u8 instance)
Arman Ugurayfdf51782015-03-25 18:53:46 -07001092{
1093 struct hci_dev *hdev = req->hdev;
1094 struct hci_cp_le_set_adv_data cp;
1095 u8 len;
1096
1097 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1098 return;
1099
1100 memset(&cp, 0, sizeof(cp));
1101
1102 len = create_instance_adv_data(hdev, instance, cp.data);
1103
1104 /* There's nothing to do if the data hasn't changed */
1105 if (hdev->adv_data_len == len &&
1106 memcmp(cp.data, hdev->adv_data, len) == 0)
1107 return;
1108
1109 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1110 hdev->adv_data_len = len;
1111
1112 cp.length = len;
1113
1114 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1115}
1116
Arman Uguraye7a685d2015-03-25 18:53:40 -07001117static void update_adv_data(struct hci_request *req)
1118{
Florian Grandelefae0022015-06-18 03:16:37 +02001119 update_inst_adv_data(req, get_current_adv_instance(req->hdev));
Arman Uguray24b4f382015-03-23 15:57:12 -07001120}
1121
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001122int mgmt_update_adv_data(struct hci_dev *hdev)
1123{
1124 struct hci_request req;
1125
1126 hci_req_init(&req, hdev);
1127 update_adv_data(&req);
1128
1129 return hci_req_run(&req, NULL);
1130}
1131
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001132static void create_eir(struct hci_dev *hdev, u8 *data)
1133{
1134 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001135 size_t name_len;
1136
1137 name_len = strlen(hdev->dev_name);
1138
1139 if (name_len > 0) {
1140 /* EIR Data type */
1141 if (name_len > 48) {
1142 name_len = 48;
1143 ptr[1] = EIR_NAME_SHORT;
1144 } else
1145 ptr[1] = EIR_NAME_COMPLETE;
1146
1147 /* EIR Data length */
1148 ptr[0] = name_len + 1;
1149
1150 memcpy(ptr + 2, hdev->dev_name, name_len);
1151
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001152 ptr += (name_len + 2);
1153 }
1154
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001155 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001156 ptr[0] = 2;
1157 ptr[1] = EIR_TX_POWER;
1158 ptr[2] = (u8) hdev->inq_tx_power;
1159
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001160 ptr += 3;
1161 }
1162
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001163 if (hdev->devid_source > 0) {
1164 ptr[0] = 9;
1165 ptr[1] = EIR_DEVICE_ID;
1166
1167 put_unaligned_le16(hdev->devid_source, ptr + 2);
1168 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1169 put_unaligned_le16(hdev->devid_product, ptr + 6);
1170 put_unaligned_le16(hdev->devid_version, ptr + 8);
1171
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001172 ptr += 10;
1173 }
1174
Johan Hedberg213202e2013-01-27 00:31:33 +02001175 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001176 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001177 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001178}
1179
Johan Hedberg890ea892013-03-15 17:06:52 -05001180static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001181{
Johan Hedberg890ea892013-03-15 17:06:52 -05001182 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001183 struct hci_cp_write_eir cp;
1184
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001185 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001186 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001187
Johan Hedberg976eb202012-10-24 21:12:01 +03001188 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001189 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001190
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001191 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001192 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001193
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001194 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001195 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001196
1197 memset(&cp, 0, sizeof(cp));
1198
1199 create_eir(hdev, cp.data);
1200
1201 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001202 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001203
1204 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1205
Johan Hedberg890ea892013-03-15 17:06:52 -05001206 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001207}
1208
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001209static u8 get_service_classes(struct hci_dev *hdev)
1210{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001211 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001212 u8 val = 0;
1213
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001214 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001215 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001216
1217 return val;
1218}
1219
Johan Hedberg890ea892013-03-15 17:06:52 -05001220static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001221{
Johan Hedberg890ea892013-03-15 17:06:52 -05001222 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001223 u8 cod[3];
1224
1225 BT_DBG("%s", hdev->name);
1226
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001227 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001228 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001229
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001230 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001231 return;
1232
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001233 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001234 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001235
1236 cod[0] = hdev->minor_class;
1237 cod[1] = hdev->major_class;
1238 cod[2] = get_service_classes(hdev);
1239
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001240 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001241 cod[1] |= 0x20;
1242
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001243 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001244 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001245
Johan Hedberg890ea892013-03-15 17:06:52 -05001246 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001247}
1248
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001249static void disable_advertising(struct hci_request *req)
1250{
1251 u8 enable = 0x00;
1252
1253 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1254}
1255
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001256static void enable_advertising(struct hci_request *req)
1257{
1258 struct hci_dev *hdev = req->hdev;
1259 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001260 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001261 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001262 u8 instance;
1263 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001264
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001265 if (hci_conn_num(hdev, LE_LINK) > 0)
1266 return;
1267
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001268 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001269 disable_advertising(req);
1270
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001271 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001272 * hci_update_random_address knows that it's safe to go ahead
1273 * and write a new random address. The flag will be set back on
1274 * as soon as the SET_ADV_ENABLE HCI command completes.
1275 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001276 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001277
Arman Uguraye7a685d2015-03-25 18:53:40 -07001278 instance = get_current_adv_instance(hdev);
1279 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001280
1281 /* If the "connectable" instance flag was not set, then choose between
1282 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1283 */
1284 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1285 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001286
Johan Hedberga4858cb2014-02-25 19:56:31 +02001287 /* Set require_privacy to true only when non-connectable
1288 * advertising is used. In that case it is fine to use a
1289 * non-resolvable private address.
1290 */
1291 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001292 return;
1293
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001294 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001295 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1296 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001297
1298 if (connectable)
1299 cp.type = LE_ADV_IND;
Florian Grandel7b683b72015-06-18 03:16:42 +02001300 else if (get_cur_adv_instance_scan_rsp_len(hdev))
Arman Ugurayc7d48832015-03-28 12:38:59 -07001301 cp.type = LE_ADV_SCAN_IND;
1302 else
1303 cp.type = LE_ADV_NONCONN_IND;
1304
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001305 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001306 cp.channel_map = hdev->le_adv_channel_map;
1307
1308 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1309
1310 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1311}
1312
Johan Hedberg7d785252011-12-15 00:47:39 +02001313static void service_cache_off(struct work_struct *work)
1314{
1315 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001316 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001317 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001318
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001319 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001320 return;
1321
Johan Hedberg890ea892013-03-15 17:06:52 -05001322 hci_req_init(&req, hdev);
1323
Johan Hedberg7d785252011-12-15 00:47:39 +02001324 hci_dev_lock(hdev);
1325
Johan Hedberg890ea892013-03-15 17:06:52 -05001326 update_eir(&req);
1327 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001328
1329 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001330
1331 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001332}
1333
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001334static void rpa_expired(struct work_struct *work)
1335{
1336 struct hci_dev *hdev = container_of(work, struct hci_dev,
1337 rpa_expired.work);
1338 struct hci_request req;
1339
1340 BT_DBG("");
1341
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001342 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001343
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001344 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001345 return;
1346
1347 /* The generation of a new RPA and programming it into the
1348 * controller happens in the enable_advertising() function.
1349 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001350 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001351 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001352 hci_req_run(&req, NULL);
1353}
1354
Johan Hedberg6a919082012-02-28 06:17:26 +02001355static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001356{
Marcel Holtmann238be782015-03-13 02:11:06 -07001357 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001358 return;
1359
Johan Hedberg4f87da82012-03-02 19:55:56 +02001360 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001361 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001362
Johan Hedberg4f87da82012-03-02 19:55:56 +02001363 /* Non-mgmt controlled devices get this bit set
1364 * implicitly so that pairing works for them, however
1365 * for mgmt we require user-space to explicitly enable
1366 * it
1367 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001368 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001369}
1370
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001371static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001372 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001373{
1374 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001375
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001376 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg03811012010-12-08 00:21:06 +02001380 memset(&rp, 0, sizeof(rp));
1381
Johan Hedberg03811012010-12-08 00:21:06 +02001382 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001383
1384 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001385 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001386
1387 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1388 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1389
1390 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001391
1392 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001393 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001394
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001395 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001396
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001397 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1398 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001399}
1400
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001401static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001402{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001403 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001404
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001405 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1406 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001407}
1408
Marcel Holtmann1904a852015-01-11 13:50:44 -08001409static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410{
1411 BT_DBG("%s status 0x%02x", hdev->name, status);
1412
Johan Hedberga3172b72014-02-28 09:33:44 +02001413 if (hci_conn_count(hdev) == 0) {
1414 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001415 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001416 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001417}
1418
Arman Uguray912098a2015-03-23 15:57:15 -07001419static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1420 u8 instance)
1421{
1422 struct mgmt_ev_advertising_added ev;
1423
1424 ev.instance = instance;
1425
1426 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1427}
1428
1429static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1430 u8 instance)
1431{
1432 struct mgmt_ev_advertising_removed ev;
1433
1434 ev.instance = instance;
1435
1436 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1437}
1438
Florian Grandel7816b822015-06-18 03:16:45 +02001439static int schedule_adv_instance(struct hci_request *req, u8 instance,
1440 bool force) {
1441 struct hci_dev *hdev = req->hdev;
1442 struct adv_info *adv_instance = NULL;
1443 u16 timeout;
1444
1445 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
1446 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1447 return -EPERM;
1448
1449 if (hdev->adv_instance_timeout)
1450 return -EBUSY;
1451
1452 adv_instance = hci_find_adv_instance(hdev, instance);
1453 if (!adv_instance)
1454 return -ENOENT;
1455
1456 /* A zero timeout means unlimited advertising. As long as there is
1457 * only one instance, duration should be ignored. We still set a timeout
1458 * in case further instances are being added later on.
1459 *
1460 * If the remaining lifetime of the instance is more than the duration
1461 * then the timeout corresponds to the duration, otherwise it will be
1462 * reduced to the remaining instance lifetime.
1463 */
1464 if (adv_instance->timeout == 0 ||
1465 adv_instance->duration <= adv_instance->remaining_time)
1466 timeout = adv_instance->duration;
1467 else
1468 timeout = adv_instance->remaining_time;
1469
1470 /* The remaining time is being reduced unless the instance is being
1471 * advertised without time limit.
1472 */
1473 if (adv_instance->timeout)
1474 adv_instance->remaining_time =
1475 adv_instance->remaining_time - timeout;
1476
1477 hdev->adv_instance_timeout = timeout;
1478 queue_delayed_work(hdev->workqueue,
1479 &hdev->adv_instance_expire,
1480 msecs_to_jiffies(timeout * 1000));
1481
1482 /* If we're just re-scheduling the same instance again then do not
1483 * execute any HCI commands. This happens when a single instance is
1484 * being advertised.
1485 */
1486 if (!force && hdev->cur_adv_instance == instance &&
1487 hci_dev_test_flag(hdev, HCI_LE_ADV))
1488 return 0;
1489
1490 hdev->cur_adv_instance = instance;
1491 update_adv_data(req);
1492 update_scan_rsp_data(req);
1493 enable_advertising(req);
1494
1495 return 0;
1496}
1497
1498static void cancel_adv_timeout(struct hci_dev *hdev)
1499{
1500 if (hdev->adv_instance_timeout) {
1501 hdev->adv_instance_timeout = 0;
1502 cancel_delayed_work(&hdev->adv_instance_expire);
1503 }
1504}
1505
Florian Grandel847818d2015-06-18 03:16:46 +02001506/* For a single instance:
1507 * - force == true: The instance will be removed even when its remaining
1508 * lifetime is not zero.
1509 * - force == false: the instance will be deactivated but kept stored unless
1510 * the remaining lifetime is zero.
1511 *
1512 * For instance == 0x00:
1513 * - force == true: All instances will be removed regardless of their timeout
1514 * setting.
1515 * - force == false: Only instances that have a timeout will be removed.
1516 */
1517static void clear_adv_instance(struct hci_dev *hdev, struct hci_request *req,
1518 u8 instance, bool force)
Arman Uguray912098a2015-03-23 15:57:15 -07001519{
Florian Grandel847818d2015-06-18 03:16:46 +02001520 struct adv_info *adv_instance, *n, *next_instance = NULL;
1521 int err;
1522 u8 rem_inst;
Arman Uguray912098a2015-03-23 15:57:15 -07001523
Florian Grandel847818d2015-06-18 03:16:46 +02001524 /* Cancel any timeout concerning the removed instance(s). */
1525 if (!instance || hdev->cur_adv_instance == instance)
1526 cancel_adv_timeout(hdev);
Arman Uguray912098a2015-03-23 15:57:15 -07001527
Florian Grandel847818d2015-06-18 03:16:46 +02001528 /* Get the next instance to advertise BEFORE we remove
1529 * the current one. This can be the same instance again
1530 * if there is only one instance.
1531 */
1532 if (instance && hdev->cur_adv_instance == instance)
1533 next_instance = hci_get_next_instance(hdev, instance);
Arman Uguray912098a2015-03-23 15:57:15 -07001534
Florian Grandel847818d2015-06-18 03:16:46 +02001535 if (instance == 0x00) {
1536 list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances,
1537 list) {
1538 if (!(force || adv_instance->timeout))
1539 continue;
Arman Uguray912098a2015-03-23 15:57:15 -07001540
Florian Grandel847818d2015-06-18 03:16:46 +02001541 rem_inst = adv_instance->instance;
1542 err = hci_remove_adv_instance(hdev, rem_inst);
1543 if (!err)
1544 advertising_removed(NULL, hdev, rem_inst);
1545 }
1546 hdev->cur_adv_instance = 0x00;
1547 } else {
1548 adv_instance = hci_find_adv_instance(hdev, instance);
1549
1550 if (force || (adv_instance && adv_instance->timeout &&
1551 !adv_instance->remaining_time)) {
1552 /* Don't advertise a removed instance. */
1553 if (next_instance &&
1554 next_instance->instance == instance)
1555 next_instance = NULL;
1556
1557 err = hci_remove_adv_instance(hdev, instance);
1558 if (!err)
1559 advertising_removed(NULL, hdev, instance);
1560 }
1561 }
1562
1563 if (list_empty(&hdev->adv_instances)) {
1564 hdev->cur_adv_instance = 0x00;
1565 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1566 }
1567
1568 if (!req || !hdev_is_powered(hdev) ||
Arman Uguray912098a2015-03-23 15:57:15 -07001569 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1570 return;
1571
Florian Grandel847818d2015-06-18 03:16:46 +02001572 if (next_instance)
1573 schedule_adv_instance(req, next_instance->instance, false);
Arman Uguray912098a2015-03-23 15:57:15 -07001574}
1575
Johan Hedberg8b064a32014-02-24 14:52:22 +02001576static int clean_up_hci_state(struct hci_dev *hdev)
1577{
1578 struct hci_request req;
1579 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001580 bool discov_stopped;
1581 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001582
1583 hci_req_init(&req, hdev);
1584
1585 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1586 test_bit(HCI_PSCAN, &hdev->flags)) {
1587 u8 scan = 0x00;
1588 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1589 }
1590
Florian Grandel847818d2015-06-18 03:16:46 +02001591 clear_adv_instance(hdev, NULL, 0x00, false);
Arman Uguray912098a2015-03-23 15:57:15 -07001592
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001593 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001594 disable_advertising(&req);
1595
Johan Hedberg2154d3f2015-11-11 08:30:45 +02001596 discov_stopped = hci_req_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001597
1598 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
Johan Hedberg89e0ccc2015-10-22 10:49:38 +03001599 /* 0x15 == Terminated due to Power Off */
1600 __hci_abort_conn(&req, conn, 0x15);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001601 }
1602
Johan Hedberg23a48092014-07-08 16:05:06 +03001603 err = hci_req_run(&req, clean_up_hci_complete);
1604 if (!err && discov_stopped)
1605 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1606
1607 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001608}
1609
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001610static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001611 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001612{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001613 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001614 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001615 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001616
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001617 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001618
Johan Hedberga7e80f22013-01-09 16:05:19 +02001619 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001620 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1621 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001622
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001623 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001624
Johan Hedberg333ae952015-03-17 13:48:47 +02001625 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001626 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1627 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001628 goto failed;
1629 }
1630
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001631 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001632 cancel_delayed_work(&hdev->power_off);
1633
1634 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001635 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1636 data, len);
1637 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001638 goto failed;
1639 }
1640 }
1641
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001642 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001643 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001644 goto failed;
1645 }
1646
Johan Hedberg03811012010-12-08 00:21:06 +02001647 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1648 if (!cmd) {
1649 err = -ENOMEM;
1650 goto failed;
1651 }
1652
Johan Hedberg8b064a32014-02-24 14:52:22 +02001653 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001654 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001655 err = 0;
1656 } else {
1657 /* Disconnect connections, stop scans, etc */
1658 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001659 if (!err)
1660 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1661 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001662
Johan Hedberg8b064a32014-02-24 14:52:22 +02001663 /* ENODATA means there were no HCI commands queued */
1664 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001665 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001666 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1667 err = 0;
1668 }
1669 }
Johan Hedberg03811012010-12-08 00:21:06 +02001670
1671failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001672 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001673 return err;
1674}
1675
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001676static int new_settings(struct hci_dev *hdev, struct sock *skip)
1677{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001678 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001679
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001680 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1681 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001682}
1683
Johan Hedberg91a668b2014-07-09 13:28:26 +03001684int mgmt_new_settings(struct hci_dev *hdev)
1685{
1686 return new_settings(hdev, NULL);
1687}
1688
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001689struct cmd_lookup {
1690 struct sock *sk;
1691 struct hci_dev *hdev;
1692 u8 mgmt_status;
1693};
1694
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001695static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001696{
1697 struct cmd_lookup *match = data;
1698
1699 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1700
1701 list_del(&cmd->list);
1702
1703 if (match->sk == NULL) {
1704 match->sk = cmd->sk;
1705 sock_hold(match->sk);
1706 }
1707
1708 mgmt_pending_free(cmd);
1709}
1710
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001711static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001712{
1713 u8 *status = data;
1714
Johan Hedberga69e8372015-03-06 21:08:53 +02001715 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001716 mgmt_pending_remove(cmd);
1717}
1718
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001719static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001720{
1721 if (cmd->cmd_complete) {
1722 u8 *status = data;
1723
1724 cmd->cmd_complete(cmd, *status);
1725 mgmt_pending_remove(cmd);
1726
1727 return;
1728 }
1729
1730 cmd_status_rsp(cmd, data);
1731}
1732
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001733static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001734{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001735 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1736 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001737}
1738
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001739static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001740{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001741 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1742 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001743}
1744
Johan Hedberge6fe7982013-10-02 15:45:22 +03001745static u8 mgmt_bredr_support(struct hci_dev *hdev)
1746{
1747 if (!lmp_bredr_capable(hdev))
1748 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001749 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001750 return MGMT_STATUS_REJECTED;
1751 else
1752 return MGMT_STATUS_SUCCESS;
1753}
1754
1755static u8 mgmt_le_support(struct hci_dev *hdev)
1756{
1757 if (!lmp_le_capable(hdev))
1758 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001759 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001760 return MGMT_STATUS_REJECTED;
1761 else
1762 return MGMT_STATUS_SUCCESS;
1763}
1764
Marcel Holtmann1904a852015-01-11 13:50:44 -08001765static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1766 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001767{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001768 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001769 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001770 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001771 bool changed;
1772
1773 BT_DBG("status 0x%02x", status);
1774
1775 hci_dev_lock(hdev);
1776
Johan Hedberg333ae952015-03-17 13:48:47 +02001777 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001778 if (!cmd)
1779 goto unlock;
1780
1781 if (status) {
1782 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001783 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001784 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001785 goto remove_cmd;
1786 }
1787
1788 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001789 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001790 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001791
1792 if (hdev->discov_timeout > 0) {
1793 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1794 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1795 to);
1796 }
1797 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001798 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001799 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001800
1801 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1802
1803 if (changed)
1804 new_settings(hdev, cmd->sk);
1805
Marcel Holtmann970ba522013-10-15 06:33:57 -07001806 /* When the discoverable mode gets changed, make sure
1807 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001808 * bit correctly set. Also update page scan based on whitelist
1809 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001810 */
1811 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001812 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001813 update_class(&req);
1814 hci_req_run(&req, NULL);
1815
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001816remove_cmd:
1817 mgmt_pending_remove(cmd);
1818
1819unlock:
1820 hci_dev_unlock(hdev);
1821}
1822
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001823static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001824 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001825{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001826 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001827 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001828 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001829 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001830 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001831 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001832
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001833 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001834
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001835 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1836 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001837 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1838 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001839
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001840 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001841 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1842 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001843
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001844 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001845
1846 /* Disabling discoverable requires that no timeout is set,
1847 * and enabling limited discoverable requires a timeout.
1848 */
1849 if ((cp->val == 0x00 && timeout > 0) ||
1850 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001851 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1852 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001853
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001854 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001855
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001856 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001857 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1858 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001859 goto failed;
1860 }
1861
Johan Hedberg333ae952015-03-17 13:48:47 +02001862 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1863 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001864 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1865 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001866 goto failed;
1867 }
1868
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001869 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001870 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1871 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001872 goto failed;
1873 }
1874
1875 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001876 bool changed = false;
1877
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001878 /* Setting limited discoverable when powered off is
1879 * not a valid operation since it requires a timeout
1880 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1881 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001882 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001883 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001884 changed = true;
1885 }
1886
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001887 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001888 if (err < 0)
1889 goto failed;
1890
1891 if (changed)
1892 err = new_settings(hdev, sk);
1893
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001894 goto failed;
1895 }
1896
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001897 /* If the current mode is the same, then just update the timeout
1898 * value with the new value. And if only the timeout gets updated,
1899 * then no need for any HCI transactions.
1900 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001901 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1902 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1903 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001904 cancel_delayed_work(&hdev->discov_off);
1905 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001906
Marcel Holtmann36261542013-10-15 08:28:51 -07001907 if (cp->val && hdev->discov_timeout > 0) {
1908 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001909 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001910 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001911 }
1912
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001913 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001914 goto failed;
1915 }
1916
1917 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1918 if (!cmd) {
1919 err = -ENOMEM;
1920 goto failed;
1921 }
1922
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001923 /* Cancel any potential discoverable timeout that might be
1924 * still active and store new timeout value. The arming of
1925 * the timeout happens in the complete handler.
1926 */
1927 cancel_delayed_work(&hdev->discov_off);
1928 hdev->discov_timeout = timeout;
1929
Johan Hedbergb456f872013-10-19 23:38:22 +03001930 /* Limited discoverable mode */
1931 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001932 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001933 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001934 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001935
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001936 hci_req_init(&req, hdev);
1937
Johan Hedberg9a43e252013-10-20 19:00:07 +03001938 /* The procedure for LE-only controllers is much simpler - just
1939 * update the advertising data.
1940 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001941 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001942 goto update_ad;
1943
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001944 scan = SCAN_PAGE;
1945
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001946 if (cp->val) {
1947 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001948
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001949 if (cp->val == 0x02) {
1950 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001951 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001952 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1953 hci_cp.iac_lap[1] = 0x8b;
1954 hci_cp.iac_lap[2] = 0x9e;
1955 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1956 hci_cp.iac_lap[4] = 0x8b;
1957 hci_cp.iac_lap[5] = 0x9e;
1958 } else {
1959 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001960 hci_cp.num_iac = 1;
1961 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1962 hci_cp.iac_lap[1] = 0x8b;
1963 hci_cp.iac_lap[2] = 0x9e;
1964 }
1965
1966 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1967 (hci_cp.num_iac * 3) + 1, &hci_cp);
1968
1969 scan |= SCAN_INQUIRY;
1970 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001971 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001972 }
1973
1974 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001975
Johan Hedberg9a43e252013-10-20 19:00:07 +03001976update_ad:
1977 update_adv_data(&req);
1978
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001979 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001980 if (err < 0)
1981 mgmt_pending_remove(cmd);
1982
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001983failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001984 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001985 return err;
1986}
1987
Johan Hedberg406d7802013-03-15 17:07:09 -05001988static void write_fast_connectable(struct hci_request *req, bool enable)
1989{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001990 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001991 struct hci_cp_write_page_scan_activity acp;
1992 u8 type;
1993
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001994 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001995 return;
1996
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001997 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1998 return;
1999
Johan Hedberg406d7802013-03-15 17:07:09 -05002000 if (enable) {
2001 type = PAGE_SCAN_TYPE_INTERLACED;
2002
2003 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002004 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05002005 } else {
2006 type = PAGE_SCAN_TYPE_STANDARD; /* default */
2007
2008 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002009 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05002010 }
2011
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002012 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05002013
Johan Hedbergbd98b992013-03-15 17:07:13 -05002014 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
2015 __cpu_to_le16(hdev->page_scan_window) != acp.window)
2016 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
2017 sizeof(acp), &acp);
2018
2019 if (hdev->page_scan_type != type)
2020 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05002021}
2022
Marcel Holtmann1904a852015-01-11 13:50:44 -08002023static void set_connectable_complete(struct hci_dev *hdev, u8 status,
2024 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05002025{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002026 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002027 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002028 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002029
2030 BT_DBG("status 0x%02x", status);
2031
2032 hci_dev_lock(hdev);
2033
Johan Hedberg333ae952015-03-17 13:48:47 +02002034 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05002035 if (!cmd)
2036 goto unlock;
2037
Johan Hedberg37438c12013-10-14 16:20:05 +03002038 if (status) {
2039 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02002040 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03002041 goto remove_cmd;
2042 }
2043
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002044 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002045 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002046 conn_changed = !hci_dev_test_and_set_flag(hdev,
2047 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002048 discov_changed = false;
2049 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002050 conn_changed = hci_dev_test_and_clear_flag(hdev,
2051 HCI_CONNECTABLE);
2052 discov_changed = hci_dev_test_and_clear_flag(hdev,
2053 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002054 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002055
Johan Hedberg2b76f452013-03-15 17:07:04 -05002056 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
2057
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002058 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002059 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002060 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002061 if (discov_changed)
2062 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03002063 hci_update_background_scan(hdev);
2064 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002065
Johan Hedberg37438c12013-10-14 16:20:05 +03002066remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002067 mgmt_pending_remove(cmd);
2068
2069unlock:
2070 hci_dev_unlock(hdev);
2071}
2072
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002073static int set_connectable_update_settings(struct hci_dev *hdev,
2074 struct sock *sk, u8 val)
2075{
2076 bool changed = false;
2077 int err;
2078
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002079 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002080 changed = true;
2081
2082 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002083 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002084 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002085 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2086 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002087 }
2088
2089 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2090 if (err < 0)
2091 return err;
2092
Johan Hedberg562064e2014-07-08 16:35:34 +03002093 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002094 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002095 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002096 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002097 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002098
2099 return 0;
2100}
2101
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002102static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002103 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002104{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002105 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002106 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002107 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002108 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002109 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002110
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002111 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002112
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002113 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2114 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002115 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2116 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002117
Johan Hedberga7e80f22013-01-09 16:05:19 +02002118 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002119 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2120 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002121
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002122 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002123
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002124 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002125 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002126 goto failed;
2127 }
2128
Johan Hedberg333ae952015-03-17 13:48:47 +02002129 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2130 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002131 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2132 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002133 goto failed;
2134 }
2135
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002136 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2137 if (!cmd) {
2138 err = -ENOMEM;
2139 goto failed;
2140 }
2141
Johan Hedberg2b76f452013-03-15 17:07:04 -05002142 hci_req_init(&req, hdev);
2143
Johan Hedberg9a43e252013-10-20 19:00:07 +03002144 /* If BR/EDR is not enabled and we disable advertising as a
2145 * by-product of disabling connectable, we need to update the
2146 * advertising flags.
2147 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002148 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002149 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002150 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2151 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002152 }
2153 update_adv_data(&req);
2154 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002155 if (cp->val) {
2156 scan = SCAN_PAGE;
2157 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002158 /* If we don't have any whitelist entries just
2159 * disable all scanning. If there are entries
2160 * and we had both page and inquiry scanning
2161 * enabled then fall back to only page scanning.
2162 * Otherwise no changes are needed.
2163 */
2164 if (list_empty(&hdev->whitelist))
2165 scan = SCAN_DISABLED;
2166 else if (test_bit(HCI_ISCAN, &hdev->flags))
2167 scan = SCAN_PAGE;
2168 else
2169 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002170
2171 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002172 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002173 cancel_delayed_work(&hdev->discov_off);
2174 }
2175
2176 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2177 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002178
Johan Hedberg3bd27242014-07-28 20:53:58 +03002179no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002180 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002181 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2182 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002183 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002184
Johan Hedberg2b76f452013-03-15 17:07:04 -05002185 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002186 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002187 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002188 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002189 err = set_connectable_update_settings(hdev, sk,
2190 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002191 goto failed;
2192 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002193
2194failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002195 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002196 return err;
2197}
2198
Johan Hedbergb2939472014-07-30 09:22:23 +03002199static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002200 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002201{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002202 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002203 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002204 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002205
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002206 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002207
Johan Hedberga7e80f22013-01-09 16:05:19 +02002208 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002209 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2210 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002211
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002212 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002213
2214 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002215 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002216 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002217 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002218
Johan Hedbergb2939472014-07-30 09:22:23 +03002219 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002220 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002221 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002222
Marcel Holtmann55594352013-10-06 16:11:57 -07002223 if (changed)
2224 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002225
Marcel Holtmann55594352013-10-06 16:11:57 -07002226unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002227 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002228 return err;
2229}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002230
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002231static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2232 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002233{
2234 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002235 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002236 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002237 int err;
2238
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002239 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002240
Johan Hedberge6fe7982013-10-02 15:45:22 +03002241 status = mgmt_bredr_support(hdev);
2242 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002243 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2244 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002245
Johan Hedberga7e80f22013-01-09 16:05:19 +02002246 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002247 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2248 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002249
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002250 hci_dev_lock(hdev);
2251
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002252 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002253 bool changed = false;
2254
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002255 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002256 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002257 changed = true;
2258 }
2259
2260 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2261 if (err < 0)
2262 goto failed;
2263
2264 if (changed)
2265 err = new_settings(hdev, sk);
2266
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002267 goto failed;
2268 }
2269
Johan Hedberg333ae952015-03-17 13:48:47 +02002270 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002271 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2272 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002273 goto failed;
2274 }
2275
2276 val = !!cp->val;
2277
2278 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2279 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2280 goto failed;
2281 }
2282
2283 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2284 if (!cmd) {
2285 err = -ENOMEM;
2286 goto failed;
2287 }
2288
2289 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2290 if (err < 0) {
2291 mgmt_pending_remove(cmd);
2292 goto failed;
2293 }
2294
2295failed:
2296 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002297 return err;
2298}
2299
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002300static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002301{
2302 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002303 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002304 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002305 int err;
2306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002307 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002308
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002309 status = mgmt_bredr_support(hdev);
2310 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002311 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002312
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002313 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002314 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2315 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002316
Johan Hedberga7e80f22013-01-09 16:05:19 +02002317 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002318 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2319 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002320
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002321 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002322
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002323 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002324 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002325
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002326 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002327 changed = !hci_dev_test_and_set_flag(hdev,
2328 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002329 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002330 changed = hci_dev_test_and_clear_flag(hdev,
2331 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002332 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002333 changed = hci_dev_test_and_clear_flag(hdev,
2334 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002335 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002336 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002337 }
2338
2339 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2340 if (err < 0)
2341 goto failed;
2342
2343 if (changed)
2344 err = new_settings(hdev, sk);
2345
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002346 goto failed;
2347 }
2348
Johan Hedberg333ae952015-03-17 13:48:47 +02002349 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002350 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2351 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002352 goto failed;
2353 }
2354
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002355 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002356 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2357 goto failed;
2358 }
2359
2360 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2361 if (!cmd) {
2362 err = -ENOMEM;
2363 goto failed;
2364 }
2365
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002366 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002367 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2368 sizeof(cp->val), &cp->val);
2369
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002370 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002371 if (err < 0) {
2372 mgmt_pending_remove(cmd);
2373 goto failed;
2374 }
2375
2376failed:
2377 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002378 return err;
2379}
2380
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002381static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002382{
2383 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002384 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002385 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002386 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002387
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002388 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002389
Johan Hedberge6fe7982013-10-02 15:45:22 +03002390 status = mgmt_bredr_support(hdev);
2391 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002392 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002393
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002394 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002395 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2396 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002397
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002398 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002399 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2400 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002401
Johan Hedberga7e80f22013-01-09 16:05:19 +02002402 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002403 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2404 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002405
Marcel Holtmannee392692013-10-01 22:59:23 -07002406 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002407
Johan Hedberg333ae952015-03-17 13:48:47 +02002408 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002409 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2410 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002411 goto unlock;
2412 }
2413
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002414 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002415 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002416 } else {
2417 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002418 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2419 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002420 goto unlock;
2421 }
2422
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002423 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002424 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002425
2426 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2427 if (err < 0)
2428 goto unlock;
2429
2430 if (changed)
2431 err = new_settings(hdev, sk);
2432
2433unlock:
2434 hci_dev_unlock(hdev);
2435 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002436}
2437
Marcel Holtmann1904a852015-01-11 13:50:44 -08002438static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002439{
2440 struct cmd_lookup match = { NULL, hdev };
2441
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302442 hci_dev_lock(hdev);
2443
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002444 if (status) {
2445 u8 mgmt_err = mgmt_status(status);
2446
2447 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2448 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302449 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002450 }
2451
2452 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2453
2454 new_settings(hdev, match.sk);
2455
2456 if (match.sk)
2457 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002458
2459 /* Make sure the controller has a good default for
2460 * advertising data. Restrict the update to when LE
2461 * has actually been enabled. During power on, the
2462 * update in powered_update_hci will take care of it.
2463 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002464 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002465 struct hci_request req;
2466
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002467 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002468 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002469 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002470 hci_req_run(&req, NULL);
Johan Hedberg2e93e532015-11-11 08:11:17 +02002471 hci_update_background_scan(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002472 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302473
2474unlock:
2475 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002476}
2477
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002478static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002479{
2480 struct mgmt_mode *cp = data;
2481 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002482 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002483 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002484 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002485 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002486
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002487 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002488
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002489 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002490 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2491 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002492
Johan Hedberga7e80f22013-01-09 16:05:19 +02002493 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002494 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2495 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002496
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002497 /* Bluetooth single mode LE only controllers or dual-mode
2498 * controllers configured as LE only devices, do not allow
2499 * switching LE off. These have either LE enabled explicitly
2500 * or BR/EDR has been previously switched off.
2501 *
2502 * When trying to enable an already enabled LE, then gracefully
2503 * send a positive response. Trying to disable it however will
2504 * result into rejection.
2505 */
2506 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2507 if (cp->val == 0x01)
2508 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2509
Johan Hedberga69e8372015-03-06 21:08:53 +02002510 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2511 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002512 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002513
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002514 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002515
2516 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002517 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002518
Florian Grandel847818d2015-06-18 03:16:46 +02002519 if (!val)
2520 clear_adv_instance(hdev, NULL, 0x00, true);
2521
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002522 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002523 bool changed = false;
2524
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002525 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002526 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002527 changed = true;
2528 }
2529
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002530 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002531 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002532 changed = true;
2533 }
2534
Johan Hedberg06199cf2012-02-22 16:37:11 +02002535 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2536 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002537 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002538
2539 if (changed)
2540 err = new_settings(hdev, sk);
2541
Johan Hedberg1de028c2012-02-29 19:55:35 -08002542 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002543 }
2544
Johan Hedberg333ae952015-03-17 13:48:47 +02002545 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2546 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002547 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2548 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002549 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002550 }
2551
2552 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2553 if (!cmd) {
2554 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002555 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002556 }
2557
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002558 hci_req_init(&req, hdev);
2559
Johan Hedberg06199cf2012-02-22 16:37:11 +02002560 memset(&hci_cp, 0, sizeof(hci_cp));
2561
2562 if (val) {
2563 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002564 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002565 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002566 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002567 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002568 }
2569
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002570 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2571 &hci_cp);
2572
2573 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302574 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002575 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002576
Johan Hedberg1de028c2012-02-29 19:55:35 -08002577unlock:
2578 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002579 return err;
2580}
2581
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002582/* This is a helper function to test for pending mgmt commands that can
2583 * cause CoD or EIR HCI commands. We can only allow one such pending
2584 * mgmt command at a time since otherwise we cannot easily track what
2585 * the current values are, will be, and based on that calculate if a new
2586 * HCI command needs to be sent and if yes with what value.
2587 */
2588static bool pending_eir_or_class(struct hci_dev *hdev)
2589{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002590 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002591
2592 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2593 switch (cmd->opcode) {
2594 case MGMT_OP_ADD_UUID:
2595 case MGMT_OP_REMOVE_UUID:
2596 case MGMT_OP_SET_DEV_CLASS:
2597 case MGMT_OP_SET_POWERED:
2598 return true;
2599 }
2600 }
2601
2602 return false;
2603}
2604
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002605static const u8 bluetooth_base_uuid[] = {
2606 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2607 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2608};
2609
2610static u8 get_uuid_size(const u8 *uuid)
2611{
2612 u32 val;
2613
2614 if (memcmp(uuid, bluetooth_base_uuid, 12))
2615 return 128;
2616
2617 val = get_unaligned_le32(&uuid[12]);
2618 if (val > 0xffff)
2619 return 32;
2620
2621 return 16;
2622}
2623
Johan Hedberg92da6092013-03-15 17:06:55 -05002624static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2625{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002626 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002627
2628 hci_dev_lock(hdev);
2629
Johan Hedberg333ae952015-03-17 13:48:47 +02002630 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002631 if (!cmd)
2632 goto unlock;
2633
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002634 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2635 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002636
2637 mgmt_pending_remove(cmd);
2638
2639unlock:
2640 hci_dev_unlock(hdev);
2641}
2642
Marcel Holtmann1904a852015-01-11 13:50:44 -08002643static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002644{
2645 BT_DBG("status 0x%02x", status);
2646
2647 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2648}
2649
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002650static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002651{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002652 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002653 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002654 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002655 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002656 int err;
2657
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002658 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002659
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002660 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002661
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002662 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002663 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2664 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002665 goto failed;
2666 }
2667
Andre Guedes92c4c202012-06-07 19:05:44 -03002668 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002669 if (!uuid) {
2670 err = -ENOMEM;
2671 goto failed;
2672 }
2673
2674 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002675 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002676 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002677
Johan Hedbergde66aa62013-01-27 00:31:27 +02002678 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002679
Johan Hedberg890ea892013-03-15 17:06:52 -05002680 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002681
Johan Hedberg890ea892013-03-15 17:06:52 -05002682 update_class(&req);
2683 update_eir(&req);
2684
Johan Hedberg92da6092013-03-15 17:06:55 -05002685 err = hci_req_run(&req, add_uuid_complete);
2686 if (err < 0) {
2687 if (err != -ENODATA)
2688 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002689
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002690 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2691 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002692 goto failed;
2693 }
2694
2695 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002696 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002697 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002698 goto failed;
2699 }
2700
2701 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002702
2703failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002704 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002705 return err;
2706}
2707
Johan Hedberg24b78d02012-02-23 23:24:30 +02002708static bool enable_service_cache(struct hci_dev *hdev)
2709{
2710 if (!hdev_is_powered(hdev))
2711 return false;
2712
Marcel Holtmann238be782015-03-13 02:11:06 -07002713 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002714 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2715 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002716 return true;
2717 }
2718
2719 return false;
2720}
2721
Marcel Holtmann1904a852015-01-11 13:50:44 -08002722static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002723{
2724 BT_DBG("status 0x%02x", status);
2725
2726 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2727}
2728
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002729static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002730 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002731{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002732 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002733 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002734 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002735 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 -05002736 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002737 int err, found;
2738
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002739 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002740
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002741 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002742
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002743 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002744 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2745 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002746 goto unlock;
2747 }
2748
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002749 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002750 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002751
Johan Hedberg24b78d02012-02-23 23:24:30 +02002752 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002753 err = mgmt_cmd_complete(sk, hdev->id,
2754 MGMT_OP_REMOVE_UUID,
2755 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002756 goto unlock;
2757 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002758
Johan Hedberg9246a862012-02-23 21:33:16 +02002759 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002760 }
2761
2762 found = 0;
2763
Johan Hedberg056341c2013-01-27 00:31:30 +02002764 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002765 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2766 continue;
2767
2768 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002769 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002770 found++;
2771 }
2772
2773 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002774 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2775 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002776 goto unlock;
2777 }
2778
Johan Hedberg9246a862012-02-23 21:33:16 +02002779update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002780 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002781
Johan Hedberg890ea892013-03-15 17:06:52 -05002782 update_class(&req);
2783 update_eir(&req);
2784
Johan Hedberg92da6092013-03-15 17:06:55 -05002785 err = hci_req_run(&req, remove_uuid_complete);
2786 if (err < 0) {
2787 if (err != -ENODATA)
2788 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002789
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002790 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2791 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002792 goto unlock;
2793 }
2794
2795 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002796 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002797 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002798 goto unlock;
2799 }
2800
2801 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002802
2803unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002804 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002805 return err;
2806}
2807
Marcel Holtmann1904a852015-01-11 13:50:44 -08002808static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002809{
2810 BT_DBG("status 0x%02x", status);
2811
2812 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2813}
2814
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002815static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002816 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002817{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002818 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002819 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002820 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002821 int err;
2822
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002823 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002824
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002825 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002826 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2827 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002828
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002829 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002830
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002831 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002832 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2833 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002834 goto unlock;
2835 }
2836
2837 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002838 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2839 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002840 goto unlock;
2841 }
2842
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002843 hdev->major_class = cp->major;
2844 hdev->minor_class = cp->minor;
2845
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002846 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002847 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2848 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002849 goto unlock;
2850 }
2851
Johan Hedberg890ea892013-03-15 17:06:52 -05002852 hci_req_init(&req, hdev);
2853
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002854 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002855 hci_dev_unlock(hdev);
2856 cancel_delayed_work_sync(&hdev->service_cache);
2857 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002858 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002859 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002860
Johan Hedberg890ea892013-03-15 17:06:52 -05002861 update_class(&req);
2862
Johan Hedberg92da6092013-03-15 17:06:55 -05002863 err = hci_req_run(&req, set_class_complete);
2864 if (err < 0) {
2865 if (err != -ENODATA)
2866 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002867
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002868 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2869 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002870 goto unlock;
2871 }
2872
2873 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002874 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002875 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002876 goto unlock;
2877 }
2878
2879 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002880
Johan Hedbergb5235a62012-02-21 14:32:24 +02002881unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002882 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002883 return err;
2884}
2885
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002886static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002887 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002888{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002889 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002890 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2891 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002892 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002893 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002894 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002895
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002896 BT_DBG("request for %s", hdev->name);
2897
2898 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002899 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2900 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002901
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002902 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002903 if (key_count > max_key_count) {
2904 BT_ERR("load_link_keys: too big key_count value %u",
2905 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002906 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2907 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002908 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002909
Johan Hedberg86742e12011-11-07 23:13:38 +02002910 expected_len = sizeof(*cp) + key_count *
2911 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002912 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002913 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002914 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002915 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2916 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002917 }
2918
Johan Hedberg4ae143012013-01-20 14:27:13 +02002919 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002920 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2921 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae143012013-01-20 14:27:13 +02002922
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002923 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002924 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002925
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002926 for (i = 0; i < key_count; i++) {
2927 struct mgmt_link_key_info *key = &cp->keys[i];
2928
Marcel Holtmann8e991132014-01-10 02:07:25 -08002929 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002930 return mgmt_cmd_status(sk, hdev->id,
2931 MGMT_OP_LOAD_LINK_KEYS,
2932 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002933 }
2934
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002935 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002936
2937 hci_link_keys_clear(hdev);
2938
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002939 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002940 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002941 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002942 changed = hci_dev_test_and_clear_flag(hdev,
2943 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002944
2945 if (changed)
2946 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002947
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002948 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002949 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002950
Johan Hedberg58e92932014-06-24 14:00:26 +03002951 /* Always ignore debug keys and require a new pairing if
2952 * the user wants to use them.
2953 */
2954 if (key->type == HCI_LK_DEBUG_COMBINATION)
2955 continue;
2956
Johan Hedberg7652ff62014-06-24 13:15:49 +03002957 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2958 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002959 }
2960
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002961 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002962
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002963 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002964
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002965 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002966}
2967
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002968static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002969 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002970{
2971 struct mgmt_ev_device_unpaired ev;
2972
2973 bacpy(&ev.addr.bdaddr, bdaddr);
2974 ev.addr.type = addr_type;
2975
2976 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002977 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002978}
2979
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002980static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002981 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002982{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002983 struct mgmt_cp_unpair_device *cp = data;
2984 struct mgmt_rp_unpair_device rp;
Johan Hedbergfc643612015-10-22 09:38:31 +03002985 struct hci_conn_params *params;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002986 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002987 struct hci_conn *conn;
Johan Hedbergec182f02015-10-21 18:03:03 +03002988 u8 addr_type;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002989 int err;
2990
Johan Hedberga8a1d192011-11-10 15:54:38 +02002991 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002992 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2993 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002994
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002995 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002996 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2997 MGMT_STATUS_INVALID_PARAMS,
2998 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002999
Johan Hedberg118da702013-01-20 14:27:20 +02003000 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003001 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3002 MGMT_STATUS_INVALID_PARAMS,
3003 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02003004
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003005 hci_dev_lock(hdev);
3006
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02003007 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003008 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3009 MGMT_STATUS_NOT_POWERED, &rp,
3010 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02003011 goto unlock;
3012 }
3013
Johan Hedberge0b2b272014-02-18 17:14:31 +02003014 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003015 /* If disconnection is requested, then look up the
3016 * connection. If the remote device is connected, it
3017 * will be later used to terminate the link.
3018 *
3019 * Setting it to NULL explicitly will cause no
3020 * termination of the link.
3021 */
3022 if (cp->disconnect)
3023 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3024 &cp->addr.bdaddr);
3025 else
3026 conn = NULL;
3027
Johan Hedberg124f6e32012-02-09 13:50:12 +02003028 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedbergec182f02015-10-21 18:03:03 +03003029 if (err < 0) {
3030 err = mgmt_cmd_complete(sk, hdev->id,
3031 MGMT_OP_UNPAIR_DEVICE,
3032 MGMT_STATUS_NOT_PAIRED, &rp,
3033 sizeof(rp));
3034 goto unlock;
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003035 }
3036
Johan Hedbergec182f02015-10-21 18:03:03 +03003037 goto done;
Johan Hedberge0b2b272014-02-18 17:14:31 +02003038 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03003039
Johan Hedbergec182f02015-10-21 18:03:03 +03003040 /* LE address type */
3041 addr_type = le_addr_type(cp->addr.type);
3042
3043 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
3044
3045 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003046 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003047 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3048 MGMT_STATUS_NOT_PAIRED, &rp,
3049 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003050 goto unlock;
3051 }
3052
Johan Hedbergec182f02015-10-21 18:03:03 +03003053 conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, addr_type);
3054 if (!conn) {
3055 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
3056 goto done;
3057 }
3058
Johan Hedbergc81d5552015-10-22 09:38:35 +03003059 /* Abort any ongoing SMP pairing */
3060 smp_cancel_pairing(conn);
3061
Johan Hedbergec182f02015-10-21 18:03:03 +03003062 /* Defer clearing up the connection parameters until closing to
3063 * give a chance of keeping them if a repairing happens.
3064 */
3065 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
3066
Johan Hedbergfc643612015-10-22 09:38:31 +03003067 /* Disable auto-connection parameters if present */
3068 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, addr_type);
3069 if (params) {
3070 if (params->explicit_connect)
3071 params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
3072 else
3073 params->auto_connect = HCI_AUTO_CONN_DISABLED;
3074 }
3075
Johan Hedbergec182f02015-10-21 18:03:03 +03003076 /* If disconnection is not requested, then clear the connection
3077 * variable so that the link is not terminated.
3078 */
3079 if (!cp->disconnect)
3080 conn = NULL;
3081
3082done:
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003083 /* If the connection variable is set, then termination of the
3084 * link is requested.
3085 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02003086 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003087 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3088 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003089 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003090 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003091 }
3092
Johan Hedberg124f6e32012-02-09 13:50:12 +02003093 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003094 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003095 if (!cmd) {
3096 err = -ENOMEM;
3097 goto unlock;
3098 }
3099
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003100 cmd->cmd_complete = addr_cmd_complete;
3101
Johan Hedberg89e0ccc2015-10-22 10:49:38 +03003102 err = hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003103 if (err < 0)
3104 mgmt_pending_remove(cmd);
3105
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003106unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003107 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003108 return err;
3109}
3110
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003111static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003112 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003113{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003114 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003115 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003116 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003117 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003118 int err;
3119
3120 BT_DBG("");
3121
Johan Hedberg06a63b12013-01-20 14:27:21 +02003122 memset(&rp, 0, sizeof(rp));
3123 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3124 rp.addr.type = cp->addr.type;
3125
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003126 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003127 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3128 MGMT_STATUS_INVALID_PARAMS,
3129 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003130
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003131 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003132
3133 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003134 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3135 MGMT_STATUS_NOT_POWERED, &rp,
3136 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003137 goto failed;
3138 }
3139
Johan Hedberg333ae952015-03-17 13:48:47 +02003140 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003141 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3142 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003143 goto failed;
3144 }
3145
Andre Guedes591f47f2012-04-24 21:02:49 -03003146 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003147 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3148 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003149 else
Johan Hedberg9d4c1cc2015-10-21 18:03:01 +03003150 conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
3151 le_addr_type(cp->addr.type));
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003152
Vishal Agarwalf9607272012-06-13 05:32:43 +05303153 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003154 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3155 MGMT_STATUS_NOT_CONNECTED, &rp,
3156 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003157 goto failed;
3158 }
3159
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003160 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003161 if (!cmd) {
3162 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003163 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003164 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003165
Johan Hedbergf5818c22014-12-05 13:36:02 +02003166 cmd->cmd_complete = generic_cmd_complete;
3167
Johan Hedberge3f2f922014-08-18 20:33:33 +03003168 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003169 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003170 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003171
3172failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003173 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003174 return err;
3175}
3176
Andre Guedes57c14772012-04-24 21:02:50 -03003177static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003178{
3179 switch (link_type) {
3180 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003181 switch (addr_type) {
3182 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003183 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003184
Johan Hedberg48264f02011-11-09 13:58:58 +02003185 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003186 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003187 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003188 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003189
Johan Hedberg4c659c32011-11-07 23:13:39 +02003190 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003191 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003192 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003193 }
3194}
3195
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003196static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3197 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003198{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003199 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003200 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003201 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003202 int err;
3203 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003204
3205 BT_DBG("");
3206
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003207 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003208
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003209 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003210 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3211 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003212 goto unlock;
3213 }
3214
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003215 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003216 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3217 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003218 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003219 }
3220
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003221 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003222 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003223 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003224 err = -ENOMEM;
3225 goto unlock;
3226 }
3227
Johan Hedberg2784eb42011-01-21 13:56:35 +02003228 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003229 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003230 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3231 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003232 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003233 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003234 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003235 continue;
3236 i++;
3237 }
3238
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003239 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003240
Johan Hedberg4c659c32011-11-07 23:13:39 +02003241 /* Recalculate length in case of filtered SCO connections, etc */
3242 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003243
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003244 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3245 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003246
Johan Hedberga38528f2011-01-22 06:46:43 +02003247 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003248
3249unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003250 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003251 return err;
3252}
3253
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003254static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003255 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003256{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003257 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003258 int err;
3259
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003260 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003261 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003262 if (!cmd)
3263 return -ENOMEM;
3264
Johan Hedbergd8457692012-02-17 14:24:57 +02003265 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003266 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003267 if (err < 0)
3268 mgmt_pending_remove(cmd);
3269
3270 return err;
3271}
3272
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003273static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003274 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003275{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003276 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003277 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003278 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003279 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003280 int err;
3281
3282 BT_DBG("");
3283
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003284 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003285
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003286 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003287 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3288 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003289 goto failed;
3290 }
3291
Johan Hedbergd8457692012-02-17 14:24:57 +02003292 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003293 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003294 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3295 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003296 goto failed;
3297 }
3298
3299 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003300 struct mgmt_cp_pin_code_neg_reply ncp;
3301
3302 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003303
3304 BT_ERR("PIN code is not 16 bytes long");
3305
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003306 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003307 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003308 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3309 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003310
3311 goto failed;
3312 }
3313
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003314 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003315 if (!cmd) {
3316 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003317 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003318 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003319
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003320 cmd->cmd_complete = addr_cmd_complete;
3321
Johan Hedbergd8457692012-02-17 14:24:57 +02003322 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003323 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003324 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003325
3326 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3327 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003328 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003329
3330failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003331 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003332 return err;
3333}
3334
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003335static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3336 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003337{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003338 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003339
3340 BT_DBG("");
3341
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003342 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003343 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3344 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003345
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003346 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003347
3348 hdev->io_capability = cp->io_capability;
3349
3350 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003351 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003352
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003353 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003354
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003355 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3356 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003357}
3358
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003359static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003360{
3361 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003362 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003363
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003364 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003365 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3366 continue;
3367
Johan Hedberge9a416b2011-02-19 12:05:56 -03003368 if (cmd->user_data != conn)
3369 continue;
3370
3371 return cmd;
3372 }
3373
3374 return NULL;
3375}
3376
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003377static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003378{
3379 struct mgmt_rp_pair_device rp;
3380 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003381 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003382
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003383 bacpy(&rp.addr.bdaddr, &conn->dst);
3384 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003385
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003386 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3387 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003388
3389 /* So we don't get further callbacks for this connection */
3390 conn->connect_cfm_cb = NULL;
3391 conn->security_cfm_cb = NULL;
3392 conn->disconn_cfm_cb = NULL;
3393
David Herrmann76a68ba2013-04-06 20:28:37 +02003394 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003395
3396 /* The device is paired so there is no need to remove
3397 * its connection parameters anymore.
3398 */
3399 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003400
3401 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003402
3403 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003404}
3405
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003406void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3407{
3408 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003409 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003410
3411 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003412 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003413 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003414 mgmt_pending_remove(cmd);
3415 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003416}
3417
Johan Hedberge9a416b2011-02-19 12:05:56 -03003418static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3419{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003420 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003421
3422 BT_DBG("status %u", status);
3423
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003424 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003425 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003426 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003427 return;
3428 }
3429
3430 cmd->cmd_complete(cmd, mgmt_status(status));
3431 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003432}
3433
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003434static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303435{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003436 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303437
3438 BT_DBG("status %u", status);
3439
3440 if (!status)
3441 return;
3442
3443 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003444 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303445 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003446 return;
3447 }
3448
3449 cmd->cmd_complete(cmd, mgmt_status(status));
3450 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303451}
3452
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003453static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003454 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003455{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003456 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003457 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003458 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003459 u8 sec_level, auth_type;
3460 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003461 int err;
3462
3463 BT_DBG("");
3464
Szymon Jancf950a30e2013-01-18 12:48:07 +01003465 memset(&rp, 0, sizeof(rp));
3466 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3467 rp.addr.type = cp->addr.type;
3468
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003469 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003470 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3471 MGMT_STATUS_INVALID_PARAMS,
3472 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003473
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003474 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003475 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3476 MGMT_STATUS_INVALID_PARAMS,
3477 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003478
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003479 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003480
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003481 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003482 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3483 MGMT_STATUS_NOT_POWERED, &rp,
3484 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003485 goto unlock;
3486 }
3487
Johan Hedberg55e76b32015-03-10 22:34:40 +02003488 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3489 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3490 MGMT_STATUS_ALREADY_PAIRED, &rp,
3491 sizeof(rp));
3492 goto unlock;
3493 }
3494
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003495 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003496 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003497
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003498 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003499 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3500 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003501 } else {
Johan Hedberg85813a72015-10-21 18:02:59 +03003502 u8 addr_type = le_addr_type(cp->addr.type);
Jakub Pawlowski5157b8a2015-10-16 10:07:54 +03003503 struct hci_conn_params *p;
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003504
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003505 /* When pairing a new device, it is expected to remember
3506 * this device for future connections. Adding the connection
3507 * parameter information ahead of time allows tracking
3508 * of the slave preferred values and will speed up any
3509 * further connection establishment.
3510 *
3511 * If connection parameters already exist, then they
3512 * will be kept and this function does nothing.
3513 */
Jakub Pawlowski5157b8a2015-10-16 10:07:54 +03003514 p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3515
3516 if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
3517 p->auto_connect = HCI_AUTO_CONN_DISABLED;
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003518
Jakub Pawlowskifa142222015-08-07 20:22:56 +02003519 conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
3520 addr_type, sec_level,
Johan Hedberg0ad06aa2015-11-11 14:44:57 +02003521 HCI_LE_CONN_TIMEOUT);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003522 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003523
Ville Tervo30e76272011-02-22 16:10:53 -03003524 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003525 int status;
3526
3527 if (PTR_ERR(conn) == -EBUSY)
3528 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003529 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3530 status = MGMT_STATUS_NOT_SUPPORTED;
3531 else if (PTR_ERR(conn) == -ECONNREFUSED)
3532 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003533 else
3534 status = MGMT_STATUS_CONNECT_FAILED;
3535
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003536 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3537 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003538 goto unlock;
3539 }
3540
3541 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003542 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003543 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3544 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003545 goto unlock;
3546 }
3547
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003548 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003549 if (!cmd) {
3550 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003551 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003552 goto unlock;
3553 }
3554
Johan Hedberg04ab2742014-12-05 13:36:04 +02003555 cmd->cmd_complete = pairing_complete;
3556
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003557 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003558 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003559 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003560 conn->security_cfm_cb = pairing_complete_cb;
3561 conn->disconn_cfm_cb = pairing_complete_cb;
3562 } else {
3563 conn->connect_cfm_cb = le_pairing_complete_cb;
3564 conn->security_cfm_cb = le_pairing_complete_cb;
3565 conn->disconn_cfm_cb = le_pairing_complete_cb;
3566 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003567
Johan Hedberge9a416b2011-02-19 12:05:56 -03003568 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003569 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003570
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003571 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003572 hci_conn_security(conn, sec_level, auth_type, true)) {
3573 cmd->cmd_complete(cmd, 0);
3574 mgmt_pending_remove(cmd);
3575 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003576
3577 err = 0;
3578
3579unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003580 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003581 return err;
3582}
3583
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003584static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3585 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003586{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003587 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003588 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003589 struct hci_conn *conn;
3590 int err;
3591
3592 BT_DBG("");
3593
Johan Hedberg28424702012-02-02 04:02:29 +02003594 hci_dev_lock(hdev);
3595
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003596 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003597 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3598 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003599 goto unlock;
3600 }
3601
Johan Hedberg333ae952015-03-17 13:48:47 +02003602 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003603 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003604 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3605 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003606 goto unlock;
3607 }
3608
3609 conn = cmd->user_data;
3610
3611 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003612 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3613 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003614 goto unlock;
3615 }
3616
Johan Hedberga511b352014-12-11 21:45:45 +02003617 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3618 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003619
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003620 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3621 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003622unlock:
3623 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003624 return err;
3625}
3626
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003627static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003628 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003629 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003630{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003631 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003632 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003633 int err;
3634
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003635 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003636
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003637 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003638 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3639 MGMT_STATUS_NOT_POWERED, addr,
3640 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003641 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003642 }
3643
Johan Hedberg1707c602013-03-15 17:07:15 -05003644 if (addr->type == BDADDR_BREDR)
3645 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003646 else
Johan Hedberg9d4c1cc2015-10-21 18:03:01 +03003647 conn = hci_conn_hash_lookup_le(hdev, &addr->bdaddr,
3648 le_addr_type(addr->type));
Brian Gix47c15e22011-11-16 13:53:14 -08003649
Johan Hedberg272d90d2012-02-09 15:26:12 +02003650 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003651 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3652 MGMT_STATUS_NOT_CONNECTED, addr,
3653 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003654 goto done;
3655 }
3656
Johan Hedberg1707c602013-03-15 17:07:15 -05003657 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003658 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003659 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003660 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3661 MGMT_STATUS_SUCCESS, addr,
3662 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003663 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003664 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3665 MGMT_STATUS_FAILED, addr,
3666 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003667
Brian Gix47c15e22011-11-16 13:53:14 -08003668 goto done;
3669 }
3670
Johan Hedberg1707c602013-03-15 17:07:15 -05003671 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003672 if (!cmd) {
3673 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003674 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003675 }
3676
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003677 cmd->cmd_complete = addr_cmd_complete;
3678
Brian Gix0df4c182011-11-16 13:53:13 -08003679 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003680 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3681 struct hci_cp_user_passkey_reply cp;
3682
Johan Hedberg1707c602013-03-15 17:07:15 -05003683 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003684 cp.passkey = passkey;
3685 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3686 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003687 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3688 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003689
Johan Hedberga664b5b2011-02-19 12:06:02 -03003690 if (err < 0)
3691 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003692
Brian Gix0df4c182011-11-16 13:53:13 -08003693done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003694 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003695 return err;
3696}
3697
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303698static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3699 void *data, u16 len)
3700{
3701 struct mgmt_cp_pin_code_neg_reply *cp = data;
3702
3703 BT_DBG("");
3704
Johan Hedberg1707c602013-03-15 17:07:15 -05003705 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303706 MGMT_OP_PIN_CODE_NEG_REPLY,
3707 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3708}
3709
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003710static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3711 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003712{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003713 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003714
3715 BT_DBG("");
3716
3717 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003718 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3719 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003720
Johan Hedberg1707c602013-03-15 17:07:15 -05003721 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003722 MGMT_OP_USER_CONFIRM_REPLY,
3723 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003724}
3725
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003726static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003727 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003728{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003729 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003730
3731 BT_DBG("");
3732
Johan Hedberg1707c602013-03-15 17:07:15 -05003733 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003734 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3735 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003736}
3737
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003738static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3739 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003740{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003741 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003742
3743 BT_DBG("");
3744
Johan Hedberg1707c602013-03-15 17:07:15 -05003745 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003746 MGMT_OP_USER_PASSKEY_REPLY,
3747 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003748}
3749
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003750static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003751 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003752{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003753 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003754
3755 BT_DBG("");
3756
Johan Hedberg1707c602013-03-15 17:07:15 -05003757 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003758 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3759 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003760}
3761
Johan Hedberg13928972013-03-15 17:07:00 -05003762static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003763{
Johan Hedberg13928972013-03-15 17:07:00 -05003764 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003765 struct hci_cp_write_local_name cp;
3766
Johan Hedberg13928972013-03-15 17:07:00 -05003767 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003768
Johan Hedberg890ea892013-03-15 17:06:52 -05003769 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003770}
3771
Marcel Holtmann1904a852015-01-11 13:50:44 -08003772static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003773{
3774 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003775 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003776
3777 BT_DBG("status 0x%02x", status);
3778
3779 hci_dev_lock(hdev);
3780
Johan Hedberg333ae952015-03-17 13:48:47 +02003781 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003782 if (!cmd)
3783 goto unlock;
3784
3785 cp = cmd->param;
3786
3787 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003788 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3789 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003790 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003791 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3792 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003793
3794 mgmt_pending_remove(cmd);
3795
3796unlock:
3797 hci_dev_unlock(hdev);
3798}
3799
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003800static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003801 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003802{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003803 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003804 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003805 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003806 int err;
3807
3808 BT_DBG("");
3809
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003810 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003811
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003812 /* If the old values are the same as the new ones just return a
3813 * direct command complete event.
3814 */
3815 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3816 !memcmp(hdev->short_name, cp->short_name,
3817 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003818 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3819 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003820 goto failed;
3821 }
3822
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003823 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003824
Johan Hedbergb5235a62012-02-21 14:32:24 +02003825 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003826 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003827
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003828 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3829 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003830 if (err < 0)
3831 goto failed;
3832
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003833 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3834 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003835
Johan Hedbergb5235a62012-02-21 14:32:24 +02003836 goto failed;
3837 }
3838
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003839 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003840 if (!cmd) {
3841 err = -ENOMEM;
3842 goto failed;
3843 }
3844
Johan Hedberg13928972013-03-15 17:07:00 -05003845 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3846
Johan Hedberg890ea892013-03-15 17:06:52 -05003847 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003848
3849 if (lmp_bredr_capable(hdev)) {
3850 update_name(&req);
3851 update_eir(&req);
3852 }
3853
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003854 /* The name is stored in the scan response data and so
3855 * no need to udpate the advertising data here.
3856 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003857 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003858 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003859
Johan Hedberg13928972013-03-15 17:07:00 -05003860 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003861 if (err < 0)
3862 mgmt_pending_remove(cmd);
3863
3864failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003865 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003866 return err;
3867}
3868
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003869static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3870 u16 opcode, struct sk_buff *skb)
3871{
3872 struct mgmt_rp_read_local_oob_data mgmt_rp;
3873 size_t rp_size = sizeof(mgmt_rp);
3874 struct mgmt_pending_cmd *cmd;
3875
3876 BT_DBG("%s status %u", hdev->name, status);
3877
3878 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3879 if (!cmd)
3880 return;
3881
3882 if (status || !skb) {
3883 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3884 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3885 goto remove;
3886 }
3887
3888 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3889
3890 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3891 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3892
3893 if (skb->len < sizeof(*rp)) {
3894 mgmt_cmd_status(cmd->sk, hdev->id,
3895 MGMT_OP_READ_LOCAL_OOB_DATA,
3896 MGMT_STATUS_FAILED);
3897 goto remove;
3898 }
3899
3900 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3901 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3902
3903 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3904 } else {
3905 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3906
3907 if (skb->len < sizeof(*rp)) {
3908 mgmt_cmd_status(cmd->sk, hdev->id,
3909 MGMT_OP_READ_LOCAL_OOB_DATA,
3910 MGMT_STATUS_FAILED);
3911 goto remove;
3912 }
3913
3914 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3915 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3916
3917 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3918 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3919 }
3920
3921 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3922 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3923
3924remove:
3925 mgmt_pending_remove(cmd);
3926}
3927
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003928static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003929 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003930{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003931 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003932 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003933 int err;
3934
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003935 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003936
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003937 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003938
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003939 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003940 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3941 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003942 goto unlock;
3943 }
3944
Andre Guedes9a1a1992012-07-24 15:03:48 -03003945 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003946 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3947 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003948 goto unlock;
3949 }
3950
Johan Hedberg333ae952015-03-17 13:48:47 +02003951 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003952 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3953 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003954 goto unlock;
3955 }
3956
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003957 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003958 if (!cmd) {
3959 err = -ENOMEM;
3960 goto unlock;
3961 }
3962
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003963 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003964
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003965 if (bredr_sc_enabled(hdev))
3966 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3967 else
3968 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3969
3970 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003971 if (err < 0)
3972 mgmt_pending_remove(cmd);
3973
3974unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003975 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003976 return err;
3977}
3978
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003979static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003980 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003981{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003982 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003983 int err;
3984
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003985 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003986
Johan Hedberg5d57e792015-01-23 10:10:38 +02003987 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003988 return mgmt_cmd_complete(sk, hdev->id,
3989 MGMT_OP_ADD_REMOTE_OOB_DATA,
3990 MGMT_STATUS_INVALID_PARAMS,
3991 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003992
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003993 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003994
Marcel Holtmannec109112014-01-10 02:07:30 -08003995 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3996 struct mgmt_cp_add_remote_oob_data *cp = data;
3997 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003998
Johan Hedbergc19a4952014-11-17 20:52:19 +02003999 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004000 err = mgmt_cmd_complete(sk, hdev->id,
4001 MGMT_OP_ADD_REMOTE_OOB_DATA,
4002 MGMT_STATUS_INVALID_PARAMS,
4003 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004004 goto unlock;
4005 }
4006
Marcel Holtmannec109112014-01-10 02:07:30 -08004007 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01004008 cp->addr.type, cp->hash,
4009 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08004010 if (err < 0)
4011 status = MGMT_STATUS_FAILED;
4012 else
4013 status = MGMT_STATUS_SUCCESS;
4014
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004015 err = mgmt_cmd_complete(sk, hdev->id,
4016 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
4017 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08004018 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
4019 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004020 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08004021 u8 status;
4022
Johan Hedberg86df9202014-10-26 20:52:27 +01004023 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02004024 /* Enforce zero-valued 192-bit parameters as
4025 * long as legacy SMP OOB isn't implemented.
4026 */
4027 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
4028 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004029 err = mgmt_cmd_complete(sk, hdev->id,
4030 MGMT_OP_ADD_REMOTE_OOB_DATA,
4031 MGMT_STATUS_INVALID_PARAMS,
4032 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02004033 goto unlock;
4034 }
4035
Johan Hedberg86df9202014-10-26 20:52:27 +01004036 rand192 = NULL;
4037 hash192 = NULL;
4038 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004039 /* In case one of the P-192 values is set to zero,
4040 * then just disable OOB data for P-192.
4041 */
4042 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
4043 !memcmp(cp->hash192, ZERO_KEY, 16)) {
4044 rand192 = NULL;
4045 hash192 = NULL;
4046 } else {
4047 rand192 = cp->rand192;
4048 hash192 = cp->hash192;
4049 }
4050 }
4051
4052 /* In case one of the P-256 values is set to zero, then just
4053 * disable OOB data for P-256.
4054 */
4055 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
4056 !memcmp(cp->hash256, ZERO_KEY, 16)) {
4057 rand256 = NULL;
4058 hash256 = NULL;
4059 } else {
4060 rand256 = cp->rand256;
4061 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01004062 }
4063
Johan Hedberg81328d5c2014-10-26 20:33:47 +01004064 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01004065 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004066 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08004067 if (err < 0)
4068 status = MGMT_STATUS_FAILED;
4069 else
4070 status = MGMT_STATUS_SUCCESS;
4071
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004072 err = mgmt_cmd_complete(sk, hdev->id,
4073 MGMT_OP_ADD_REMOTE_OOB_DATA,
4074 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08004075 } else {
4076 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02004077 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
4078 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08004079 }
Szymon Janc2763eda2011-03-22 13:12:22 +01004080
Johan Hedbergc19a4952014-11-17 20:52:19 +02004081unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004082 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004083 return err;
4084}
4085
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004086static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004087 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01004088{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004089 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004090 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01004091 int err;
4092
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004093 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01004094
Johan Hedbergc19a4952014-11-17 20:52:19 +02004095 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004096 return mgmt_cmd_complete(sk, hdev->id,
4097 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4098 MGMT_STATUS_INVALID_PARAMS,
4099 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004100
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004101 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004102
Johan Hedbergeedbd582014-11-15 09:34:23 +02004103 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4104 hci_remote_oob_data_clear(hdev);
4105 status = MGMT_STATUS_SUCCESS;
4106 goto done;
4107 }
4108
Johan Hedberg6928a922014-10-26 20:46:09 +01004109 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004110 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004111 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004112 else
Szymon Janca6785be2012-12-13 15:11:21 +01004113 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004114
Johan Hedbergeedbd582014-11-15 09:34:23 +02004115done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004116 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4117 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004118
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004119 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004120 return err;
4121}
4122
Johan Hedberge68f0722015-11-11 08:30:30 +02004123void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
Andre Guedes7c307722013-04-30 15:29:28 -03004124{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004125 struct mgmt_pending_cmd *cmd;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004126
Andre Guedes7c307722013-04-30 15:29:28 -03004127 BT_DBG("status %d", status);
4128
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004129 hci_dev_lock(hdev);
4130
Johan Hedberg333ae952015-03-17 13:48:47 +02004131 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004132 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004133 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004134
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004135 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004136 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004137 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004138 }
4139
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004140 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004141}
4142
Johan Hedberg591752a2015-11-11 08:11:24 +02004143static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type,
4144 uint8_t *mgmt_status)
4145{
4146 switch (type) {
4147 case DISCOV_TYPE_LE:
4148 *mgmt_status = mgmt_le_support(hdev);
4149 if (*mgmt_status)
4150 return false;
4151 break;
4152 case DISCOV_TYPE_INTERLEAVED:
4153 *mgmt_status = mgmt_le_support(hdev);
4154 if (*mgmt_status)
4155 return false;
4156 /* Intentional fall-through */
4157 case DISCOV_TYPE_BREDR:
4158 *mgmt_status = mgmt_bredr_support(hdev);
4159 if (*mgmt_status)
4160 return false;
4161 break;
4162 default:
4163 *mgmt_status = MGMT_STATUS_INVALID_PARAMS;
4164 return false;
4165 }
4166
4167 return true;
4168}
4169
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004170static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004171 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004172{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004173 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004174 struct mgmt_pending_cmd *cmd;
Marcel Holtmann80190442014-12-04 11:36:36 +01004175 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004176 int err;
4177
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004178 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004179
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004180 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004181
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004182 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004183 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4184 MGMT_STATUS_NOT_POWERED,
4185 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004186 goto failed;
4187 }
4188
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004189 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004190 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004191 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4192 MGMT_STATUS_BUSY, &cp->type,
4193 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004194 goto failed;
4195 }
4196
Johan Hedberg591752a2015-11-11 08:11:24 +02004197 if (!discovery_type_is_valid(hdev, cp->type, &status)) {
4198 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4199 status, &cp->type, sizeof(cp->type));
4200 goto failed;
4201 }
4202
Marcel Holtmann22078802014-12-05 11:45:22 +01004203 /* Clear the discovery filter first to free any previously
4204 * allocated memory for the UUID list.
4205 */
4206 hci_discovery_filter_clear(hdev);
4207
Andre Guedes4aab14e2012-02-17 20:39:36 -03004208 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004209 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004210
Johan Hedberge68f0722015-11-11 08:30:30 +02004211 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
4212 if (!cmd) {
4213 err = -ENOMEM;
Johan Hedberg04106752013-01-10 14:54:09 +02004214 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004215 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004216
Johan Hedberge68f0722015-11-11 08:30:30 +02004217 cmd->cmd_complete = generic_cmd_complete;
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004218
4219 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberge68f0722015-11-11 08:30:30 +02004220 queue_work(hdev->req_workqueue, &hdev->discov_update);
4221 err = 0;
Johan Hedberg14a53662011-04-27 10:29:56 -04004222
4223failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004224 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004225 return err;
4226}
4227
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004228static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4229 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004230{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004231 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4232 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004233}
4234
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004235static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4236 void *data, u16 len)
4237{
4238 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004239 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004240 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4241 u16 uuid_count, expected_len;
4242 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004243 int err;
4244
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004245 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004246
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004247 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004248
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004249 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004250 err = mgmt_cmd_complete(sk, hdev->id,
4251 MGMT_OP_START_SERVICE_DISCOVERY,
4252 MGMT_STATUS_NOT_POWERED,
4253 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004254 goto failed;
4255 }
4256
4257 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004258 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004259 err = mgmt_cmd_complete(sk, hdev->id,
4260 MGMT_OP_START_SERVICE_DISCOVERY,
4261 MGMT_STATUS_BUSY, &cp->type,
4262 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004263 goto failed;
4264 }
4265
4266 uuid_count = __le16_to_cpu(cp->uuid_count);
4267 if (uuid_count > max_uuid_count) {
4268 BT_ERR("service_discovery: too big uuid_count value %u",
4269 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004270 err = mgmt_cmd_complete(sk, hdev->id,
4271 MGMT_OP_START_SERVICE_DISCOVERY,
4272 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4273 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004274 goto failed;
4275 }
4276
4277 expected_len = sizeof(*cp) + uuid_count * 16;
4278 if (expected_len != len) {
4279 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4280 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004281 err = mgmt_cmd_complete(sk, hdev->id,
4282 MGMT_OP_START_SERVICE_DISCOVERY,
4283 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4284 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004285 goto failed;
4286 }
4287
Johan Hedberg591752a2015-11-11 08:11:24 +02004288 if (!discovery_type_is_valid(hdev, cp->type, &status)) {
4289 err = mgmt_cmd_complete(sk, hdev->id,
4290 MGMT_OP_START_SERVICE_DISCOVERY,
4291 status, &cp->type, sizeof(cp->type));
4292 goto failed;
4293 }
4294
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004295 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004296 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004297 if (!cmd) {
4298 err = -ENOMEM;
4299 goto failed;
4300 }
4301
Johan Hedberg2922a942014-12-05 13:36:06 +02004302 cmd->cmd_complete = service_discovery_cmd_complete;
4303
Marcel Holtmann22078802014-12-05 11:45:22 +01004304 /* Clear the discovery filter first to free any previously
4305 * allocated memory for the UUID list.
4306 */
4307 hci_discovery_filter_clear(hdev);
4308
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004309 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004310 hdev->discovery.type = cp->type;
4311 hdev->discovery.rssi = cp->rssi;
4312 hdev->discovery.uuid_count = uuid_count;
4313
4314 if (uuid_count > 0) {
4315 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4316 GFP_KERNEL);
4317 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004318 err = mgmt_cmd_complete(sk, hdev->id,
4319 MGMT_OP_START_SERVICE_DISCOVERY,
4320 MGMT_STATUS_FAILED,
4321 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004322 mgmt_pending_remove(cmd);
4323 goto failed;
4324 }
4325 }
4326
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004327 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberge68f0722015-11-11 08:30:30 +02004328 queue_work(hdev->req_workqueue, &hdev->discov_update);
4329 err = 0;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004330
4331failed:
4332 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004333 return err;
4334}
4335
Johan Hedberg2154d3f2015-11-11 08:30:45 +02004336void mgmt_stop_discovery_complete(struct hci_dev *hdev, u8 status)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004337{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004338 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004339
Andre Guedes0e05bba2013-04-30 15:29:33 -03004340 BT_DBG("status %d", status);
4341
4342 hci_dev_lock(hdev);
4343
Johan Hedberg333ae952015-03-17 13:48:47 +02004344 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004345 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004346 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004347 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004348 }
4349
Andre Guedes0e05bba2013-04-30 15:29:33 -03004350 hci_dev_unlock(hdev);
4351}
4352
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004353static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004354 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004355{
Johan Hedbergd9306502012-02-20 23:25:18 +02004356 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004357 struct mgmt_pending_cmd *cmd;
Johan Hedberg14a53662011-04-27 10:29:56 -04004358 int err;
4359
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004360 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004361
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004362 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004363
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004364 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004365 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4366 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4367 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004368 goto unlock;
4369 }
4370
4371 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004372 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4373 MGMT_STATUS_INVALID_PARAMS,
4374 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004375 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004376 }
4377
Johan Hedberg2922a942014-12-05 13:36:06 +02004378 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004379 if (!cmd) {
4380 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004381 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004382 }
4383
Johan Hedberg2922a942014-12-05 13:36:06 +02004384 cmd->cmd_complete = generic_cmd_complete;
4385
Johan Hedberg2154d3f2015-11-11 08:30:45 +02004386 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
4387 queue_work(hdev->req_workqueue, &hdev->discov_update);
4388 err = 0;
Johan Hedberg14a53662011-04-27 10:29:56 -04004389
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004390unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004391 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004392 return err;
4393}
4394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004395static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004396 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004397{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004398 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004399 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004400 int err;
4401
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004402 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004403
Johan Hedberg561aafb2012-01-04 13:31:59 +02004404 hci_dev_lock(hdev);
4405
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004406 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004407 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4408 MGMT_STATUS_FAILED, &cp->addr,
4409 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004410 goto failed;
4411 }
4412
Johan Hedberga198e7b2012-02-17 14:27:06 +02004413 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004414 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004415 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4416 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4417 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004418 goto failed;
4419 }
4420
4421 if (cp->name_known) {
4422 e->name_state = NAME_KNOWN;
4423 list_del(&e->list);
4424 } else {
4425 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004426 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004427 }
4428
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004429 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4430 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004431
4432failed:
4433 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004434 return err;
4435}
4436
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004437static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004438 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004439{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004440 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004441 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004442 int err;
4443
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004444 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004445
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004446 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004447 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4448 MGMT_STATUS_INVALID_PARAMS,
4449 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004450
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004451 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004452
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004453 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4454 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004455 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004456 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004457 goto done;
4458 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004459
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004460 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4461 sk);
4462 status = MGMT_STATUS_SUCCESS;
4463
4464done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004465 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4466 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004467
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004468 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004469
4470 return err;
4471}
4472
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004473static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004474 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004475{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004476 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004477 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004478 int err;
4479
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004480 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004481
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004482 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004483 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4484 MGMT_STATUS_INVALID_PARAMS,
4485 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004486
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004487 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004488
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004489 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4490 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004491 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004492 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004493 goto done;
4494 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004495
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004496 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4497 sk);
4498 status = MGMT_STATUS_SUCCESS;
4499
4500done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004501 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4502 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004503
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004504 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004505
4506 return err;
4507}
4508
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004509static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4510 u16 len)
4511{
4512 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004513 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004514 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004515 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004516
4517 BT_DBG("%s", hdev->name);
4518
Szymon Jancc72d4b82012-03-16 16:02:57 +01004519 source = __le16_to_cpu(cp->source);
4520
4521 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004522 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4523 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004524
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004525 hci_dev_lock(hdev);
4526
Szymon Jancc72d4b82012-03-16 16:02:57 +01004527 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004528 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4529 hdev->devid_product = __le16_to_cpu(cp->product);
4530 hdev->devid_version = __le16_to_cpu(cp->version);
4531
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004532 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4533 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004534
Johan Hedberg890ea892013-03-15 17:06:52 -05004535 hci_req_init(&req, hdev);
4536 update_eir(&req);
4537 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004538
4539 hci_dev_unlock(hdev);
4540
4541 return err;
4542}
4543
Arman Uguray24b4f382015-03-23 15:57:12 -07004544static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4545 u16 opcode)
4546{
4547 BT_DBG("status %d", status);
4548}
4549
Marcel Holtmann1904a852015-01-11 13:50:44 -08004550static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4551 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004552{
4553 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004554 struct hci_request req;
Florian Grandel7816b822015-06-18 03:16:45 +02004555 u8 instance;
4556 struct adv_info *adv_instance;
4557 int err;
Johan Hedberg4375f102013-09-25 13:26:10 +03004558
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304559 hci_dev_lock(hdev);
4560
Johan Hedberg4375f102013-09-25 13:26:10 +03004561 if (status) {
4562 u8 mgmt_err = mgmt_status(status);
4563
4564 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4565 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304566 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004567 }
4568
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004569 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004570 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004571 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004572 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004573
Johan Hedberg4375f102013-09-25 13:26:10 +03004574 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4575 &match);
4576
4577 new_settings(hdev, match.sk);
4578
4579 if (match.sk)
4580 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304581
Arman Uguray24b4f382015-03-23 15:57:12 -07004582 /* If "Set Advertising" was just disabled and instance advertising was
Florian Grandel7816b822015-06-18 03:16:45 +02004583 * set up earlier, then re-enable multi-instance advertising.
Arman Uguray24b4f382015-03-23 15:57:12 -07004584 */
4585 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
Florian Grandel7816b822015-06-18 03:16:45 +02004586 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) ||
4587 list_empty(&hdev->adv_instances))
Arman Uguray24b4f382015-03-23 15:57:12 -07004588 goto unlock;
4589
Florian Grandel7816b822015-06-18 03:16:45 +02004590 instance = hdev->cur_adv_instance;
4591 if (!instance) {
4592 adv_instance = list_first_entry_or_null(&hdev->adv_instances,
4593 struct adv_info, list);
4594 if (!adv_instance)
4595 goto unlock;
4596
4597 instance = adv_instance->instance;
4598 }
4599
Arman Uguray24b4f382015-03-23 15:57:12 -07004600 hci_req_init(&req, hdev);
4601
Florian Grandel7816b822015-06-18 03:16:45 +02004602 err = schedule_adv_instance(&req, instance, true);
Arman Uguray24b4f382015-03-23 15:57:12 -07004603
Florian Grandel7816b822015-06-18 03:16:45 +02004604 if (!err)
4605 err = hci_req_run(&req, enable_advertising_instance);
4606
4607 if (err)
Arman Uguray24b4f382015-03-23 15:57:12 -07004608 BT_ERR("Failed to re-configure advertising");
4609
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304610unlock:
4611 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004612}
4613
Marcel Holtmann21b51872013-10-10 09:47:53 -07004614static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4615 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004616{
4617 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004618 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004619 struct hci_request req;
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004620 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004621 int err;
4622
4623 BT_DBG("request for %s", hdev->name);
4624
Johan Hedberge6fe7982013-10-02 15:45:22 +03004625 status = mgmt_le_support(hdev);
4626 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004627 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4628 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004629
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004630 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004631 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4632 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004633
4634 hci_dev_lock(hdev);
4635
4636 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004637
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004638 /* The following conditions are ones which mean that we should
4639 * not do any HCI communication but directly send a mgmt
4640 * response to user space (after toggling the flag if
4641 * necessary).
4642 */
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004643 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004644 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4645 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004646 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004647 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004648 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004649 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004650
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004651 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004652 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004653 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004654 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004655 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004656 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004657 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004658 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004659 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004660 }
4661
4662 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4663 if (err < 0)
4664 goto unlock;
4665
4666 if (changed)
4667 err = new_settings(hdev, sk);
4668
4669 goto unlock;
4670 }
4671
Johan Hedberg333ae952015-03-17 13:48:47 +02004672 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4673 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004674 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4675 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004676 goto unlock;
4677 }
4678
4679 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4680 if (!cmd) {
4681 err = -ENOMEM;
4682 goto unlock;
4683 }
4684
4685 hci_req_init(&req, hdev);
4686
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004687 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004688 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004689 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004690 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004691
Florian Grandel7816b822015-06-18 03:16:45 +02004692 cancel_adv_timeout(hdev);
4693
Arman Uguray24b4f382015-03-23 15:57:12 -07004694 if (val) {
Florian Grandel7816b822015-06-18 03:16:45 +02004695 /* Switch to instance "0" for the Set Advertising setting.
4696 * We cannot use update_[adv|scan_rsp]_data() here as the
4697 * HCI_ADVERTISING flag is not yet set.
4698 */
Florian Grandelefae0022015-06-18 03:16:37 +02004699 update_inst_adv_data(&req, 0x00);
4700 update_inst_scan_rsp_data(&req, 0x00);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004701 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004702 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004703 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004704 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004705
4706 err = hci_req_run(&req, set_advertising_complete);
4707 if (err < 0)
4708 mgmt_pending_remove(cmd);
4709
4710unlock:
4711 hci_dev_unlock(hdev);
4712 return err;
4713}
4714
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004715static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4716 void *data, u16 len)
4717{
4718 struct mgmt_cp_set_static_address *cp = data;
4719 int err;
4720
4721 BT_DBG("%s", hdev->name);
4722
Marcel Holtmann62af4442013-10-02 22:10:32 -07004723 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004724 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4725 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004726
4727 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004728 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4729 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004730
4731 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4732 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004733 return mgmt_cmd_status(sk, hdev->id,
4734 MGMT_OP_SET_STATIC_ADDRESS,
4735 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004736
4737 /* Two most significant bits shall be set */
4738 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004739 return mgmt_cmd_status(sk, hdev->id,
4740 MGMT_OP_SET_STATIC_ADDRESS,
4741 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004742 }
4743
4744 hci_dev_lock(hdev);
4745
4746 bacpy(&hdev->static_addr, &cp->bdaddr);
4747
Marcel Holtmann93690c22015-03-06 10:11:21 -08004748 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4749 if (err < 0)
4750 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004751
Marcel Holtmann93690c22015-03-06 10:11:21 -08004752 err = new_settings(hdev, sk);
4753
4754unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004755 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004756 return err;
4757}
4758
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004759static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4760 void *data, u16 len)
4761{
4762 struct mgmt_cp_set_scan_params *cp = data;
4763 __u16 interval, window;
4764 int err;
4765
4766 BT_DBG("%s", hdev->name);
4767
4768 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004769 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4770 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004771
4772 interval = __le16_to_cpu(cp->interval);
4773
4774 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004775 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4776 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004777
4778 window = __le16_to_cpu(cp->window);
4779
4780 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004781 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4782 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004783
Marcel Holtmann899e1072013-10-14 09:55:32 -07004784 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004785 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4786 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004787
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004788 hci_dev_lock(hdev);
4789
4790 hdev->le_scan_interval = interval;
4791 hdev->le_scan_window = window;
4792
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004793 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4794 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004795
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004796 /* If background scan is running, restart it so new parameters are
4797 * loaded.
4798 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004799 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004800 hdev->discovery.state == DISCOVERY_STOPPED) {
4801 struct hci_request req;
4802
4803 hci_req_init(&req, hdev);
4804
4805 hci_req_add_le_scan_disable(&req);
4806 hci_req_add_le_passive_scan(&req);
4807
4808 hci_req_run(&req, NULL);
4809 }
4810
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004811 hci_dev_unlock(hdev);
4812
4813 return err;
4814}
4815
Marcel Holtmann1904a852015-01-11 13:50:44 -08004816static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4817 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004818{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004819 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004820
4821 BT_DBG("status 0x%02x", status);
4822
4823 hci_dev_lock(hdev);
4824
Johan Hedberg333ae952015-03-17 13:48:47 +02004825 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004826 if (!cmd)
4827 goto unlock;
4828
4829 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004830 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4831 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004832 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004833 struct mgmt_mode *cp = cmd->param;
4834
4835 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004836 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004837 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004838 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004839
Johan Hedberg33e38b32013-03-15 17:07:05 -05004840 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4841 new_settings(hdev, cmd->sk);
4842 }
4843
4844 mgmt_pending_remove(cmd);
4845
4846unlock:
4847 hci_dev_unlock(hdev);
4848}
4849
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004850static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004851 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004852{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004853 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004854 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004855 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004856 int err;
4857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004858 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004859
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004860 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004861 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004862 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4863 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004864
Johan Hedberga7e80f22013-01-09 16:05:19 +02004865 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004866 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4867 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004868
Antti Julkuf6422ec2011-06-22 13:11:56 +03004869 hci_dev_lock(hdev);
4870
Johan Hedberg333ae952015-03-17 13:48:47 +02004871 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004872 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4873 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004874 goto unlock;
4875 }
4876
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004877 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004878 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4879 hdev);
4880 goto unlock;
4881 }
4882
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004883 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004884 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004885 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4886 hdev);
4887 new_settings(hdev, sk);
4888 goto unlock;
4889 }
4890
Johan Hedberg33e38b32013-03-15 17:07:05 -05004891 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4892 data, len);
4893 if (!cmd) {
4894 err = -ENOMEM;
4895 goto unlock;
4896 }
4897
4898 hci_req_init(&req, hdev);
4899
Johan Hedberg406d7802013-03-15 17:07:09 -05004900 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004901
4902 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004903 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004904 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4905 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004906 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004907 }
4908
Johan Hedberg33e38b32013-03-15 17:07:05 -05004909unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004910 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004911
Antti Julkuf6422ec2011-06-22 13:11:56 +03004912 return err;
4913}
4914
Marcel Holtmann1904a852015-01-11 13:50:44 -08004915static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004916{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004917 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004918
4919 BT_DBG("status 0x%02x", status);
4920
4921 hci_dev_lock(hdev);
4922
Johan Hedberg333ae952015-03-17 13:48:47 +02004923 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004924 if (!cmd)
4925 goto unlock;
4926
4927 if (status) {
4928 u8 mgmt_err = mgmt_status(status);
4929
4930 /* We need to restore the flag if related HCI commands
4931 * failed.
4932 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004933 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004934
Johan Hedberga69e8372015-03-06 21:08:53 +02004935 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004936 } else {
4937 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4938 new_settings(hdev, cmd->sk);
4939 }
4940
4941 mgmt_pending_remove(cmd);
4942
4943unlock:
4944 hci_dev_unlock(hdev);
4945}
4946
4947static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4948{
4949 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004950 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004951 struct hci_request req;
4952 int err;
4953
4954 BT_DBG("request for %s", hdev->name);
4955
4956 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004957 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4958 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004959
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004960 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004961 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4962 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004963
4964 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004965 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4966 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004967
4968 hci_dev_lock(hdev);
4969
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004970 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004971 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4972 goto unlock;
4973 }
4974
4975 if (!hdev_is_powered(hdev)) {
4976 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004977 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4978 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4979 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4980 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4981 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004982 }
4983
Marcel Holtmannce05d602015-03-13 02:11:03 -07004984 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004985
4986 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4987 if (err < 0)
4988 goto unlock;
4989
4990 err = new_settings(hdev, sk);
4991 goto unlock;
4992 }
4993
4994 /* Reject disabling when powered on */
4995 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004996 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4997 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004998 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004999 } else {
5000 /* When configuring a dual-mode controller to operate
5001 * with LE only and using a static address, then switching
5002 * BR/EDR back on is not allowed.
5003 *
5004 * Dual-mode controllers shall operate with the public
5005 * address as its identity address for BR/EDR and LE. So
5006 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005007 *
5008 * The same restrictions applies when secure connections
5009 * has been enabled. For BR/EDR this is a controller feature
5010 * while for LE it is a host stack feature. This means that
5011 * switching BR/EDR back on when secure connections has been
5012 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005013 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005014 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005015 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005016 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005017 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5018 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005019 goto unlock;
5020 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005021 }
5022
Johan Hedberg333ae952015-03-17 13:48:47 +02005023 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005024 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5025 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005026 goto unlock;
5027 }
5028
5029 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5030 if (!cmd) {
5031 err = -ENOMEM;
5032 goto unlock;
5033 }
5034
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005035 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005036 * generates the correct flags.
5037 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005038 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005039
5040 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005041
Johan Hedberg432df052014-08-01 11:13:31 +03005042 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005043 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005044
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005045 /* Since only the advertising data flags will change, there
5046 * is no need to update the scan response data.
5047 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005048 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005049
Johan Hedberg0663ca22013-10-02 13:43:14 +03005050 err = hci_req_run(&req, set_bredr_complete);
5051 if (err < 0)
5052 mgmt_pending_remove(cmd);
5053
5054unlock:
5055 hci_dev_unlock(hdev);
5056 return err;
5057}
5058
Johan Hedberga1443f52015-01-23 15:42:46 +02005059static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5060{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005061 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005062 struct mgmt_mode *cp;
5063
5064 BT_DBG("%s status %u", hdev->name, status);
5065
5066 hci_dev_lock(hdev);
5067
Johan Hedberg333ae952015-03-17 13:48:47 +02005068 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005069 if (!cmd)
5070 goto unlock;
5071
5072 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005073 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5074 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005075 goto remove;
5076 }
5077
5078 cp = cmd->param;
5079
5080 switch (cp->val) {
5081 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005082 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5083 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005084 break;
5085 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005086 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005087 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005088 break;
5089 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005090 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5091 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005092 break;
5093 }
5094
5095 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5096 new_settings(hdev, cmd->sk);
5097
5098remove:
5099 mgmt_pending_remove(cmd);
5100unlock:
5101 hci_dev_unlock(hdev);
5102}
5103
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005104static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5105 void *data, u16 len)
5106{
5107 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005108 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005109 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005110 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005111 int err;
5112
5113 BT_DBG("request for %s", hdev->name);
5114
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005115 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005116 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005117 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5118 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005119
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005120 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005121 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005122 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005123 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5124 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005125
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005126 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005127 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005128 MGMT_STATUS_INVALID_PARAMS);
5129
5130 hci_dev_lock(hdev);
5131
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005132 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005133 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005134 bool changed;
5135
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005136 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005137 changed = !hci_dev_test_and_set_flag(hdev,
5138 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005139 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005140 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005141 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005142 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005143 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005144 changed = hci_dev_test_and_clear_flag(hdev,
5145 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005146 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005147 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005148
5149 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5150 if (err < 0)
5151 goto failed;
5152
5153 if (changed)
5154 err = new_settings(hdev, sk);
5155
5156 goto failed;
5157 }
5158
Johan Hedberg333ae952015-03-17 13:48:47 +02005159 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005160 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5161 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005162 goto failed;
5163 }
5164
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005165 val = !!cp->val;
5166
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005167 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5168 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005169 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5170 goto failed;
5171 }
5172
5173 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5174 if (!cmd) {
5175 err = -ENOMEM;
5176 goto failed;
5177 }
5178
Johan Hedberga1443f52015-01-23 15:42:46 +02005179 hci_req_init(&req, hdev);
5180 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5181 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005182 if (err < 0) {
5183 mgmt_pending_remove(cmd);
5184 goto failed;
5185 }
5186
5187failed:
5188 hci_dev_unlock(hdev);
5189 return err;
5190}
5191
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005192static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5193 void *data, u16 len)
5194{
5195 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005196 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005197 int err;
5198
5199 BT_DBG("request for %s", hdev->name);
5200
Johan Hedbergb97109792014-06-24 14:00:28 +03005201 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005202 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5203 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005204
5205 hci_dev_lock(hdev);
5206
5207 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005208 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005209 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005210 changed = hci_dev_test_and_clear_flag(hdev,
5211 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005212
Johan Hedbergb97109792014-06-24 14:00:28 +03005213 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005214 use_changed = !hci_dev_test_and_set_flag(hdev,
5215 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005216 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005217 use_changed = hci_dev_test_and_clear_flag(hdev,
5218 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005219
5220 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005221 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005222 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5223 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5224 sizeof(mode), &mode);
5225 }
5226
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005227 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5228 if (err < 0)
5229 goto unlock;
5230
5231 if (changed)
5232 err = new_settings(hdev, sk);
5233
5234unlock:
5235 hci_dev_unlock(hdev);
5236 return err;
5237}
5238
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005239static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5240 u16 len)
5241{
5242 struct mgmt_cp_set_privacy *cp = cp_data;
5243 bool changed;
5244 int err;
5245
5246 BT_DBG("request for %s", hdev->name);
5247
5248 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005249 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5250 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005251
5252 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005253 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5254 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005255
5256 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005257 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5258 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005259
5260 hci_dev_lock(hdev);
5261
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005262 /* If user space supports this command it is also expected to
5263 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5264 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005265 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005266
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005267 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005268 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005269 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005270 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005271 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005272 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005273 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005274 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005275 }
5276
5277 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5278 if (err < 0)
5279 goto unlock;
5280
5281 if (changed)
5282 err = new_settings(hdev, sk);
5283
5284unlock:
5285 hci_dev_unlock(hdev);
5286 return err;
5287}
5288
Johan Hedberg41edf162014-02-18 10:19:35 +02005289static bool irk_is_valid(struct mgmt_irk_info *irk)
5290{
5291 switch (irk->addr.type) {
5292 case BDADDR_LE_PUBLIC:
5293 return true;
5294
5295 case BDADDR_LE_RANDOM:
5296 /* Two most significant bits shall be set */
5297 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5298 return false;
5299 return true;
5300 }
5301
5302 return false;
5303}
5304
5305static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5306 u16 len)
5307{
5308 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005309 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5310 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005311 u16 irk_count, expected_len;
5312 int i, err;
5313
5314 BT_DBG("request for %s", hdev->name);
5315
5316 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005317 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5318 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005319
5320 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005321 if (irk_count > max_irk_count) {
5322 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005323 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5324 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005325 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005326
5327 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5328 if (expected_len != len) {
5329 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005330 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005331 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5332 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005333 }
5334
5335 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5336
5337 for (i = 0; i < irk_count; i++) {
5338 struct mgmt_irk_info *key = &cp->irks[i];
5339
5340 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005341 return mgmt_cmd_status(sk, hdev->id,
5342 MGMT_OP_LOAD_IRKS,
5343 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005344 }
5345
5346 hci_dev_lock(hdev);
5347
5348 hci_smp_irks_clear(hdev);
5349
5350 for (i = 0; i < irk_count; i++) {
5351 struct mgmt_irk_info *irk = &cp->irks[i];
Johan Hedberg41edf162014-02-18 10:19:35 +02005352
Johan Hedberg85813a72015-10-21 18:02:59 +03005353 hci_add_irk(hdev, &irk->addr.bdaddr,
5354 le_addr_type(irk->addr.type), irk->val,
Johan Hedberg41edf162014-02-18 10:19:35 +02005355 BDADDR_ANY);
5356 }
5357
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005358 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005359
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005360 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005361
5362 hci_dev_unlock(hdev);
5363
5364 return err;
5365}
5366
Johan Hedberg3f706b72013-01-20 14:27:16 +02005367static bool ltk_is_valid(struct mgmt_ltk_info *key)
5368{
5369 if (key->master != 0x00 && key->master != 0x01)
5370 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005371
5372 switch (key->addr.type) {
5373 case BDADDR_LE_PUBLIC:
5374 return true;
5375
5376 case BDADDR_LE_RANDOM:
5377 /* Two most significant bits shall be set */
5378 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5379 return false;
5380 return true;
5381 }
5382
5383 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005384}
5385
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005386static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005387 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005388{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005389 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005390 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5391 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005392 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005393 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005394
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005395 BT_DBG("request for %s", hdev->name);
5396
5397 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005398 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5399 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005400
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005401 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005402 if (key_count > max_key_count) {
5403 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005404 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5405 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005406 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005407
5408 expected_len = sizeof(*cp) + key_count *
5409 sizeof(struct mgmt_ltk_info);
5410 if (expected_len != len) {
5411 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005412 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005413 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5414 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005415 }
5416
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005417 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005418
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005419 for (i = 0; i < key_count; i++) {
5420 struct mgmt_ltk_info *key = &cp->keys[i];
5421
Johan Hedberg3f706b72013-01-20 14:27:16 +02005422 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005423 return mgmt_cmd_status(sk, hdev->id,
5424 MGMT_OP_LOAD_LONG_TERM_KEYS,
5425 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005426 }
5427
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005428 hci_dev_lock(hdev);
5429
5430 hci_smp_ltks_clear(hdev);
5431
5432 for (i = 0; i < key_count; i++) {
5433 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedberg85813a72015-10-21 18:02:59 +03005434 u8 type, authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005435
Johan Hedberg61b43352014-05-29 19:36:53 +03005436 switch (key->type) {
5437 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005438 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005439 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005440 break;
5441 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005442 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005443 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005444 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005445 case MGMT_LTK_P256_UNAUTH:
5446 authenticated = 0x00;
5447 type = SMP_LTK_P256;
5448 break;
5449 case MGMT_LTK_P256_AUTH:
5450 authenticated = 0x01;
5451 type = SMP_LTK_P256;
5452 break;
5453 case MGMT_LTK_P256_DEBUG:
5454 authenticated = 0x00;
5455 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005456 default:
5457 continue;
5458 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005459
Johan Hedberg85813a72015-10-21 18:02:59 +03005460 hci_add_ltk(hdev, &key->addr.bdaddr,
5461 le_addr_type(key->addr.type), type, authenticated,
5462 key->val, key->enc_size, key->ediv, key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005463 }
5464
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005465 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005466 NULL, 0);
5467
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005468 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005469
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005470 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005471}
5472
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005473static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005474{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005475 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005476 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005477 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005478
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005479 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005480
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005481 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005482 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005483 rp.tx_power = conn->tx_power;
5484 rp.max_tx_power = conn->max_tx_power;
5485 } else {
5486 rp.rssi = HCI_RSSI_INVALID;
5487 rp.tx_power = HCI_TX_POWER_INVALID;
5488 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005489 }
5490
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005491 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5492 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005493
5494 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005495 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005496
5497 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005498}
5499
Marcel Holtmann1904a852015-01-11 13:50:44 -08005500static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5501 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005502{
5503 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005504 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005505 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005506 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005507 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005508
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005509 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005510
5511 hci_dev_lock(hdev);
5512
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005513 /* Commands sent in request are either Read RSSI or Read Transmit Power
5514 * Level so we check which one was last sent to retrieve connection
5515 * handle. Both commands have handle as first parameter so it's safe to
5516 * cast data on the same command struct.
5517 *
5518 * First command sent is always Read RSSI and we fail only if it fails.
5519 * In other case we simply override error to indicate success as we
5520 * already remembered if TX power value is actually valid.
5521 */
5522 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5523 if (!cp) {
5524 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005525 status = MGMT_STATUS_SUCCESS;
5526 } else {
5527 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005528 }
5529
5530 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005531 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005532 goto unlock;
5533 }
5534
5535 handle = __le16_to_cpu(cp->handle);
5536 conn = hci_conn_hash_lookup_handle(hdev, handle);
5537 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005538 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005539 goto unlock;
5540 }
5541
Johan Hedberg333ae952015-03-17 13:48:47 +02005542 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005543 if (!cmd)
5544 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005545
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005546 cmd->cmd_complete(cmd, status);
5547 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005548
5549unlock:
5550 hci_dev_unlock(hdev);
5551}
5552
5553static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5554 u16 len)
5555{
5556 struct mgmt_cp_get_conn_info *cp = data;
5557 struct mgmt_rp_get_conn_info rp;
5558 struct hci_conn *conn;
5559 unsigned long conn_info_age;
5560 int err = 0;
5561
5562 BT_DBG("%s", hdev->name);
5563
5564 memset(&rp, 0, sizeof(rp));
5565 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5566 rp.addr.type = cp->addr.type;
5567
5568 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005569 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5570 MGMT_STATUS_INVALID_PARAMS,
5571 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005572
5573 hci_dev_lock(hdev);
5574
5575 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005576 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5577 MGMT_STATUS_NOT_POWERED, &rp,
5578 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005579 goto unlock;
5580 }
5581
5582 if (cp->addr.type == BDADDR_BREDR)
5583 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5584 &cp->addr.bdaddr);
5585 else
5586 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5587
5588 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005589 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5590 MGMT_STATUS_NOT_CONNECTED, &rp,
5591 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005592 goto unlock;
5593 }
5594
Johan Hedberg333ae952015-03-17 13:48:47 +02005595 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005596 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5597 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005598 goto unlock;
5599 }
5600
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005601 /* To avoid client trying to guess when to poll again for information we
5602 * calculate conn info age as random value between min/max set in hdev.
5603 */
5604 conn_info_age = hdev->conn_info_min_age +
5605 prandom_u32_max(hdev->conn_info_max_age -
5606 hdev->conn_info_min_age);
5607
5608 /* Query controller to refresh cached values if they are too old or were
5609 * never read.
5610 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005611 if (time_after(jiffies, conn->conn_info_timestamp +
5612 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005613 !conn->conn_info_timestamp) {
5614 struct hci_request req;
5615 struct hci_cp_read_tx_power req_txp_cp;
5616 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005617 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005618
5619 hci_req_init(&req, hdev);
5620 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5621 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5622 &req_rssi_cp);
5623
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005624 /* For LE links TX power does not change thus we don't need to
5625 * query for it once value is known.
5626 */
5627 if (!bdaddr_type_is_le(cp->addr.type) ||
5628 conn->tx_power == HCI_TX_POWER_INVALID) {
5629 req_txp_cp.handle = cpu_to_le16(conn->handle);
5630 req_txp_cp.type = 0x00;
5631 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5632 sizeof(req_txp_cp), &req_txp_cp);
5633 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005634
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005635 /* Max TX power needs to be read only once per connection */
5636 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5637 req_txp_cp.handle = cpu_to_le16(conn->handle);
5638 req_txp_cp.type = 0x01;
5639 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5640 sizeof(req_txp_cp), &req_txp_cp);
5641 }
5642
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005643 err = hci_req_run(&req, conn_info_refresh_complete);
5644 if (err < 0)
5645 goto unlock;
5646
5647 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5648 data, len);
5649 if (!cmd) {
5650 err = -ENOMEM;
5651 goto unlock;
5652 }
5653
5654 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005655 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005656 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005657
5658 conn->conn_info_timestamp = jiffies;
5659 } else {
5660 /* Cache is valid, just reply with values cached in hci_conn */
5661 rp.rssi = conn->rssi;
5662 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005663 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005664
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005665 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5666 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005667 }
5668
5669unlock:
5670 hci_dev_unlock(hdev);
5671 return err;
5672}
5673
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005674static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005675{
5676 struct hci_conn *conn = cmd->user_data;
5677 struct mgmt_rp_get_clock_info rp;
5678 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005679 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005680
5681 memset(&rp, 0, sizeof(rp));
5682 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5683
5684 if (status)
5685 goto complete;
5686
5687 hdev = hci_dev_get(cmd->index);
5688 if (hdev) {
5689 rp.local_clock = cpu_to_le32(hdev->clock);
5690 hci_dev_put(hdev);
5691 }
5692
5693 if (conn) {
5694 rp.piconet_clock = cpu_to_le32(conn->clock);
5695 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5696 }
5697
5698complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005699 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5700 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005701
5702 if (conn) {
5703 hci_conn_drop(conn);
5704 hci_conn_put(conn);
5705 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005706
5707 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005708}
5709
Marcel Holtmann1904a852015-01-11 13:50:44 -08005710static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005711{
Johan Hedberg95868422014-06-28 17:54:07 +03005712 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005713 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005714 struct hci_conn *conn;
5715
5716 BT_DBG("%s status %u", hdev->name, status);
5717
5718 hci_dev_lock(hdev);
5719
5720 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5721 if (!hci_cp)
5722 goto unlock;
5723
5724 if (hci_cp->which) {
5725 u16 handle = __le16_to_cpu(hci_cp->handle);
5726 conn = hci_conn_hash_lookup_handle(hdev, handle);
5727 } else {
5728 conn = NULL;
5729 }
5730
Johan Hedberg333ae952015-03-17 13:48:47 +02005731 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005732 if (!cmd)
5733 goto unlock;
5734
Johan Hedberg69487372014-12-05 13:36:07 +02005735 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005736 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005737
5738unlock:
5739 hci_dev_unlock(hdev);
5740}
5741
5742static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5743 u16 len)
5744{
5745 struct mgmt_cp_get_clock_info *cp = data;
5746 struct mgmt_rp_get_clock_info rp;
5747 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005748 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005749 struct hci_request req;
5750 struct hci_conn *conn;
5751 int err;
5752
5753 BT_DBG("%s", hdev->name);
5754
5755 memset(&rp, 0, sizeof(rp));
5756 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5757 rp.addr.type = cp->addr.type;
5758
5759 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005760 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5761 MGMT_STATUS_INVALID_PARAMS,
5762 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005763
5764 hci_dev_lock(hdev);
5765
5766 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005767 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5768 MGMT_STATUS_NOT_POWERED, &rp,
5769 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005770 goto unlock;
5771 }
5772
5773 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5774 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5775 &cp->addr.bdaddr);
5776 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005777 err = mgmt_cmd_complete(sk, hdev->id,
5778 MGMT_OP_GET_CLOCK_INFO,
5779 MGMT_STATUS_NOT_CONNECTED,
5780 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005781 goto unlock;
5782 }
5783 } else {
5784 conn = NULL;
5785 }
5786
5787 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5788 if (!cmd) {
5789 err = -ENOMEM;
5790 goto unlock;
5791 }
5792
Johan Hedberg69487372014-12-05 13:36:07 +02005793 cmd->cmd_complete = clock_info_cmd_complete;
5794
Johan Hedberg95868422014-06-28 17:54:07 +03005795 hci_req_init(&req, hdev);
5796
5797 memset(&hci_cp, 0, sizeof(hci_cp));
5798 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5799
5800 if (conn) {
5801 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005802 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005803
5804 hci_cp.handle = cpu_to_le16(conn->handle);
5805 hci_cp.which = 0x01; /* Piconet clock */
5806 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5807 }
5808
5809 err = hci_req_run(&req, get_clock_info_complete);
5810 if (err < 0)
5811 mgmt_pending_remove(cmd);
5812
5813unlock:
5814 hci_dev_unlock(hdev);
5815 return err;
5816}
5817
Johan Hedberg5a154e62014-12-19 22:26:02 +02005818static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5819{
5820 struct hci_conn *conn;
5821
5822 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5823 if (!conn)
5824 return false;
5825
5826 if (conn->dst_type != type)
5827 return false;
5828
5829 if (conn->state != BT_CONNECTED)
5830 return false;
5831
5832 return true;
5833}
5834
5835/* This function requires the caller holds hdev->lock */
Johan Hedberg51d7a942015-11-11 08:11:18 +02005836static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
Johan Hedberg5a154e62014-12-19 22:26:02 +02005837 u8 addr_type, u8 auto_connect)
5838{
Johan Hedberg5a154e62014-12-19 22:26:02 +02005839 struct hci_conn_params *params;
5840
5841 params = hci_conn_params_add(hdev, addr, addr_type);
5842 if (!params)
5843 return -EIO;
5844
5845 if (params->auto_connect == auto_connect)
5846 return 0;
5847
5848 list_del_init(&params->action);
5849
5850 switch (auto_connect) {
5851 case HCI_AUTO_CONN_DISABLED:
5852 case HCI_AUTO_CONN_LINK_LOSS:
Jakub Pawlowski28a667c2015-08-07 20:22:54 +02005853 /* If auto connect is being disabled when we're trying to
5854 * connect to device, keep connecting.
5855 */
5856 if (params->explicit_connect)
5857 list_add(&params->action, &hdev->pend_le_conns);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005858 break;
5859 case HCI_AUTO_CONN_REPORT:
Johan Hedberg49c50922015-10-16 10:07:51 +03005860 if (params->explicit_connect)
5861 list_add(&params->action, &hdev->pend_le_conns);
5862 else
5863 list_add(&params->action, &hdev->pend_le_reports);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005864 break;
5865 case HCI_AUTO_CONN_DIRECT:
5866 case HCI_AUTO_CONN_ALWAYS:
Johan Hedberg51d7a942015-11-11 08:11:18 +02005867 if (!is_connected(hdev, addr, addr_type))
Johan Hedberg5a154e62014-12-19 22:26:02 +02005868 list_add(&params->action, &hdev->pend_le_conns);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005869 break;
5870 }
5871
5872 params->auto_connect = auto_connect;
5873
5874 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5875 auto_connect);
5876
5877 return 0;
5878}
5879
Marcel Holtmann8afef092014-06-29 22:28:34 +02005880static void device_added(struct sock *sk, struct hci_dev *hdev,
5881 bdaddr_t *bdaddr, u8 type, u8 action)
5882{
5883 struct mgmt_ev_device_added ev;
5884
5885 bacpy(&ev.addr.bdaddr, bdaddr);
5886 ev.addr.type = type;
5887 ev.action = action;
5888
5889 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5890}
5891
Marcel Holtmann2faade52014-06-29 19:44:03 +02005892static int add_device(struct sock *sk, struct hci_dev *hdev,
5893 void *data, u16 len)
5894{
5895 struct mgmt_cp_add_device *cp = data;
5896 u8 auto_conn, addr_type;
5897 int err;
5898
5899 BT_DBG("%s", hdev->name);
5900
Johan Hedberg66593582014-07-09 12:59:14 +03005901 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005902 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005903 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5904 MGMT_STATUS_INVALID_PARAMS,
5905 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005906
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005907 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005908 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5909 MGMT_STATUS_INVALID_PARAMS,
5910 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005911
5912 hci_dev_lock(hdev);
5913
Johan Hedberg66593582014-07-09 12:59:14 +03005914 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005915 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005916 if (cp->action != 0x01) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02005917 err = mgmt_cmd_complete(sk, hdev->id,
5918 MGMT_OP_ADD_DEVICE,
5919 MGMT_STATUS_INVALID_PARAMS,
5920 &cp->addr, sizeof(cp->addr));
Johan Hedberg66593582014-07-09 12:59:14 +03005921 goto unlock;
5922 }
5923
5924 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5925 cp->addr.type);
5926 if (err)
5927 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005928
Johan Hedberg2f274982015-11-11 10:36:15 +02005929 hci_update_page_scan(hdev);
Johan Hedberga3974072014-07-09 12:59:15 +03005930
Johan Hedberg66593582014-07-09 12:59:14 +03005931 goto added;
5932 }
5933
Johan Hedberg85813a72015-10-21 18:02:59 +03005934 addr_type = le_addr_type(cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005935
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005936 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005937 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005938 else if (cp->action == 0x01)
5939 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005940 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005941 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005942
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02005943 /* Kernel internally uses conn_params with resolvable private
5944 * address, but Add Device allows only identity addresses.
5945 * Make sure it is enforced before calling
5946 * hci_conn_params_lookup.
5947 */
5948 if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02005949 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5950 MGMT_STATUS_INVALID_PARAMS,
5951 &cp->addr, sizeof(cp->addr));
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02005952 goto unlock;
5953 }
5954
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005955 /* If the connection parameters don't exist for this device,
5956 * they will be created and configured with defaults.
5957 */
Johan Hedberg51d7a942015-11-11 08:11:18 +02005958 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005959 auto_conn) < 0) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02005960 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5961 MGMT_STATUS_FAILED, &cp->addr,
5962 sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005963 goto unlock;
5964 }
5965
Johan Hedberg51d7a942015-11-11 08:11:18 +02005966 hci_update_background_scan(hdev);
5967
Johan Hedberg66593582014-07-09 12:59:14 +03005968added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005969 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5970
Johan Hedberg51d7a942015-11-11 08:11:18 +02005971 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5972 MGMT_STATUS_SUCCESS, &cp->addr,
5973 sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005974
5975unlock:
5976 hci_dev_unlock(hdev);
5977 return err;
5978}
5979
Marcel Holtmann8afef092014-06-29 22:28:34 +02005980static void device_removed(struct sock *sk, struct hci_dev *hdev,
5981 bdaddr_t *bdaddr, u8 type)
5982{
5983 struct mgmt_ev_device_removed ev;
5984
5985 bacpy(&ev.addr.bdaddr, bdaddr);
5986 ev.addr.type = type;
5987
5988 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5989}
5990
Marcel Holtmann2faade52014-06-29 19:44:03 +02005991static int remove_device(struct sock *sk, struct hci_dev *hdev,
5992 void *data, u16 len)
5993{
5994 struct mgmt_cp_remove_device *cp = data;
5995 int err;
5996
5997 BT_DBG("%s", hdev->name);
5998
5999 hci_dev_lock(hdev);
6000
6001 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006002 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006003 u8 addr_type;
6004
Johan Hedberg66593582014-07-09 12:59:14 +03006005 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006006 err = mgmt_cmd_complete(sk, hdev->id,
6007 MGMT_OP_REMOVE_DEVICE,
6008 MGMT_STATUS_INVALID_PARAMS,
6009 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006010 goto unlock;
6011 }
6012
Johan Hedberg66593582014-07-09 12:59:14 +03006013 if (cp->addr.type == BDADDR_BREDR) {
6014 err = hci_bdaddr_list_del(&hdev->whitelist,
6015 &cp->addr.bdaddr,
6016 cp->addr.type);
6017 if (err) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006018 err = mgmt_cmd_complete(sk, hdev->id,
6019 MGMT_OP_REMOVE_DEVICE,
6020 MGMT_STATUS_INVALID_PARAMS,
6021 &cp->addr,
6022 sizeof(cp->addr));
Johan Hedberg66593582014-07-09 12:59:14 +03006023 goto unlock;
6024 }
6025
Johan Hedberg51d7a942015-11-11 08:11:18 +02006026 hci_update_page_scan(hdev);
Johan Hedberga3974072014-07-09 12:59:15 +03006027
Johan Hedberg66593582014-07-09 12:59:14 +03006028 device_removed(sk, hdev, &cp->addr.bdaddr,
6029 cp->addr.type);
6030 goto complete;
6031 }
6032
Johan Hedberg85813a72015-10-21 18:02:59 +03006033 addr_type = le_addr_type(cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006034
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02006035 /* Kernel internally uses conn_params with resolvable private
6036 * address, but Remove Device allows only identity addresses.
6037 * Make sure it is enforced before calling
6038 * hci_conn_params_lookup.
6039 */
6040 if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006041 err = mgmt_cmd_complete(sk, hdev->id,
6042 MGMT_OP_REMOVE_DEVICE,
6043 MGMT_STATUS_INVALID_PARAMS,
6044 &cp->addr, sizeof(cp->addr));
Jakub Pawlowski9a0a8a82015-07-20 13:12:49 +02006045 goto unlock;
6046 }
6047
Johan Hedbergc71593d2014-07-02 17:37:28 +03006048 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6049 addr_type);
6050 if (!params) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006051 err = mgmt_cmd_complete(sk, hdev->id,
6052 MGMT_OP_REMOVE_DEVICE,
6053 MGMT_STATUS_INVALID_PARAMS,
6054 &cp->addr, sizeof(cp->addr));
Johan Hedbergc71593d2014-07-02 17:37:28 +03006055 goto unlock;
6056 }
6057
Johan Hedberg679d2b62015-10-16 10:07:52 +03006058 if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
6059 params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006060 err = mgmt_cmd_complete(sk, hdev->id,
6061 MGMT_OP_REMOVE_DEVICE,
6062 MGMT_STATUS_INVALID_PARAMS,
6063 &cp->addr, sizeof(cp->addr));
Johan Hedbergc71593d2014-07-02 17:37:28 +03006064 goto unlock;
6065 }
6066
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006067 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006068 list_del(&params->list);
6069 kfree(params);
Johan Hedberg51d7a942015-11-11 08:11:18 +02006070 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006071
6072 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006073 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006074 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006075 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006076
Marcel Holtmann2faade52014-06-29 19:44:03 +02006077 if (cp->addr.type) {
Johan Hedberg51d7a942015-11-11 08:11:18 +02006078 err = mgmt_cmd_complete(sk, hdev->id,
6079 MGMT_OP_REMOVE_DEVICE,
6080 MGMT_STATUS_INVALID_PARAMS,
6081 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006082 goto unlock;
6083 }
6084
Johan Hedberg66593582014-07-09 12:59:14 +03006085 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6086 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6087 list_del(&b->list);
6088 kfree(b);
6089 }
6090
Johan Hedberg51d7a942015-11-11 08:11:18 +02006091 hci_update_page_scan(hdev);
Johan Hedberga3974072014-07-09 12:59:15 +03006092
Johan Hedberg19de0822014-07-06 13:06:51 +03006093 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6094 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6095 continue;
6096 device_removed(sk, hdev, &p->addr, p->addr_type);
Johan Hedberg679d2b62015-10-16 10:07:52 +03006097 if (p->explicit_connect) {
6098 p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
6099 continue;
6100 }
Johan Hedberg19de0822014-07-06 13:06:51 +03006101 list_del(&p->action);
6102 list_del(&p->list);
6103 kfree(p);
6104 }
6105
6106 BT_DBG("All LE connection parameters were removed");
6107
Johan Hedberg51d7a942015-11-11 08:11:18 +02006108 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006109 }
6110
Johan Hedberg66593582014-07-09 12:59:14 +03006111complete:
Johan Hedberg51d7a942015-11-11 08:11:18 +02006112 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
6113 MGMT_STATUS_SUCCESS, &cp->addr,
6114 sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006115unlock:
6116 hci_dev_unlock(hdev);
6117 return err;
6118}
6119
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006120static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6121 u16 len)
6122{
6123 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006124 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6125 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006126 u16 param_count, expected_len;
6127 int i;
6128
6129 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006130 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6131 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006132
6133 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006134 if (param_count > max_param_count) {
6135 BT_ERR("load_conn_param: too big param_count value %u",
6136 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006137 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6138 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006139 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006140
6141 expected_len = sizeof(*cp) + param_count *
6142 sizeof(struct mgmt_conn_param);
6143 if (expected_len != len) {
6144 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6145 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006146 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6147 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006148 }
6149
6150 BT_DBG("%s param_count %u", hdev->name, param_count);
6151
6152 hci_dev_lock(hdev);
6153
6154 hci_conn_params_clear_disabled(hdev);
6155
6156 for (i = 0; i < param_count; i++) {
6157 struct mgmt_conn_param *param = &cp->params[i];
6158 struct hci_conn_params *hci_param;
6159 u16 min, max, latency, timeout;
6160 u8 addr_type;
6161
6162 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6163 param->addr.type);
6164
6165 if (param->addr.type == BDADDR_LE_PUBLIC) {
6166 addr_type = ADDR_LE_DEV_PUBLIC;
6167 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6168 addr_type = ADDR_LE_DEV_RANDOM;
6169 } else {
6170 BT_ERR("Ignoring invalid connection parameters");
6171 continue;
6172 }
6173
6174 min = le16_to_cpu(param->min_interval);
6175 max = le16_to_cpu(param->max_interval);
6176 latency = le16_to_cpu(param->latency);
6177 timeout = le16_to_cpu(param->timeout);
6178
6179 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6180 min, max, latency, timeout);
6181
6182 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6183 BT_ERR("Ignoring invalid connection parameters");
6184 continue;
6185 }
6186
6187 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6188 addr_type);
6189 if (!hci_param) {
6190 BT_ERR("Failed to add connection parameters");
6191 continue;
6192 }
6193
6194 hci_param->conn_min_interval = min;
6195 hci_param->conn_max_interval = max;
6196 hci_param->conn_latency = latency;
6197 hci_param->supervision_timeout = timeout;
6198 }
6199
6200 hci_dev_unlock(hdev);
6201
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006202 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6203 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006204}
6205
Marcel Holtmanndbece372014-07-04 18:11:55 +02006206static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6207 void *data, u16 len)
6208{
6209 struct mgmt_cp_set_external_config *cp = data;
6210 bool changed;
6211 int err;
6212
6213 BT_DBG("%s", hdev->name);
6214
6215 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006216 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6217 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006218
6219 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006220 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6221 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006222
6223 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006224 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6225 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006226
6227 hci_dev_lock(hdev);
6228
6229 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006230 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006231 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006232 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006233
6234 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6235 if (err < 0)
6236 goto unlock;
6237
6238 if (!changed)
6239 goto unlock;
6240
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006241 err = new_options(hdev, sk);
6242
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006243 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006244 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006245
Marcel Holtmann516018a2015-03-13 02:11:04 -07006246 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006247 hci_dev_set_flag(hdev, HCI_CONFIG);
6248 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006249
6250 queue_work(hdev->req_workqueue, &hdev->power_on);
6251 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006252 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006253 mgmt_index_added(hdev);
6254 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006255 }
6256
6257unlock:
6258 hci_dev_unlock(hdev);
6259 return err;
6260}
6261
Marcel Holtmann9713c172014-07-06 12:11:15 +02006262static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6263 void *data, u16 len)
6264{
6265 struct mgmt_cp_set_public_address *cp = data;
6266 bool changed;
6267 int err;
6268
6269 BT_DBG("%s", hdev->name);
6270
6271 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006272 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6273 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006274
6275 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006276 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6277 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006278
6279 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006280 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6281 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006282
6283 hci_dev_lock(hdev);
6284
6285 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6286 bacpy(&hdev->public_addr, &cp->bdaddr);
6287
6288 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6289 if (err < 0)
6290 goto unlock;
6291
6292 if (!changed)
6293 goto unlock;
6294
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006295 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006296 err = new_options(hdev, sk);
6297
6298 if (is_configured(hdev)) {
6299 mgmt_index_removed(hdev);
6300
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006301 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006302
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006303 hci_dev_set_flag(hdev, HCI_CONFIG);
6304 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006305
6306 queue_work(hdev->req_workqueue, &hdev->power_on);
6307 }
6308
6309unlock:
6310 hci_dev_unlock(hdev);
6311 return err;
6312}
6313
Marcel Holtmannbea41602015-03-14 22:43:17 -07006314static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6315 u8 data_len)
6316{
6317 eir[eir_len++] = sizeof(type) + data_len;
6318 eir[eir_len++] = type;
6319 memcpy(&eir[eir_len], data, data_len);
6320 eir_len += data_len;
6321
6322 return eir_len;
6323}
6324
Johan Hedberg40f66c02015-04-07 21:52:22 +03006325static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
6326 u16 opcode, struct sk_buff *skb)
6327{
6328 const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
6329 struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
6330 u8 *h192, *r192, *h256, *r256;
6331 struct mgmt_pending_cmd *cmd;
6332 u16 eir_len;
6333 int err;
6334
6335 BT_DBG("%s status %u", hdev->name, status);
6336
6337 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
6338 if (!cmd)
6339 return;
6340
6341 mgmt_cp = cmd->param;
6342
6343 if (status) {
6344 status = mgmt_status(status);
6345 eir_len = 0;
6346
6347 h192 = NULL;
6348 r192 = NULL;
6349 h256 = NULL;
6350 r256 = NULL;
6351 } else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
6352 struct hci_rp_read_local_oob_data *rp;
6353
6354 if (skb->len != sizeof(*rp)) {
6355 status = MGMT_STATUS_FAILED;
6356 eir_len = 0;
6357 } else {
6358 status = MGMT_STATUS_SUCCESS;
6359 rp = (void *)skb->data;
6360
6361 eir_len = 5 + 18 + 18;
6362 h192 = rp->hash;
6363 r192 = rp->rand;
6364 h256 = NULL;
6365 r256 = NULL;
6366 }
6367 } else {
6368 struct hci_rp_read_local_oob_ext_data *rp;
6369
6370 if (skb->len != sizeof(*rp)) {
6371 status = MGMT_STATUS_FAILED;
6372 eir_len = 0;
6373 } else {
6374 status = MGMT_STATUS_SUCCESS;
6375 rp = (void *)skb->data;
6376
6377 if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
6378 eir_len = 5 + 18 + 18;
6379 h192 = NULL;
6380 r192 = NULL;
6381 } else {
6382 eir_len = 5 + 18 + 18 + 18 + 18;
6383 h192 = rp->hash192;
6384 r192 = rp->rand192;
6385 }
6386
6387 h256 = rp->hash256;
6388 r256 = rp->rand256;
6389 }
6390 }
6391
6392 mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
6393 if (!mgmt_rp)
6394 goto done;
6395
6396 if (status)
6397 goto send_rsp;
6398
6399 eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
6400 hdev->dev_class, 3);
6401
6402 if (h192 && r192) {
6403 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6404 EIR_SSP_HASH_C192, h192, 16);
6405 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6406 EIR_SSP_RAND_R192, r192, 16);
6407 }
6408
6409 if (h256 && r256) {
6410 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6411 EIR_SSP_HASH_C256, h256, 16);
6412 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6413 EIR_SSP_RAND_R256, r256, 16);
6414 }
6415
6416send_rsp:
6417 mgmt_rp->type = mgmt_cp->type;
6418 mgmt_rp->eir_len = cpu_to_le16(eir_len);
6419
6420 err = mgmt_cmd_complete(cmd->sk, hdev->id,
6421 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
6422 mgmt_rp, sizeof(*mgmt_rp) + eir_len);
6423 if (err < 0 || status)
6424 goto done;
6425
6426 hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
6427
6428 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6429 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
6430 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
6431done:
6432 kfree(mgmt_rp);
6433 mgmt_pending_remove(cmd);
6434}
6435
6436static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
6437 struct mgmt_cp_read_local_oob_ext_data *cp)
6438{
6439 struct mgmt_pending_cmd *cmd;
6440 struct hci_request req;
6441 int err;
6442
6443 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
6444 cp, sizeof(*cp));
6445 if (!cmd)
6446 return -ENOMEM;
6447
6448 hci_req_init(&req, hdev);
6449
6450 if (bredr_sc_enabled(hdev))
6451 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
6452 else
6453 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
6454
6455 err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
6456 if (err < 0) {
6457 mgmt_pending_remove(cmd);
6458 return err;
6459 }
6460
6461 return 0;
6462}
6463
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006464static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6465 void *data, u16 data_len)
6466{
6467 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6468 struct mgmt_rp_read_local_oob_ext_data *rp;
6469 size_t rp_len;
6470 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006471 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006472 int err;
6473
6474 BT_DBG("%s", hdev->name);
6475
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006476 if (hdev_is_powered(hdev)) {
6477 switch (cp->type) {
6478 case BIT(BDADDR_BREDR):
6479 status = mgmt_bredr_support(hdev);
6480 if (status)
6481 eir_len = 0;
6482 else
6483 eir_len = 5;
6484 break;
6485 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6486 status = mgmt_le_support(hdev);
6487 if (status)
6488 eir_len = 0;
6489 else
6490 eir_len = 9 + 3 + 18 + 18 + 3;
6491 break;
6492 default:
6493 status = MGMT_STATUS_INVALID_PARAMS;
6494 eir_len = 0;
6495 break;
6496 }
6497 } else {
6498 status = MGMT_STATUS_NOT_POWERED;
6499 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006500 }
6501
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006502 rp_len = sizeof(*rp) + eir_len;
6503 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006504 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006505 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006506
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006507 if (status)
6508 goto complete;
6509
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006510 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006511
6512 eir_len = 0;
6513 switch (cp->type) {
6514 case BIT(BDADDR_BREDR):
Johan Hedberg40f66c02015-04-07 21:52:22 +03006515 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
6516 err = read_local_ssp_oob_req(hdev, sk, cp);
6517 hci_dev_unlock(hdev);
6518 if (!err)
6519 goto done;
6520
6521 status = MGMT_STATUS_FAILED;
6522 goto complete;
6523 } else {
6524 eir_len = eir_append_data(rp->eir, eir_len,
6525 EIR_CLASS_OF_DEV,
6526 hdev->dev_class, 3);
6527 }
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006528 break;
6529 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006530 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6531 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006532 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006533 status = MGMT_STATUS_FAILED;
6534 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006535 }
6536
Marcel Holtmanne2135682015-04-02 12:00:58 -07006537 /* This should return the active RPA, but since the RPA
6538 * is only programmed on demand, it is really hard to fill
6539 * this in at the moment. For now disallow retrieving
6540 * local out-of-band data when privacy is in use.
6541 *
6542 * Returning the identity address will not help here since
6543 * pairing happens before the identity resolving key is
6544 * known and thus the connection establishment happens
6545 * based on the RPA and not the identity address.
6546 */
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006547 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
Marcel Holtmanne2135682015-04-02 12:00:58 -07006548 hci_dev_unlock(hdev);
6549 status = MGMT_STATUS_REJECTED;
6550 goto complete;
6551 }
6552
6553 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6554 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6555 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6556 bacmp(&hdev->static_addr, BDADDR_ANY))) {
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006557 memcpy(addr, &hdev->static_addr, 6);
6558 addr[6] = 0x01;
6559 } else {
6560 memcpy(addr, &hdev->bdaddr, 6);
6561 addr[6] = 0x00;
6562 }
6563
6564 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6565 addr, sizeof(addr));
6566
6567 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6568 role = 0x02;
6569 else
6570 role = 0x01;
6571
6572 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6573 &role, sizeof(role));
6574
Marcel Holtmann5082a592015-03-16 12:39:00 -07006575 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6576 eir_len = eir_append_data(rp->eir, eir_len,
6577 EIR_LE_SC_CONFIRM,
6578 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006579
Marcel Holtmann5082a592015-03-16 12:39:00 -07006580 eir_len = eir_append_data(rp->eir, eir_len,
6581 EIR_LE_SC_RANDOM,
6582 rand, sizeof(rand));
6583 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006584
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006585 flags = get_adv_discov_flags(hdev);
6586
6587 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6588 flags |= LE_AD_NO_BREDR;
6589
6590 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6591 &flags, sizeof(flags));
6592 break;
6593 }
6594
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006595 hci_dev_unlock(hdev);
6596
Marcel Holtmann72000df2015-03-16 16:11:21 -07006597 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6598
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006599 status = MGMT_STATUS_SUCCESS;
6600
6601complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006602 rp->type = cp->type;
6603 rp->eir_len = cpu_to_le16(eir_len);
6604
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006605 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006606 status, rp, sizeof(*rp) + eir_len);
6607 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006608 goto done;
6609
6610 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6611 rp, sizeof(*rp) + eir_len,
6612 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006613
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006614done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006615 kfree(rp);
6616
6617 return err;
6618}
6619
Arman Uguray089fa8c2015-03-25 18:53:45 -07006620static u32 get_supported_adv_flags(struct hci_dev *hdev)
6621{
6622 u32 flags = 0;
6623
6624 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6625 flags |= MGMT_ADV_FLAG_DISCOV;
6626 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6627 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6628
6629 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6630 flags |= MGMT_ADV_FLAG_TX_POWER;
6631
6632 return flags;
6633}
6634
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006635static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6636 void *data, u16 data_len)
6637{
6638 struct mgmt_rp_read_adv_features *rp;
6639 size_t rp_len;
Florian Grandel286e0c82015-06-18 03:16:38 +02006640 int err, i;
Arman Uguray24b4f382015-03-23 15:57:12 -07006641 bool instance;
Florian Grandel286e0c82015-06-18 03:16:38 +02006642 struct adv_info *adv_instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006643 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006644
6645 BT_DBG("%s", hdev->name);
6646
Arman Uguray089fa8c2015-03-25 18:53:45 -07006647 if (!lmp_le_capable(hdev))
6648 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6649 MGMT_STATUS_REJECTED);
6650
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006651 hci_dev_lock(hdev);
6652
6653 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006654
Arman Uguray24b4f382015-03-23 15:57:12 -07006655 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6656 if (instance)
Florian Grandel286e0c82015-06-18 03:16:38 +02006657 rp_len += hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006658
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006659 rp = kmalloc(rp_len, GFP_ATOMIC);
6660 if (!rp) {
6661 hci_dev_unlock(hdev);
6662 return -ENOMEM;
6663 }
6664
Arman Uguray089fa8c2015-03-25 18:53:45 -07006665 supported_flags = get_supported_adv_flags(hdev);
6666
6667 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006668 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6669 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Florian Grandeld2609b32015-06-18 03:16:34 +02006670 rp->max_instances = HCI_MAX_ADV_INSTANCES;
Arman Uguray24b4f382015-03-23 15:57:12 -07006671
Arman Uguray24b4f382015-03-23 15:57:12 -07006672 if (instance) {
Florian Grandel286e0c82015-06-18 03:16:38 +02006673 i = 0;
6674 list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
6675 if (i >= hdev->adv_instance_cnt)
6676 break;
6677
6678 rp->instance[i] = adv_instance->instance;
6679 i++;
6680 }
6681 rp->num_instances = hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006682 } else {
6683 rp->num_instances = 0;
6684 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006685
6686 hci_dev_unlock(hdev);
6687
6688 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6689 MGMT_STATUS_SUCCESS, rp, rp_len);
6690
6691 kfree(rp);
6692
6693 return err;
6694}
6695
Arman Uguray4117ed72015-03-23 15:57:14 -07006696static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006697 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006698{
Arman Uguray4117ed72015-03-23 15:57:14 -07006699 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006700 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006701 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006702 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006703 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6704 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006705
Arman Uguray807ec772015-03-25 18:53:42 -07006706 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006707 flags_managed = true;
6708 max_len -= 3;
6709 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006710
Arman Uguray5507e352015-03-25 18:53:44 -07006711 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6712 tx_power_managed = true;
6713 max_len -= 3;
6714 }
6715
Arman Uguray4117ed72015-03-23 15:57:14 -07006716 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006717 return false;
6718
Arman Uguray4117ed72015-03-23 15:57:14 -07006719 /* Make sure that the data is correctly formatted. */
6720 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6721 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006722
Arman Ugurayb44133f2015-03-25 18:53:41 -07006723 if (flags_managed && data[i + 1] == EIR_FLAGS)
6724 return false;
6725
Arman Uguray5507e352015-03-25 18:53:44 -07006726 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6727 return false;
6728
Arman Uguray24b4f382015-03-23 15:57:12 -07006729 /* If the current field length would exceed the total data
6730 * length, then it's invalid.
6731 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006732 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006733 return false;
6734 }
6735
6736 return true;
6737}
6738
Arman Uguray24b4f382015-03-23 15:57:12 -07006739static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6740 u16 opcode)
6741{
6742 struct mgmt_pending_cmd *cmd;
Florian Grandelfffd38b2015-06-18 03:16:47 +02006743 struct mgmt_cp_add_advertising *cp;
Arman Uguray24b4f382015-03-23 15:57:12 -07006744 struct mgmt_rp_add_advertising rp;
Florian Grandelfffd38b2015-06-18 03:16:47 +02006745 struct adv_info *adv_instance, *n;
6746 u8 instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006747
6748 BT_DBG("status %d", status);
6749
6750 hci_dev_lock(hdev);
6751
6752 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6753
Florian Grandelfffd38b2015-06-18 03:16:47 +02006754 if (status)
Arman Uguray24b4f382015-03-23 15:57:12 -07006755 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
Florian Grandelfffd38b2015-06-18 03:16:47 +02006756
6757 list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
6758 if (!adv_instance->pending)
6759 continue;
6760
6761 if (!status) {
6762 adv_instance->pending = false;
6763 continue;
6764 }
6765
6766 instance = adv_instance->instance;
6767
6768 if (hdev->cur_adv_instance == instance)
6769 cancel_adv_timeout(hdev);
6770
6771 hci_remove_adv_instance(hdev, instance);
6772 advertising_removed(cmd ? cmd->sk : NULL, hdev, instance);
Arman Uguray24b4f382015-03-23 15:57:12 -07006773 }
6774
6775 if (!cmd)
6776 goto unlock;
6777
Florian Grandelfffd38b2015-06-18 03:16:47 +02006778 cp = cmd->param;
6779 rp.instance = cp->instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006780
6781 if (status)
6782 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6783 mgmt_status(status));
6784 else
6785 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6786 mgmt_status(status), &rp, sizeof(rp));
6787
6788 mgmt_pending_remove(cmd);
6789
6790unlock:
6791 hci_dev_unlock(hdev);
6792}
6793
Florian Grandel5d900e42015-06-18 03:16:35 +02006794void mgmt_adv_timeout_expired(struct hci_dev *hdev)
Arman Uguray912098a2015-03-23 15:57:15 -07006795{
Florian Grandel847818d2015-06-18 03:16:46 +02006796 u8 instance;
6797 struct hci_request req;
6798
Florian Grandel5d900e42015-06-18 03:16:35 +02006799 hdev->adv_instance_timeout = 0;
Arman Uguray912098a2015-03-23 15:57:15 -07006800
Florian Grandel847818d2015-06-18 03:16:46 +02006801 instance = get_current_adv_instance(hdev);
6802 if (instance == 0x00)
6803 return;
6804
Arman Uguray912098a2015-03-23 15:57:15 -07006805 hci_dev_lock(hdev);
Florian Grandel847818d2015-06-18 03:16:46 +02006806 hci_req_init(&req, hdev);
6807
6808 clear_adv_instance(hdev, &req, instance, false);
6809
6810 if (list_empty(&hdev->adv_instances))
6811 disable_advertising(&req);
6812
6813 if (!skb_queue_empty(&req.cmd_q))
6814 hci_req_run(&req, NULL);
6815
Arman Uguray912098a2015-03-23 15:57:15 -07006816 hci_dev_unlock(hdev);
6817}
6818
Arman Uguray24b4f382015-03-23 15:57:12 -07006819static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6820 void *data, u16 data_len)
6821{
6822 struct mgmt_cp_add_advertising *cp = data;
6823 struct mgmt_rp_add_advertising rp;
6824 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006825 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006826 u8 status;
Florian Grandelfffd38b2015-06-18 03:16:47 +02006827 u16 timeout, duration;
6828 unsigned int prev_instance_cnt = hdev->adv_instance_cnt;
6829 u8 schedule_instance = 0;
6830 struct adv_info *next_instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006831 int err;
6832 struct mgmt_pending_cmd *cmd;
6833 struct hci_request req;
6834
6835 BT_DBG("%s", hdev->name);
6836
6837 status = mgmt_le_support(hdev);
6838 if (status)
6839 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6840 status);
6841
6842 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006843 timeout = __le16_to_cpu(cp->timeout);
Florian Grandelfffd38b2015-06-18 03:16:47 +02006844 duration = __le16_to_cpu(cp->duration);
Arman Uguray24b4f382015-03-23 15:57:12 -07006845
Florian Grandelfffd38b2015-06-18 03:16:47 +02006846 /* The current implementation only supports a subset of the specified
6847 * flags.
Arman Uguray089fa8c2015-03-25 18:53:45 -07006848 */
6849 supported_flags = get_supported_adv_flags(hdev);
Florian Grandelfffd38b2015-06-18 03:16:47 +02006850 if (flags & ~supported_flags)
Arman Uguray24b4f382015-03-23 15:57:12 -07006851 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6852 MGMT_STATUS_INVALID_PARAMS);
6853
6854 hci_dev_lock(hdev);
6855
Arman Uguray912098a2015-03-23 15:57:15 -07006856 if (timeout && !hdev_is_powered(hdev)) {
6857 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6858 MGMT_STATUS_REJECTED);
6859 goto unlock;
6860 }
6861
Arman Uguray24b4f382015-03-23 15:57:12 -07006862 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006863 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006864 pending_find(MGMT_OP_SET_LE, hdev)) {
6865 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6866 MGMT_STATUS_BUSY);
6867 goto unlock;
6868 }
6869
Arman Ugurayb44133f2015-03-25 18:53:41 -07006870 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006871 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006872 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006873 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6874 MGMT_STATUS_INVALID_PARAMS);
6875 goto unlock;
6876 }
6877
Florian Grandelfffd38b2015-06-18 03:16:47 +02006878 err = hci_add_adv_instance(hdev, cp->instance, flags,
6879 cp->adv_data_len, cp->data,
6880 cp->scan_rsp_len,
6881 cp->data + cp->adv_data_len,
6882 timeout, duration);
6883 if (err < 0) {
6884 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6885 MGMT_STATUS_FAILED);
6886 goto unlock;
6887 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006888
Florian Grandelfffd38b2015-06-18 03:16:47 +02006889 /* Only trigger an advertising added event if a new instance was
6890 * actually added.
6891 */
6892 if (hdev->adv_instance_cnt > prev_instance_cnt)
6893 advertising_added(sk, hdev, cp->instance);
Arman Uguray24b4f382015-03-23 15:57:12 -07006894
Florian Grandelfffd38b2015-06-18 03:16:47 +02006895 hci_dev_set_flag(hdev, HCI_ADVERTISING_INSTANCE);
Arman Uguray24b4f382015-03-23 15:57:12 -07006896
Florian Grandelfffd38b2015-06-18 03:16:47 +02006897 if (hdev->cur_adv_instance == cp->instance) {
6898 /* If the currently advertised instance is being changed then
6899 * cancel the current advertising and schedule the next
6900 * instance. If there is only one instance then the overridden
6901 * advertising data will be visible right away.
6902 */
6903 cancel_adv_timeout(hdev);
Arman Uguray912098a2015-03-23 15:57:15 -07006904
Florian Grandelfffd38b2015-06-18 03:16:47 +02006905 next_instance = hci_get_next_instance(hdev, cp->instance);
6906 if (next_instance)
6907 schedule_instance = next_instance->instance;
6908 } else if (!hdev->adv_instance_timeout) {
6909 /* Immediately advertise the new instance if no other
6910 * instance is currently being advertised.
6911 */
6912 schedule_instance = cp->instance;
6913 }
Arman Uguray912098a2015-03-23 15:57:15 -07006914
Florian Grandelfffd38b2015-06-18 03:16:47 +02006915 /* If the HCI_ADVERTISING flag is set or the device isn't powered or
6916 * there is no instance to be advertised then we have no HCI
6917 * communication to make. Simply return.
Arman Uguray24b4f382015-03-23 15:57:12 -07006918 */
6919 if (!hdev_is_powered(hdev) ||
Florian Grandelfffd38b2015-06-18 03:16:47 +02006920 hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
6921 !schedule_instance) {
6922 rp.instance = cp->instance;
Arman Uguray24b4f382015-03-23 15:57:12 -07006923 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6924 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6925 goto unlock;
6926 }
6927
6928 /* We're good to go, update advertising data, parameters, and start
6929 * advertising.
6930 */
6931 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6932 data_len);
6933 if (!cmd) {
6934 err = -ENOMEM;
6935 goto unlock;
6936 }
6937
6938 hci_req_init(&req, hdev);
6939
Florian Grandelfffd38b2015-06-18 03:16:47 +02006940 err = schedule_adv_instance(&req, schedule_instance, true);
Arman Uguray24b4f382015-03-23 15:57:12 -07006941
Florian Grandelfffd38b2015-06-18 03:16:47 +02006942 if (!err)
6943 err = hci_req_run(&req, add_advertising_complete);
6944
Arman Uguray24b4f382015-03-23 15:57:12 -07006945 if (err < 0)
6946 mgmt_pending_remove(cmd);
6947
6948unlock:
6949 hci_dev_unlock(hdev);
6950
6951 return err;
6952}
6953
Arman Ugurayda9293352015-03-23 15:57:13 -07006954static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6955 u16 opcode)
6956{
6957 struct mgmt_pending_cmd *cmd;
Florian Grandel01948332015-06-18 03:16:48 +02006958 struct mgmt_cp_remove_advertising *cp;
Arman Ugurayda9293352015-03-23 15:57:13 -07006959 struct mgmt_rp_remove_advertising rp;
6960
6961 BT_DBG("status %d", status);
6962
6963 hci_dev_lock(hdev);
6964
6965 /* A failure status here only means that we failed to disable
6966 * advertising. Otherwise, the advertising instance has been removed,
6967 * so report success.
6968 */
6969 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6970 if (!cmd)
6971 goto unlock;
6972
Florian Grandel01948332015-06-18 03:16:48 +02006973 cp = cmd->param;
6974 rp.instance = cp->instance;
Arman Ugurayda9293352015-03-23 15:57:13 -07006975
6976 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6977 &rp, sizeof(rp));
6978 mgmt_pending_remove(cmd);
6979
6980unlock:
6981 hci_dev_unlock(hdev);
6982}
6983
6984static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6985 void *data, u16 data_len)
6986{
6987 struct mgmt_cp_remove_advertising *cp = data;
6988 struct mgmt_rp_remove_advertising rp;
Arman Ugurayda9293352015-03-23 15:57:13 -07006989 struct mgmt_pending_cmd *cmd;
6990 struct hci_request req;
Johan Hedberg952497b2015-06-18 21:05:31 +03006991 int err;
Arman Ugurayda9293352015-03-23 15:57:13 -07006992
6993 BT_DBG("%s", hdev->name);
6994
Arman Ugurayda9293352015-03-23 15:57:13 -07006995 hci_dev_lock(hdev);
6996
Johan Hedberg952497b2015-06-18 21:05:31 +03006997 if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {
Florian Grandel01948332015-06-18 03:16:48 +02006998 err = mgmt_cmd_status(sk, hdev->id,
6999 MGMT_OP_REMOVE_ADVERTISING,
7000 MGMT_STATUS_INVALID_PARAMS);
7001 goto unlock;
7002 }
7003
Arman Ugurayda9293352015-03-23 15:57:13 -07007004 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
7005 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
7006 pending_find(MGMT_OP_SET_LE, hdev)) {
7007 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7008 MGMT_STATUS_BUSY);
7009 goto unlock;
7010 }
7011
7012 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
7013 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7014 MGMT_STATUS_INVALID_PARAMS);
7015 goto unlock;
7016 }
7017
Florian Grandel01948332015-06-18 03:16:48 +02007018 hci_req_init(&req, hdev);
Arman Uguray912098a2015-03-23 15:57:15 -07007019
Florian Grandel01948332015-06-18 03:16:48 +02007020 clear_adv_instance(hdev, &req, cp->instance, true);
Arman Ugurayda9293352015-03-23 15:57:13 -07007021
Florian Grandel01948332015-06-18 03:16:48 +02007022 if (list_empty(&hdev->adv_instances))
7023 disable_advertising(&req);
Arman Ugurayda9293352015-03-23 15:57:13 -07007024
Florian Grandel01948332015-06-18 03:16:48 +02007025 /* If no HCI commands have been collected so far or the HCI_ADVERTISING
7026 * flag is set or the device isn't powered then we have no HCI
7027 * communication to make. Simply return.
Arman Ugurayda9293352015-03-23 15:57:13 -07007028 */
Florian Grandel01948332015-06-18 03:16:48 +02007029 if (skb_queue_empty(&req.cmd_q) ||
7030 !hdev_is_powered(hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07007031 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Florian Grandel01948332015-06-18 03:16:48 +02007032 rp.instance = cp->instance;
Arman Ugurayda9293352015-03-23 15:57:13 -07007033 err = mgmt_cmd_complete(sk, hdev->id,
7034 MGMT_OP_REMOVE_ADVERTISING,
7035 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7036 goto unlock;
7037 }
7038
7039 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
7040 data_len);
7041 if (!cmd) {
7042 err = -ENOMEM;
7043 goto unlock;
7044 }
7045
Arman Ugurayda9293352015-03-23 15:57:13 -07007046 err = hci_req_run(&req, remove_advertising_complete);
7047 if (err < 0)
7048 mgmt_pending_remove(cmd);
7049
7050unlock:
7051 hci_dev_unlock(hdev);
7052
7053 return err;
7054}
7055
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007056static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007057 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007058 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007059 HCI_MGMT_NO_HDEV |
7060 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007061 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007062 HCI_MGMT_NO_HDEV |
7063 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007064 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007065 HCI_MGMT_NO_HDEV |
7066 HCI_MGMT_UNTRUSTED },
7067 { read_controller_info, MGMT_READ_INFO_SIZE,
7068 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007069 { set_powered, MGMT_SETTING_SIZE },
7070 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7071 { set_connectable, MGMT_SETTING_SIZE },
7072 { set_fast_connectable, MGMT_SETTING_SIZE },
7073 { set_bondable, MGMT_SETTING_SIZE },
7074 { set_link_security, MGMT_SETTING_SIZE },
7075 { set_ssp, MGMT_SETTING_SIZE },
7076 { set_hs, MGMT_SETTING_SIZE },
7077 { set_le, MGMT_SETTING_SIZE },
7078 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7079 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7080 { add_uuid, MGMT_ADD_UUID_SIZE },
7081 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007082 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7083 HCI_MGMT_VAR_LEN },
7084 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7085 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007086 { disconnect, MGMT_DISCONNECT_SIZE },
7087 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7088 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7089 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7090 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7091 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7092 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7093 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7094 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7095 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7096 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7097 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007098 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7099 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7100 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007101 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7102 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7103 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7104 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7105 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7106 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7107 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7108 { set_advertising, MGMT_SETTING_SIZE },
7109 { set_bredr, MGMT_SETTING_SIZE },
7110 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7111 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7112 { set_secure_conn, MGMT_SETTING_SIZE },
7113 { set_debug_keys, MGMT_SETTING_SIZE },
7114 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007115 { load_irks, MGMT_LOAD_IRKS_SIZE,
7116 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007117 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7118 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7119 { add_device, MGMT_ADD_DEVICE_SIZE },
7120 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007121 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7122 HCI_MGMT_VAR_LEN },
7123 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007124 HCI_MGMT_NO_HDEV |
7125 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007126 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007127 HCI_MGMT_UNCONFIGURED |
7128 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007129 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7130 HCI_MGMT_UNCONFIGURED },
7131 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7132 HCI_MGMT_UNCONFIGURED },
7133 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7134 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007135 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007136 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007137 HCI_MGMT_NO_HDEV |
7138 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007139 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007140 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7141 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007142 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007143};
7144
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007145void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007146{
Marcel Holtmannced85542015-03-14 19:27:56 -07007147 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007148
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007149 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7150 return;
7151
Marcel Holtmannf9207332015-03-14 19:27:55 -07007152 switch (hdev->dev_type) {
7153 case HCI_BREDR:
7154 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7155 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7156 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007157 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007158 } else {
7159 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7160 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007161 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007162 }
7163 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007164 case HCI_AMP:
7165 ev.type = 0x02;
7166 break;
7167 default:
7168 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007169 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007170
7171 ev.bus = hdev->bus;
7172
7173 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7174 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007175}
7176
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007177void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007178{
Marcel Holtmannced85542015-03-14 19:27:56 -07007179 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007180 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007181
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007182 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7183 return;
7184
Marcel Holtmannf9207332015-03-14 19:27:55 -07007185 switch (hdev->dev_type) {
7186 case HCI_BREDR:
7187 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007188
Marcel Holtmannf9207332015-03-14 19:27:55 -07007189 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7190 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7191 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007192 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007193 } else {
7194 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7195 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007196 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007197 }
7198 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007199 case HCI_AMP:
7200 ev.type = 0x02;
7201 break;
7202 default:
7203 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007204 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007205
7206 ev.bus = hdev->bus;
7207
7208 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7209 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007210}
7211
Andre Guedes6046dc32014-02-26 20:21:51 -03007212/* This function requires the caller holds hdev->lock */
Johan Hedbergaf02dd42015-11-11 08:11:21 +02007213static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03007214{
7215 struct hci_conn_params *p;
7216
7217 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007218 /* Needed for AUTO_OFF case where might not "really"
7219 * have been powered off.
7220 */
7221 list_del_init(&p->action);
7222
7223 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007224 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007225 case HCI_AUTO_CONN_ALWAYS:
7226 list_add(&p->action, &hdev->pend_le_conns);
7227 break;
7228 case HCI_AUTO_CONN_REPORT:
7229 list_add(&p->action, &hdev->pend_le_reports);
7230 break;
7231 default:
7232 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007233 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007234 }
7235}
7236
Marcel Holtmann1904a852015-01-11 13:50:44 -08007237static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007238{
7239 struct cmd_lookup match = { NULL, hdev };
7240
7241 BT_DBG("status 0x%02x", status);
7242
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007243 if (!status) {
7244 /* Register the available SMP channels (BR/EDR and LE) only
7245 * when successfully powering on the controller. This late
7246 * registration is required so that LE SMP can clearly
7247 * decide if the public address or static address is used.
7248 */
7249 smp_register(hdev);
Johan Hedbergaf02dd42015-11-11 08:11:21 +02007250
7251 restart_le_actions(hdev);
7252 hci_update_background_scan(hdev);
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007253 }
7254
Johan Hedberg229ab392013-03-15 17:06:53 -05007255 hci_dev_lock(hdev);
7256
7257 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7258
7259 new_settings(hdev, match.sk);
7260
7261 hci_dev_unlock(hdev);
7262
7263 if (match.sk)
7264 sock_put(match.sk);
7265}
7266
Johan Hedberg70da6242013-03-15 17:06:51 -05007267static int powered_update_hci(struct hci_dev *hdev)
7268{
Johan Hedberg890ea892013-03-15 17:06:52 -05007269 struct hci_request req;
Florian Grandel320b3bf2015-06-18 03:16:49 +02007270 struct adv_info *adv_instance;
Johan Hedberg70da6242013-03-15 17:06:51 -05007271 u8 link_sec;
7272
Johan Hedberg890ea892013-03-15 17:06:52 -05007273 hci_req_init(&req, hdev);
7274
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007275 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007276 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007277 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007278
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007279 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007280
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007281 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7282 u8 support = 0x01;
7283
7284 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7285 sizeof(support), &support);
7286 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007287 }
7288
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007289 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007290 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007291 struct hci_cp_write_le_host_supported cp;
7292
Marcel Holtmann32226e42014-07-24 20:04:16 +02007293 cp.le = 0x01;
7294 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007295
7296 /* Check first if we already have the right
7297 * host state (host features set)
7298 */
7299 if (cp.le != lmp_host_le_capable(hdev) ||
7300 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007301 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7302 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007303 }
7304
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007305 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007306 /* Make sure the controller has a good default for
7307 * advertising data. This also applies to the case
7308 * where BR/EDR was toggled during the AUTO_OFF phase.
7309 */
Florian Grandel320b3bf2015-06-18 03:16:49 +02007310 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
7311 (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7312 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007313 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007314 update_scan_rsp_data(&req);
7315 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007316
Florian Grandel320b3bf2015-06-18 03:16:49 +02007317 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
7318 hdev->cur_adv_instance == 0x00 &&
7319 !list_empty(&hdev->adv_instances)) {
7320 adv_instance = list_first_entry(&hdev->adv_instances,
7321 struct adv_info, list);
7322 hdev->cur_adv_instance = adv_instance->instance;
7323 }
7324
7325 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007326 enable_advertising(&req);
Florian Grandel320b3bf2015-06-18 03:16:49 +02007327 else if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
7328 hdev->cur_adv_instance)
7329 schedule_adv_instance(&req, hdev->cur_adv_instance,
7330 true);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007331 }
7332
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007333 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007334 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007335 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7336 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007337
7338 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007339 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007340 write_fast_connectable(&req, true);
7341 else
7342 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007343 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007344 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007345 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007346 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007347 }
7348
Johan Hedberg229ab392013-03-15 17:06:53 -05007349 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007350}
7351
Johan Hedberg744cf192011-11-08 20:40:14 +02007352int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007353{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007354 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007355 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007356 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007357
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007358 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007359 return 0;
7360
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007361 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007362 if (powered_update_hci(hdev) == 0)
7363 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007364
Johan Hedberg229ab392013-03-15 17:06:53 -05007365 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7366 &match);
7367 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007368 }
7369
Johan Hedberg229ab392013-03-15 17:06:53 -05007370 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007371
7372 /* If the power off is because of hdev unregistration let
7373 * use the appropriate INVALID_INDEX status. Otherwise use
7374 * NOT_POWERED. We cover both scenarios here since later in
7375 * mgmt_index_removed() any hci_conn callbacks will have already
7376 * been triggered, potentially causing misleading DISCONNECTED
7377 * status responses.
7378 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007379 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007380 status = MGMT_STATUS_INVALID_INDEX;
7381 else
7382 status = MGMT_STATUS_NOT_POWERED;
7383
7384 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007385
7386 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007387 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7388 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007389
7390new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007391 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007392
7393 if (match.sk)
7394 sock_put(match.sk);
7395
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007396 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007397}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007398
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007399void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007400{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007401 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007402 u8 status;
7403
Johan Hedberg333ae952015-03-17 13:48:47 +02007404 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007405 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007406 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007407
7408 if (err == -ERFKILL)
7409 status = MGMT_STATUS_RFKILLED;
7410 else
7411 status = MGMT_STATUS_FAILED;
7412
Johan Hedberga69e8372015-03-06 21:08:53 +02007413 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007414
7415 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007416}
7417
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007418void mgmt_discoverable_timeout(struct hci_dev *hdev)
7419{
7420 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007421
7422 hci_dev_lock(hdev);
7423
7424 /* When discoverable timeout triggers, then just make sure
7425 * the limited discoverable flag is cleared. Even in the case
7426 * of a timeout triggered from general discoverable, it is
7427 * safe to unconditionally clear the flag.
7428 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007429 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7430 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007431
7432 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007433 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007434 u8 scan = SCAN_PAGE;
7435 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7436 sizeof(scan), &scan);
7437 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007438 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007439
7440 /* Advertising instances don't use the global discoverable setting, so
7441 * only update AD if advertising was enabled using Set Advertising.
7442 */
7443 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7444 update_adv_data(&req);
7445
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007446 hci_req_run(&req, NULL);
7447
7448 hdev->discov_timeout = 0;
7449
Johan Hedberg9a43e252013-10-20 19:00:07 +03007450 new_settings(hdev, NULL);
7451
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007452 hci_dev_unlock(hdev);
7453}
7454
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007455void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7456 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007457{
Johan Hedberg86742e12011-11-07 23:13:38 +02007458 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007459
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007460 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007461
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007462 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007463 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007464 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007465 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007466 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007467 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007468
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007469 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007470}
Johan Hedbergf7520542011-01-20 12:34:39 +02007471
Johan Hedbergd7b25452014-05-23 13:19:53 +03007472static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7473{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007474 switch (ltk->type) {
7475 case SMP_LTK:
7476 case SMP_LTK_SLAVE:
7477 if (ltk->authenticated)
7478 return MGMT_LTK_AUTHENTICATED;
7479 return MGMT_LTK_UNAUTHENTICATED;
7480 case SMP_LTK_P256:
7481 if (ltk->authenticated)
7482 return MGMT_LTK_P256_AUTH;
7483 return MGMT_LTK_P256_UNAUTH;
7484 case SMP_LTK_P256_DEBUG:
7485 return MGMT_LTK_P256_DEBUG;
7486 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007487
7488 return MGMT_LTK_UNAUTHENTICATED;
7489}
7490
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007491void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007492{
7493 struct mgmt_ev_new_long_term_key ev;
7494
7495 memset(&ev, 0, sizeof(ev));
7496
Marcel Holtmann5192d302014-02-19 17:11:58 -08007497 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007498 * without providing an identity resolving key don't require
Marcel Holtmann5192d302014-02-19 17:11:58 -08007499 * to store long term keys. Their addresses will change the
7500 * next time around.
7501 *
7502 * Only when a remote device provides an identity address
7503 * make sure the long term key is stored. If the remote
7504 * identity is known, the long term keys are internally
7505 * mapped to the identity address. So allow static random
7506 * and public addresses here.
7507 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007508 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7509 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7510 ev.store_hint = 0x00;
7511 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007512 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007513
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007514 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007515 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007516 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007517 ev.key.enc_size = key->enc_size;
7518 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007519 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007520
Johan Hedberg2ceba532014-06-16 19:25:16 +03007521 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007522 ev.key.master = 1;
7523
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007524 /* Make sure we copy only the significant bytes based on the
7525 * encryption key size, and set the rest of the value to zeroes.
7526 */
Jakub Pawlowskicb922052015-08-05 23:16:29 +02007527 memcpy(ev.key.val, key->val, key->enc_size);
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007528 memset(ev.key.val + key->enc_size, 0,
7529 sizeof(ev.key.val) - key->enc_size);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007530
Marcel Holtmann083368f2013-10-15 14:26:29 -07007531 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007532}
7533
Johan Hedbergcad20c22015-10-12 13:36:19 +02007534void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk, bool persistent)
Johan Hedberg95fbac82014-02-19 15:18:31 +02007535{
7536 struct mgmt_ev_new_irk ev;
7537
7538 memset(&ev, 0, sizeof(ev));
7539
Johan Hedbergcad20c22015-10-12 13:36:19 +02007540 ev.store_hint = persistent;
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007541
Johan Hedberg95fbac82014-02-19 15:18:31 +02007542 bacpy(&ev.rpa, &irk->rpa);
7543 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7544 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7545 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7546
7547 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7548}
7549
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007550void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7551 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007552{
7553 struct mgmt_ev_new_csrk ev;
7554
7555 memset(&ev, 0, sizeof(ev));
7556
7557 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007558 * without providing an identity resolving key don't require
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007559 * to store signature resolving keys. Their addresses will change
7560 * the next time around.
7561 *
7562 * Only when a remote device provides an identity address
7563 * make sure the signature resolving key is stored. So allow
7564 * static random and public addresses here.
7565 */
7566 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7567 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7568 ev.store_hint = 0x00;
7569 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007570 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007571
7572 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7573 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007574 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007575 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7576
7577 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7578}
7579
Andre Guedesffb5a8272014-07-01 18:10:11 -03007580void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007581 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7582 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007583{
7584 struct mgmt_ev_new_conn_param ev;
7585
Johan Hedbergc103aea2014-07-02 17:37:34 +03007586 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7587 return;
7588
Andre Guedesffb5a8272014-07-01 18:10:11 -03007589 memset(&ev, 0, sizeof(ev));
7590 bacpy(&ev.addr.bdaddr, bdaddr);
7591 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007592 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007593 ev.min_interval = cpu_to_le16(min_interval);
7594 ev.max_interval = cpu_to_le16(max_interval);
7595 ev.latency = cpu_to_le16(latency);
7596 ev.timeout = cpu_to_le16(timeout);
7597
7598 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7599}
7600
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007601void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7602 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007603{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007604 char buf[512];
7605 struct mgmt_ev_device_connected *ev = (void *) buf;
7606 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007607
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007608 bacpy(&ev->addr.bdaddr, &conn->dst);
7609 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007610
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007611 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007612
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007613 /* We must ensure that the EIR Data fields are ordered and
7614 * unique. Keep it simple for now and avoid the problem by not
7615 * adding any BR/EDR data to the LE adv.
7616 */
7617 if (conn->le_adv_data_len > 0) {
7618 memcpy(&ev->eir[eir_len],
7619 conn->le_adv_data, conn->le_adv_data_len);
7620 eir_len = conn->le_adv_data_len;
7621 } else {
7622 if (name_len > 0)
7623 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7624 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007625
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007626 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007627 eir_len = eir_append_data(ev->eir, eir_len,
7628 EIR_CLASS_OF_DEV,
7629 conn->dev_class, 3);
7630 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007631
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007632 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007633
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007634 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7635 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007636}
7637
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007638static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007639{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007640 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007641
Johan Hedbergf5818c22014-12-05 13:36:02 +02007642 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007643
7644 *sk = cmd->sk;
7645 sock_hold(*sk);
7646
Johan Hedberga664b5b2011-02-19 12:06:02 -03007647 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007648}
7649
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007650static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007651{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007652 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007653 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007654
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007655 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7656
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007657 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007658 mgmt_pending_remove(cmd);
7659}
7660
Johan Hedberg84c61d92014-08-01 11:13:30 +03007661bool mgmt_powering_down(struct hci_dev *hdev)
7662{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007663 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007664 struct mgmt_mode *cp;
7665
Johan Hedberg333ae952015-03-17 13:48:47 +02007666 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007667 if (!cmd)
7668 return false;
7669
7670 cp = cmd->param;
7671 if (!cp->val)
7672 return true;
7673
7674 return false;
7675}
7676
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007677void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007678 u8 link_type, u8 addr_type, u8 reason,
7679 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007680{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007681 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007682 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007683
Johan Hedberg84c61d92014-08-01 11:13:30 +03007684 /* The connection is still in hci_conn_hash so test for 1
7685 * instead of 0 to know if this is the last one.
7686 */
7687 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7688 cancel_delayed_work(&hdev->power_off);
7689 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007690 }
7691
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007692 if (!mgmt_connected)
7693 return;
7694
Andre Guedes57eb7762013-10-30 19:01:41 -03007695 if (link_type != ACL_LINK && link_type != LE_LINK)
7696 return;
7697
Johan Hedberg744cf192011-11-08 20:40:14 +02007698 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007699
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007700 bacpy(&ev.addr.bdaddr, bdaddr);
7701 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7702 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007703
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007704 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007705
7706 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007707 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007708
Johan Hedberg124f6e32012-02-09 13:50:12 +02007709 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007710 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007711}
7712
Marcel Holtmann78929242013-10-06 23:55:47 -07007713void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7714 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007715{
Andre Guedes3655bba2013-10-30 19:01:40 -03007716 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7717 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007718 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007719
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007720 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7721 hdev);
7722
Johan Hedberg333ae952015-03-17 13:48:47 +02007723 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007724 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007725 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007726
Andre Guedes3655bba2013-10-30 19:01:40 -03007727 cp = cmd->param;
7728
7729 if (bacmp(bdaddr, &cp->addr.bdaddr))
7730 return;
7731
7732 if (cp->addr.type != bdaddr_type)
7733 return;
7734
Johan Hedbergf5818c22014-12-05 13:36:02 +02007735 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007736 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007737}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007738
Marcel Holtmann445608d2013-10-06 23:55:48 -07007739void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7740 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007741{
7742 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007743
Johan Hedberg84c61d92014-08-01 11:13:30 +03007744 /* The connection is still in hci_conn_hash so test for 1
7745 * instead of 0 to know if this is the last one.
7746 */
7747 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7748 cancel_delayed_work(&hdev->power_off);
7749 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007750 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007751
Johan Hedberg4c659c32011-11-07 23:13:39 +02007752 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007753 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007754 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007755
Marcel Holtmann445608d2013-10-06 23:55:48 -07007756 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007757}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007758
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007759void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007760{
7761 struct mgmt_ev_pin_code_request ev;
7762
Johan Hedbergd8457692012-02-17 14:24:57 +02007763 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007764 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007765 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007766
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007767 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007768}
7769
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007770void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7771 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007772{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007773 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007774
Johan Hedberg333ae952015-03-17 13:48:47 +02007775 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007776 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007777 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007778
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007779 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007780 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007781}
7782
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007783void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7784 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007785{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007786 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007787
Johan Hedberg333ae952015-03-17 13:48:47 +02007788 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007789 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007790 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007791
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007792 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007793 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007794}
Johan Hedberga5c29682011-02-19 12:05:57 -03007795
Johan Hedberg744cf192011-11-08 20:40:14 +02007796int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007797 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007798 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007799{
7800 struct mgmt_ev_user_confirm_request ev;
7801
Johan Hedberg744cf192011-11-08 20:40:14 +02007802 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007803
Johan Hedberg272d90d2012-02-09 15:26:12 +02007804 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007805 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007806 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007807 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007808
Johan Hedberg744cf192011-11-08 20:40:14 +02007809 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007810 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007811}
7812
Johan Hedberg272d90d2012-02-09 15:26:12 +02007813int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007814 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007815{
7816 struct mgmt_ev_user_passkey_request ev;
7817
7818 BT_DBG("%s", hdev->name);
7819
Johan Hedberg272d90d2012-02-09 15:26:12 +02007820 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007821 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007822
7823 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007824 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007825}
7826
Brian Gix0df4c182011-11-16 13:53:13 -08007827static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007828 u8 link_type, u8 addr_type, u8 status,
7829 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007830{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007831 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007832
Johan Hedberg333ae952015-03-17 13:48:47 +02007833 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007834 if (!cmd)
7835 return -ENOENT;
7836
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007837 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007838 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007839
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007840 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007841}
7842
Johan Hedberg744cf192011-11-08 20:40:14 +02007843int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007844 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007845{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007846 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007847 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007848}
7849
Johan Hedberg272d90d2012-02-09 15:26:12 +02007850int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007851 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007852{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007853 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007854 status,
7855 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007856}
Johan Hedberg2a611692011-02-19 12:06:00 -03007857
Brian Gix604086b2011-11-23 08:28:33 -08007858int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007859 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007860{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007861 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007862 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007863}
7864
Johan Hedberg272d90d2012-02-09 15:26:12 +02007865int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007866 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007867{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007868 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007869 status,
7870 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007871}
7872
Johan Hedberg92a25252012-09-06 18:39:26 +03007873int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7874 u8 link_type, u8 addr_type, u32 passkey,
7875 u8 entered)
7876{
7877 struct mgmt_ev_passkey_notify ev;
7878
7879 BT_DBG("%s", hdev->name);
7880
7881 bacpy(&ev.addr.bdaddr, bdaddr);
7882 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7883 ev.passkey = __cpu_to_le32(passkey);
7884 ev.entered = entered;
7885
7886 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7887}
7888
Johan Hedberge1e930f2014-09-08 17:09:49 -07007889void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007890{
7891 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007892 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007893 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007894
Johan Hedberge1e930f2014-09-08 17:09:49 -07007895 bacpy(&ev.addr.bdaddr, &conn->dst);
7896 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7897 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007898
Johan Hedberge1e930f2014-09-08 17:09:49 -07007899 cmd = find_pairing(conn);
7900
7901 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7902 cmd ? cmd->sk : NULL);
7903
Johan Hedberga511b352014-12-11 21:45:45 +02007904 if (cmd) {
7905 cmd->cmd_complete(cmd, status);
7906 mgmt_pending_remove(cmd);
7907 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007908}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007909
Marcel Holtmann464996a2013-10-15 14:26:24 -07007910void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007911{
7912 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007913 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007914
7915 if (status) {
7916 u8 mgmt_err = mgmt_status(status);
7917 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007918 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007919 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007920 }
7921
Marcel Holtmann464996a2013-10-15 14:26:24 -07007922 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007923 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007924 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007925 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007926
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007927 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007928 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007929
Johan Hedberg47990ea2012-02-22 11:58:37 +02007930 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007931 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007932
7933 if (match.sk)
7934 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007935}
7936
Johan Hedberg890ea892013-03-15 17:06:52 -05007937static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007938{
Johan Hedberg890ea892013-03-15 17:06:52 -05007939 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007940 struct hci_cp_write_eir cp;
7941
Johan Hedberg976eb202012-10-24 21:12:01 +03007942 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007943 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007944
Johan Hedbergc80da272012-02-22 15:38:48 +02007945 memset(hdev->eir, 0, sizeof(hdev->eir));
7946
Johan Hedbergcacaf522012-02-21 00:52:42 +02007947 memset(&cp, 0, sizeof(cp));
7948
Johan Hedberg890ea892013-03-15 17:06:52 -05007949 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007950}
7951
Marcel Holtmann3e248562013-10-15 14:26:25 -07007952void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007953{
7954 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007955 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007956 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007957
7958 if (status) {
7959 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007960
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007961 if (enable && hci_dev_test_and_clear_flag(hdev,
7962 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007963 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007964 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007965 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007966
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007967 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7968 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007969 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007970 }
7971
7972 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007973 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007974 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007975 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007976 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007977 changed = hci_dev_test_and_clear_flag(hdev,
7978 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007979 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007980 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007981 }
7982
7983 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7984
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007985 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007986 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007987
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007988 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007989 sock_put(match.sk);
7990
Johan Hedberg890ea892013-03-15 17:06:52 -05007991 hci_req_init(&req, hdev);
7992
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007993 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7994 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007995 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7996 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007997 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007998 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007999 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008000 }
Johan Hedberg890ea892013-03-15 17:06:52 -05008001
8002 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008003}
8004
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008005static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02008006{
8007 struct cmd_lookup *match = data;
8008
Johan Hedberg90e70452012-02-23 23:09:40 +02008009 if (match->sk == NULL) {
8010 match->sk = cmd->sk;
8011 sock_hold(match->sk);
8012 }
Johan Hedberg90e70452012-02-23 23:09:40 +02008013}
8014
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07008015void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
8016 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008017{
Johan Hedberg90e70452012-02-23 23:09:40 +02008018 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008019
Johan Hedberg92da6092013-03-15 17:06:55 -05008020 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
8021 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
8022 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02008023
8024 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008025 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
8026 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02008027
8028 if (match.sk)
8029 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008030}
8031
Marcel Holtmann7667da32013-10-15 14:26:27 -07008032void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02008033{
Johan Hedbergb312b1612011-03-16 14:29:37 +02008034 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008035 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008036
Johan Hedberg13928972013-03-15 17:07:00 -05008037 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07008038 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008039
8040 memset(&ev, 0, sizeof(ev));
8041 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008042 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008043
Johan Hedberg333ae952015-03-17 13:48:47 +02008044 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05008045 if (!cmd) {
8046 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02008047
Johan Hedberg13928972013-03-15 17:07:00 -05008048 /* If this is a HCI command related to powering on the
8049 * HCI dev don't send any mgmt signals.
8050 */
Johan Hedberg333ae952015-03-17 13:48:47 +02008051 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07008052 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008053 }
8054
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008055 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
8056 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008057}
Szymon Jancc35938b2011-03-22 13:12:21 +01008058
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008059static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
8060{
8061 int i;
8062
8063 for (i = 0; i < uuid_count; i++) {
8064 if (!memcmp(uuid, uuids[i], 16))
8065 return true;
8066 }
8067
8068 return false;
8069}
8070
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008071static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
8072{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008073 u16 parsed = 0;
8074
8075 while (parsed < eir_len) {
8076 u8 field_len = eir[0];
8077 u8 uuid[16];
8078 int i;
8079
8080 if (field_len == 0)
8081 break;
8082
8083 if (eir_len - parsed < field_len + 1)
8084 break;
8085
8086 switch (eir[1]) {
8087 case EIR_UUID16_ALL:
8088 case EIR_UUID16_SOME:
8089 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008090 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008091 uuid[13] = eir[i + 3];
8092 uuid[12] = eir[i + 2];
8093 if (has_uuid(uuid, uuid_count, uuids))
8094 return true;
8095 }
8096 break;
8097 case EIR_UUID32_ALL:
8098 case EIR_UUID32_SOME:
8099 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008100 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008101 uuid[15] = eir[i + 5];
8102 uuid[14] = eir[i + 4];
8103 uuid[13] = eir[i + 3];
8104 uuid[12] = eir[i + 2];
8105 if (has_uuid(uuid, uuid_count, uuids))
8106 return true;
8107 }
8108 break;
8109 case EIR_UUID128_ALL:
8110 case EIR_UUID128_SOME:
8111 for (i = 0; i + 17 <= field_len; i += 16) {
8112 memcpy(uuid, eir + i + 2, 16);
8113 if (has_uuid(uuid, uuid_count, uuids))
8114 return true;
8115 }
8116 break;
8117 }
8118
8119 parsed += field_len + 1;
8120 eir += field_len + 1;
8121 }
8122
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008123 return false;
8124}
8125
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008126static void restart_le_scan(struct hci_dev *hdev)
8127{
8128 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008129 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008130 return;
8131
8132 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8133 hdev->discovery.scan_start +
8134 hdev->discovery.scan_duration))
8135 return;
8136
Johan Hedberg7c1fbed2015-11-11 08:11:23 +02008137 queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_restart,
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008138 DISCOV_LE_RESTART_DELAY);
8139}
8140
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008141static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8142 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8143{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008144 /* If a RSSI threshold has been specified, and
8145 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8146 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8147 * is set, let it through for further processing, as we might need to
8148 * restart the scan.
8149 *
8150 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8151 * the results are also dropped.
8152 */
8153 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8154 (rssi == HCI_RSSI_INVALID ||
8155 (rssi < hdev->discovery.rssi &&
8156 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8157 return false;
8158
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008159 if (hdev->discovery.uuid_count != 0) {
8160 /* If a list of UUIDs is provided in filter, results with no
8161 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008162 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008163 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8164 hdev->discovery.uuids) &&
8165 !eir_has_uuids(scan_rsp, scan_rsp_len,
8166 hdev->discovery.uuid_count,
8167 hdev->discovery.uuids))
8168 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008169 }
8170
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008171 /* If duplicate filtering does not report RSSI changes, then restart
8172 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008173 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008174 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8175 restart_le_scan(hdev);
8176
8177 /* Validate RSSI value against the RSSI threshold once more. */
8178 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8179 rssi < hdev->discovery.rssi)
8180 return false;
8181 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008182
8183 return true;
8184}
8185
Marcel Holtmann901801b2013-10-06 23:55:51 -07008186void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008187 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8188 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008189{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008190 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008191 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008192 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008193
Johan Hedberg75ce2082014-07-02 22:42:01 +03008194 /* Don't send events for a non-kernel initiated discovery. With
8195 * LE one exception is if we have pend_le_reports > 0 in which
8196 * case we're doing passive scanning and want these events.
8197 */
8198 if (!hci_discovery_active(hdev)) {
8199 if (link_type == ACL_LINK)
8200 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008201 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008202 return;
8203 }
Andre Guedes12602d02013-04-30 15:29:40 -03008204
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008205 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008206 /* We are using service discovery */
8207 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8208 scan_rsp_len))
8209 return;
8210 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008211
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008212 /* Make sure that the buffer is big enough. The 5 extra bytes
8213 * are for the potential CoD field.
8214 */
8215 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008216 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008217
Johan Hedberg1dc06092012-01-15 21:01:23 +02008218 memset(buf, 0, sizeof(buf));
8219
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008220 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8221 * RSSI value was reported as 0 when not available. This behavior
8222 * is kept when using device discovery. This is required for full
8223 * backwards compatibility with the API.
8224 *
8225 * However when using service discovery, the value 127 will be
8226 * returned when the RSSI is not available.
8227 */
Szymon Janc91200e92015-01-22 16:57:05 +01008228 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8229 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008230 rssi = 0;
8231
Johan Hedberg841c5642014-07-07 12:45:54 +03008232 bacpy(&ev->addr.bdaddr, bdaddr);
8233 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008234 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008235 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008236
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008237 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008238 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008239 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008240
Johan Hedberg1dc06092012-01-15 21:01:23 +02008241 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8242 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008243 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008244
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008245 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008246 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008247 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008248
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008249 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8250 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008251
Marcel Holtmann901801b2013-10-06 23:55:51 -07008252 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008253}
Johan Hedberga88a9652011-03-30 13:18:12 +03008254
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008255void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8256 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008257{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008258 struct mgmt_ev_device_found *ev;
8259 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8260 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008261
Johan Hedbergb644ba32012-01-17 21:48:47 +02008262 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008263
Johan Hedbergb644ba32012-01-17 21:48:47 +02008264 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008265
Johan Hedbergb644ba32012-01-17 21:48:47 +02008266 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008267 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008268 ev->rssi = rssi;
8269
8270 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008271 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008272
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008273 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008274
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008275 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008276}
Johan Hedberg314b2382011-04-27 10:29:57 -04008277
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008278void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008279{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008280 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008281
Andre Guedes343fb142011-11-22 17:14:19 -03008282 BT_DBG("%s discovering %u", hdev->name, discovering);
8283
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008284 memset(&ev, 0, sizeof(ev));
8285 ev.type = hdev->discovery.type;
8286 ev.discovering = discovering;
8287
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008288 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008289}
Antti Julku5e762442011-08-25 16:48:02 +03008290
Marcel Holtmann1904a852015-01-11 13:50:44 -08008291static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008292{
8293 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008294}
8295
8296void mgmt_reenable_advertising(struct hci_dev *hdev)
8297{
8298 struct hci_request req;
Florian Grandeleb6f95f2015-06-18 03:16:51 +02008299 u8 instance;
Marcel Holtmann5976e602013-10-06 04:08:14 -07008300
Arman Uguray24b4f382015-03-23 15:57:12 -07008301 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8302 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008303 return;
8304
Florian Grandeleb6f95f2015-06-18 03:16:51 +02008305 instance = get_current_adv_instance(hdev);
8306
Marcel Holtmann5976e602013-10-06 04:08:14 -07008307 hci_req_init(&req, hdev);
Florian Grandeleb6f95f2015-06-18 03:16:51 +02008308
8309 if (instance) {
8310 schedule_adv_instance(&req, instance, true);
8311 } else {
8312 update_adv_data(&req);
8313 update_scan_rsp_data(&req);
8314 enable_advertising(&req);
8315 }
8316
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008317 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008318}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008319
8320static struct hci_mgmt_chan chan = {
8321 .channel = HCI_CHANNEL_CONTROL,
8322 .handler_count = ARRAY_SIZE(mgmt_handlers),
8323 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008324 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008325};
8326
8327int mgmt_init(void)
8328{
8329 return hci_mgmt_chan_register(&chan);
8330}
8331
8332void mgmt_exit(void)
8333{
8334 hci_mgmt_chan_unregister(&chan);
8335}