blob: cc4e76f8be0e21c13e9229f059fd5b3a09a4340e [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 Holtmannbeb1c212015-03-10 14:04:52 -070041#define MGMT_REVISION 9
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 Holtmannedd38962014-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
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300271static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
272 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200273{
274 struct mgmt_rp_read_version rp;
275
276 BT_DBG("sock %p", sk);
277
278 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700279 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200280
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200281 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
282 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200283}
284
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300285static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
286 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200287{
288 struct mgmt_rp_read_commands *rp;
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700289 u16 num_commands, num_events;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200290 size_t rp_size;
291 int i, err;
292
293 BT_DBG("sock %p", sk);
294
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700295 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
296 num_commands = ARRAY_SIZE(mgmt_commands);
297 num_events = ARRAY_SIZE(mgmt_events);
298 } else {
299 num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
300 num_events = ARRAY_SIZE(mgmt_untrusted_events);
301 }
302
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200303 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
304
305 rp = kmalloc(rp_size, GFP_KERNEL);
306 if (!rp)
307 return -ENOMEM;
308
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700309 rp->num_commands = cpu_to_le16(num_commands);
310 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700312 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
313 __le16 *opcode = rp->opcodes;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200314
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700315 for (i = 0; i < num_commands; i++, opcode++)
316 put_unaligned_le16(mgmt_commands[i], opcode);
317
318 for (i = 0; i < num_events; i++, opcode++)
319 put_unaligned_le16(mgmt_events[i], opcode);
320 } else {
321 __le16 *opcode = rp->opcodes;
322
323 for (i = 0; i < num_commands; i++, opcode++)
324 put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
325
326 for (i = 0; i < num_events; i++, opcode++)
327 put_unaligned_le16(mgmt_untrusted_events[i], opcode);
328 }
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200329
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200330 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
331 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 kfree(rp);
333
334 return err;
335}
336
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300337static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
338 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200341 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200342 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200343 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300344 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345
346 BT_DBG("sock %p", sk);
347
348 read_lock(&hci_dev_list_lock);
349
350 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300351 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200352 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700353 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700354 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200355 }
356
Johan Hedberga38528f2011-01-22 06:46:43 +0200357 rp_len = sizeof(*rp) + (2 * count);
358 rp = kmalloc(rp_len, GFP_ATOMIC);
359 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100360 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100362 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363
Johan Hedberg476e44c2012-10-19 20:10:46 +0300364 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200365 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700366 if (hci_dev_test_flag(d, HCI_SETUP) ||
367 hci_dev_test_flag(d, HCI_CONFIG) ||
368 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200369 continue;
370
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200371 /* Devices marked as raw-only are neither configured
372 * nor unconfigured controllers.
373 */
374 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700375 continue;
376
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200377 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700378 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700379 rp->index[count++] = cpu_to_le16(d->id);
380 BT_DBG("Added hci%u", d->id);
381 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 }
383
Johan Hedberg476e44c2012-10-19 20:10:46 +0300384 rp->num_controllers = cpu_to_le16(count);
385 rp_len = sizeof(*rp) + (2 * count);
386
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200387 read_unlock(&hci_dev_list_lock);
388
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200389 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
390 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200391
Johan Hedberga38528f2011-01-22 06:46:43 +0200392 kfree(rp);
393
394 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200395}
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
398 void *data, u16 data_len)
399{
400 struct mgmt_rp_read_unconf_index_list *rp;
401 struct hci_dev *d;
402 size_t rp_len;
403 u16 count;
404 int err;
405
406 BT_DBG("sock %p", sk);
407
408 read_lock(&hci_dev_list_lock);
409
410 count = 0;
411 list_for_each_entry(d, &hci_dev_list, list) {
412 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700413 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200414 count++;
415 }
416
417 rp_len = sizeof(*rp) + (2 * count);
418 rp = kmalloc(rp_len, GFP_ATOMIC);
419 if (!rp) {
420 read_unlock(&hci_dev_list_lock);
421 return -ENOMEM;
422 }
423
424 count = 0;
425 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700426 if (hci_dev_test_flag(d, HCI_SETUP) ||
427 hci_dev_test_flag(d, HCI_CONFIG) ||
428 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200429 continue;
430
431 /* Devices marked as raw-only are neither configured
432 * nor unconfigured controllers.
433 */
434 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
435 continue;
436
437 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700438 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200439 rp->index[count++] = cpu_to_le16(d->id);
440 BT_DBG("Added hci%u", d->id);
441 }
442 }
443
444 rp->num_controllers = cpu_to_le16(count);
445 rp_len = sizeof(*rp) + (2 * count);
446
447 read_unlock(&hci_dev_list_lock);
448
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200449 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
450 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200451
452 kfree(rp);
453
454 return err;
455}
456
Marcel Holtmann96f14742015-03-14 19:27:57 -0700457static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
458 void *data, u16 data_len)
459{
460 struct mgmt_rp_read_ext_index_list *rp;
461 struct hci_dev *d;
462 size_t rp_len;
463 u16 count;
464 int err;
465
466 BT_DBG("sock %p", sk);
467
468 read_lock(&hci_dev_list_lock);
469
470 count = 0;
471 list_for_each_entry(d, &hci_dev_list, list) {
472 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
473 count++;
474 }
475
476 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
477 rp = kmalloc(rp_len, GFP_ATOMIC);
478 if (!rp) {
479 read_unlock(&hci_dev_list_lock);
480 return -ENOMEM;
481 }
482
483 count = 0;
484 list_for_each_entry(d, &hci_dev_list, list) {
485 if (hci_dev_test_flag(d, HCI_SETUP) ||
486 hci_dev_test_flag(d, HCI_CONFIG) ||
487 hci_dev_test_flag(d, HCI_USER_CHANNEL))
488 continue;
489
490 /* Devices marked as raw-only are neither configured
491 * nor unconfigured controllers.
492 */
493 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
494 continue;
495
496 if (d->dev_type == HCI_BREDR) {
497 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
498 rp->entry[count].type = 0x01;
499 else
500 rp->entry[count].type = 0x00;
501 } else if (d->dev_type == HCI_AMP) {
502 rp->entry[count].type = 0x02;
503 } else {
504 continue;
505 }
506
507 rp->entry[count].bus = d->bus;
508 rp->entry[count++].index = cpu_to_le16(d->id);
509 BT_DBG("Added hci%u", d->id);
510 }
511
512 rp->num_controllers = cpu_to_le16(count);
513 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
514
515 read_unlock(&hci_dev_list_lock);
516
517 /* If this command is called at least once, then all the
518 * default index and unconfigured index events are disabled
519 * and from now on only extended index events are used.
520 */
521 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
522 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
523 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
524
525 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
526 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
527
528 kfree(rp);
529
530 return err;
531}
532
Marcel Holtmanndbece372014-07-04 18:11:55 +0200533static bool is_configured(struct hci_dev *hdev)
534{
535 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700536 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200537 return false;
538
539 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
540 !bacmp(&hdev->public_addr, BDADDR_ANY))
541 return false;
542
543 return true;
544}
545
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200546static __le32 get_missing_options(struct hci_dev *hdev)
547{
548 u32 options = 0;
549
Marcel Holtmanndbece372014-07-04 18:11:55 +0200550 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700551 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200552 options |= MGMT_OPTION_EXTERNAL_CONFIG;
553
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200554 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
555 !bacmp(&hdev->public_addr, BDADDR_ANY))
556 options |= MGMT_OPTION_PUBLIC_ADDRESS;
557
558 return cpu_to_le32(options);
559}
560
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200561static int new_options(struct hci_dev *hdev, struct sock *skip)
562{
563 __le32 options = get_missing_options(hdev);
564
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700565 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
566 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200567}
568
Marcel Holtmanndbece372014-07-04 18:11:55 +0200569static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
570{
571 __le32 options = get_missing_options(hdev);
572
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200573 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
574 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200575}
576
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200577static int read_config_info(struct sock *sk, struct hci_dev *hdev,
578 void *data, u16 data_len)
579{
580 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200581 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200582
583 BT_DBG("sock %p %s", sk, hdev->name);
584
585 hci_dev_lock(hdev);
586
587 memset(&rp, 0, sizeof(rp));
588 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200589
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200590 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
591 options |= MGMT_OPTION_EXTERNAL_CONFIG;
592
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200593 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200594 options |= MGMT_OPTION_PUBLIC_ADDRESS;
595
596 rp.supported_options = cpu_to_le32(options);
597 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200598
599 hci_dev_unlock(hdev);
600
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200601 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
602 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200603}
604
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200606{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200608
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300610 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800611 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300612 settings |= MGMT_SETTING_CONNECTABLE;
613 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200614
Andre Guedesed3fa312012-07-24 15:03:46 -0300615 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500616 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
617 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_BREDR;
619 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700620
621 if (lmp_ssp_capable(hdev)) {
622 settings |= MGMT_SETTING_SSP;
623 settings |= MGMT_SETTING_HS;
624 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800625
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800626 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700628 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100629
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300630 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200631 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300632 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300633 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800635 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300636 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200637
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200638 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
639 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200640 settings |= MGMT_SETTING_CONFIGURATION;
641
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200642 return settings;
643}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200644
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200645static u32 get_current_settings(struct hci_dev *hdev)
646{
647 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200648
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200649 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100650 settings |= MGMT_SETTING_POWERED;
651
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700652 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200653 settings |= MGMT_SETTING_CONNECTABLE;
654
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700655 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500656 settings |= MGMT_SETTING_FAST_CONNECTABLE;
657
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700658 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200659 settings |= MGMT_SETTING_DISCOVERABLE;
660
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700661 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300662 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200663
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700664 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200665 settings |= MGMT_SETTING_BREDR;
666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700667 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200668 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700670 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200672
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700673 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200674 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200675
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700676 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200677 settings |= MGMT_SETTING_HS;
678
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700679 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300680 settings |= MGMT_SETTING_ADVERTISING;
681
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700682 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800683 settings |= MGMT_SETTING_SECURE_CONN;
684
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700685 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800686 settings |= MGMT_SETTING_DEBUG_KEYS;
687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700688 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200689 settings |= MGMT_SETTING_PRIVACY;
690
Marcel Holtmann93690c22015-03-06 10:11:21 -0800691 /* The current setting for static address has two purposes. The
692 * first is to indicate if the static address will be used and
693 * the second is to indicate if it is actually set.
694 *
695 * This means if the static address is not configured, this flag
Marcel Holtmann08dc0e92015-03-25 18:32:13 -0700696 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800697 * address is actually used decides if the flag is set or not.
698 *
699 * For single mode LE only controllers and dual-mode controllers
700 * with BR/EDR disabled, the existence of the static address will
701 * be evaluated.
702 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700703 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700704 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
706 if (bacmp(&hdev->static_addr, BDADDR_ANY))
707 settings |= MGMT_SETTING_STATIC_ADDRESS;
708 }
709
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200710 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200711}
712
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300713#define PNP_INFO_SVCLASS_ID 0x1200
714
Johan Hedberg213202e2013-01-27 00:31:33 +0200715static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 4)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 u16 uuid16;
725
726 if (uuid->size != 16)
727 continue;
728
729 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
730 if (uuid16 < 0x1100)
731 continue;
732
733 if (uuid16 == PNP_INFO_SVCLASS_ID)
734 continue;
735
736 if (!uuids_start) {
737 uuids_start = ptr;
738 uuids_start[0] = 1;
739 uuids_start[1] = EIR_UUID16_ALL;
740 ptr += 2;
741 }
742
743 /* Stop if not enough space to put next UUID */
744 if ((ptr - data) + sizeof(u16) > len) {
745 uuids_start[1] = EIR_UUID16_SOME;
746 break;
747 }
748
749 *ptr++ = (uuid16 & 0x00ff);
750 *ptr++ = (uuid16 & 0xff00) >> 8;
751 uuids_start[0] += sizeof(uuid16);
752 }
753
754 return ptr;
755}
756
Johan Hedbergcdf19632013-01-27 00:31:34 +0200757static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
758{
759 u8 *ptr = data, *uuids_start = NULL;
760 struct bt_uuid *uuid;
761
762 if (len < 6)
763 return ptr;
764
765 list_for_each_entry(uuid, &hdev->uuids, list) {
766 if (uuid->size != 32)
767 continue;
768
769 if (!uuids_start) {
770 uuids_start = ptr;
771 uuids_start[0] = 1;
772 uuids_start[1] = EIR_UUID32_ALL;
773 ptr += 2;
774 }
775
776 /* Stop if not enough space to put next UUID */
777 if ((ptr - data) + sizeof(u32) > len) {
778 uuids_start[1] = EIR_UUID32_SOME;
779 break;
780 }
781
782 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
783 ptr += sizeof(u32);
784 uuids_start[0] += sizeof(u32);
785 }
786
787 return ptr;
788}
789
Johan Hedbergc00d5752013-01-27 00:31:35 +0200790static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
791{
792 u8 *ptr = data, *uuids_start = NULL;
793 struct bt_uuid *uuid;
794
795 if (len < 18)
796 return ptr;
797
798 list_for_each_entry(uuid, &hdev->uuids, list) {
799 if (uuid->size != 128)
800 continue;
801
802 if (!uuids_start) {
803 uuids_start = ptr;
804 uuids_start[0] = 1;
805 uuids_start[1] = EIR_UUID128_ALL;
806 ptr += 2;
807 }
808
809 /* Stop if not enough space to put next UUID */
810 if ((ptr - data) + 16 > len) {
811 uuids_start[1] = EIR_UUID128_SOME;
812 break;
813 }
814
815 memcpy(ptr, uuid->uuid, 16);
816 ptr += 16;
817 uuids_start[0] += 16;
818 }
819
820 return ptr;
821}
822
Johan Hedberg333ae952015-03-17 13:48:47 +0200823static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
824{
825 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
826}
827
Johan Hedberg333ae952015-03-17 13:48:47 +0200828static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
829 struct hci_dev *hdev,
830 const void *data)
831{
832 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
833}
834
Arman Uguray4117ed72015-03-23 15:57:14 -0700835static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700836{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700837 u8 ad_len = 0;
838 size_t name_len;
839
840 name_len = strlen(hdev->dev_name);
841 if (name_len > 0) {
842 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
843
844 if (name_len > max_len) {
845 name_len = max_len;
846 ptr[1] = EIR_NAME_SHORT;
847 } else
848 ptr[1] = EIR_NAME_COMPLETE;
849
850 ptr[0] = name_len + 1;
851
852 memcpy(ptr + 2, hdev->dev_name, name_len);
853
854 ad_len += (name_len + 2);
855 ptr += (name_len + 2);
856 }
857
858 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700859}
860
Arman Uguray4117ed72015-03-23 15:57:14 -0700861static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
862{
863 /* TODO: Set the appropriate entries based on advertising instance flags
864 * here once flags other than 0 are supported.
865 */
866 memcpy(ptr, hdev->adv_instance.scan_rsp_data,
867 hdev->adv_instance.scan_rsp_len);
868
869 return hdev->adv_instance.scan_rsp_len;
870}
871
872static void update_scan_rsp_data_for_instance(struct hci_request *req,
873 u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700874{
875 struct hci_dev *hdev = req->hdev;
876 struct hci_cp_le_set_scan_rsp_data cp;
877 u8 len;
878
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700880 return;
881
882 memset(&cp, 0, sizeof(cp));
883
Arman Uguray4117ed72015-03-23 15:57:14 -0700884 if (instance)
885 len = create_instance_scan_rsp_data(hdev, cp.data);
886 else
887 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700888
Johan Hedbergeb438b52013-10-16 15:31:07 +0300889 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700890 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700891 return;
892
Johan Hedbergeb438b52013-10-16 15:31:07 +0300893 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
894 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700895
896 cp.length = len;
897
898 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
899}
900
Arman Uguray4117ed72015-03-23 15:57:14 -0700901static void update_scan_rsp_data(struct hci_request *req)
902{
903 struct hci_dev *hdev = req->hdev;
904 u8 instance;
905
906 /* The "Set Advertising" setting supersedes the "Add Advertising"
907 * setting. Here we set the scan response data based on which
908 * setting was set. When neither apply, default to the global settings,
909 * represented by instance "0".
910 */
911 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
912 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
913 instance = 0x01;
914 else
915 instance = 0x00;
916
917 update_scan_rsp_data_for_instance(req, instance);
918}
919
Johan Hedberg9a43e252013-10-20 19:00:07 +0300920static u8 get_adv_discov_flags(struct hci_dev *hdev)
921{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200922 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300923
924 /* If there's a pending mgmt command the flags will not yet have
925 * their final values, so check for this first.
926 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200927 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300928 if (cmd) {
929 struct mgmt_mode *cp = cmd->param;
930 if (cp->val == 0x01)
931 return LE_AD_GENERAL;
932 else if (cp->val == 0x02)
933 return LE_AD_LIMITED;
934 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700935 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300936 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700937 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300938 return LE_AD_GENERAL;
939 }
940
941 return 0;
942}
943
Arman Uguray24b4f382015-03-23 15:57:12 -0700944static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700945{
946 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700947
Johan Hedberg9a43e252013-10-20 19:00:07 +0300948 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700949
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700950 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700951 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700952
953 if (flags) {
954 BT_DBG("adv flags 0x%02x", flags);
955
956 ptr[0] = 2;
957 ptr[1] = EIR_FLAGS;
958 ptr[2] = flags;
959
960 ad_len += 3;
961 ptr += 3;
962 }
963
964 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
965 ptr[0] = 2;
966 ptr[1] = EIR_TX_POWER;
967 ptr[2] = (u8) hdev->adv_tx_power;
968
969 ad_len += 3;
970 ptr += 3;
971 }
972
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700973 return ad_len;
974}
975
Arman Uguray24b4f382015-03-23 15:57:12 -0700976static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
977{
Arman Ugurayb44133f2015-03-25 18:53:41 -0700978 u8 ad_len = 0, flags = 0;
979
Arman Uguray807ec772015-03-25 18:53:42 -0700980 /* The Add Advertising command allows userspace to set both the general
981 * and limited discoverable flags.
982 */
Arman Ugurayb44133f2015-03-25 18:53:41 -0700983 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV)
984 flags |= LE_AD_GENERAL;
985
Arman Uguray807ec772015-03-25 18:53:42 -0700986 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
987 flags |= LE_AD_LIMITED;
988
Arman Uguray67e0c0c2015-03-25 18:53:43 -0700989 if (flags || (hdev->adv_instance.flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
990 /* If a discovery flag wasn't provided, simply use the global
991 * settings.
992 */
993 if (!flags)
994 flags |= get_adv_discov_flags(hdev);
995
Arman Ugurayb44133f2015-03-25 18:53:41 -0700996 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
997 flags |= LE_AD_NO_BREDR;
998
999 ptr[0] = 0x02;
1000 ptr[1] = EIR_FLAGS;
1001 ptr[2] = flags;
1002
1003 ad_len += 3;
1004 ptr += 3;
1005 }
1006
Arman Uguray24b4f382015-03-23 15:57:12 -07001007 memcpy(ptr, hdev->adv_instance.adv_data,
1008 hdev->adv_instance.adv_data_len);
Arman Ugurayb44133f2015-03-25 18:53:41 -07001009 ad_len += hdev->adv_instance.adv_data_len;
Arman Uguray24b4f382015-03-23 15:57:12 -07001010
Arman Ugurayb44133f2015-03-25 18:53:41 -07001011 return ad_len;
Arman Uguray24b4f382015-03-23 15:57:12 -07001012}
1013
1014static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001015{
1016 struct hci_dev *hdev = req->hdev;
1017 struct hci_cp_le_set_adv_data cp;
1018 u8 len;
1019
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001020 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001021 return;
1022
1023 memset(&cp, 0, sizeof(cp));
1024
Arman Uguray24b4f382015-03-23 15:57:12 -07001025 if (instance)
1026 len = create_instance_adv_data(hdev, cp.data);
1027 else
1028 len = create_default_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001029
Arman Uguray24b4f382015-03-23 15:57:12 -07001030 /* There's nothing to do if the data hasn't changed */
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001031 if (hdev->adv_data_len == len &&
1032 memcmp(cp.data, hdev->adv_data, len) == 0)
1033 return;
1034
1035 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1036 hdev->adv_data_len = len;
1037
1038 cp.length = len;
1039
1040 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1041}
1042
Arman Uguraye7a685d2015-03-25 18:53:40 -07001043static u8 get_current_adv_instance(struct hci_dev *hdev)
Arman Uguray24b4f382015-03-23 15:57:12 -07001044{
Arman Uguray24b4f382015-03-23 15:57:12 -07001045 /* The "Set Advertising" setting supersedes the "Add Advertising"
1046 * setting. Here we set the advertising data based on which
1047 * setting was set. When neither apply, default to the global settings,
1048 * represented by instance "0".
1049 */
1050 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
1051 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Arman Uguraye7a685d2015-03-25 18:53:40 -07001052 return 0x01;
1053
1054 return 0x00;
1055}
1056
1057static bool get_connectable(struct hci_dev *hdev)
1058{
1059 struct mgmt_pending_cmd *cmd;
1060
1061 /* If there's a pending mgmt command the flag will not yet have
1062 * it's final value, so check for this first.
1063 */
1064 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1065 if (cmd) {
1066 struct mgmt_mode *cp = cmd->param;
1067
1068 return cp->val;
1069 }
1070
1071 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
1072}
1073
1074static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
1075{
1076 u32 flags;
1077
1078 if (instance > 0x01)
1079 return 0;
1080
1081 if (instance == 1)
1082 return hdev->adv_instance.flags;
1083
1084 flags = 0;
1085
1086 /* For instance 0, assemble the flags from global settings */
1087 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) ||
1088 get_connectable(hdev))
1089 flags |= MGMT_ADV_FLAG_CONNECTABLE;
1090
1091 /* TODO: Add the rest of the flags */
1092
1093 return flags;
1094}
1095
1096static void update_adv_data(struct hci_request *req)
1097{
1098 struct hci_dev *hdev = req->hdev;
1099 u8 instance = get_current_adv_instance(hdev);
Arman Uguray24b4f382015-03-23 15:57:12 -07001100
1101 update_adv_data_for_instance(req, instance);
1102}
1103
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001104int mgmt_update_adv_data(struct hci_dev *hdev)
1105{
1106 struct hci_request req;
1107
1108 hci_req_init(&req, hdev);
1109 update_adv_data(&req);
1110
1111 return hci_req_run(&req, NULL);
1112}
1113
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001114static void create_eir(struct hci_dev *hdev, u8 *data)
1115{
1116 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001117 size_t name_len;
1118
1119 name_len = strlen(hdev->dev_name);
1120
1121 if (name_len > 0) {
1122 /* EIR Data type */
1123 if (name_len > 48) {
1124 name_len = 48;
1125 ptr[1] = EIR_NAME_SHORT;
1126 } else
1127 ptr[1] = EIR_NAME_COMPLETE;
1128
1129 /* EIR Data length */
1130 ptr[0] = name_len + 1;
1131
1132 memcpy(ptr + 2, hdev->dev_name, name_len);
1133
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001134 ptr += (name_len + 2);
1135 }
1136
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001137 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001138 ptr[0] = 2;
1139 ptr[1] = EIR_TX_POWER;
1140 ptr[2] = (u8) hdev->inq_tx_power;
1141
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001142 ptr += 3;
1143 }
1144
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001145 if (hdev->devid_source > 0) {
1146 ptr[0] = 9;
1147 ptr[1] = EIR_DEVICE_ID;
1148
1149 put_unaligned_le16(hdev->devid_source, ptr + 2);
1150 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1151 put_unaligned_le16(hdev->devid_product, ptr + 6);
1152 put_unaligned_le16(hdev->devid_version, ptr + 8);
1153
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001154 ptr += 10;
1155 }
1156
Johan Hedberg213202e2013-01-27 00:31:33 +02001157 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001158 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001159 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001160}
1161
Johan Hedberg890ea892013-03-15 17:06:52 -05001162static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001163{
Johan Hedberg890ea892013-03-15 17:06:52 -05001164 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001165 struct hci_cp_write_eir cp;
1166
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001167 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001168 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001169
Johan Hedberg976eb202012-10-24 21:12:01 +03001170 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001171 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001172
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001173 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001174 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001175
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001176 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001177 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001178
1179 memset(&cp, 0, sizeof(cp));
1180
1181 create_eir(hdev, cp.data);
1182
1183 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001184 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001185
1186 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1187
Johan Hedberg890ea892013-03-15 17:06:52 -05001188 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001189}
1190
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001191static u8 get_service_classes(struct hci_dev *hdev)
1192{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001193 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001194 u8 val = 0;
1195
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001196 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001197 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001198
1199 return val;
1200}
1201
Johan Hedberg890ea892013-03-15 17:06:52 -05001202static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001203{
Johan Hedberg890ea892013-03-15 17:06:52 -05001204 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001205 u8 cod[3];
1206
1207 BT_DBG("%s", hdev->name);
1208
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001209 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001210 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001211
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001212 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001213 return;
1214
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001215 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001216 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001217
1218 cod[0] = hdev->minor_class;
1219 cod[1] = hdev->major_class;
1220 cod[2] = get_service_classes(hdev);
1221
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001222 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001223 cod[1] |= 0x20;
1224
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001225 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001226 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001227
Johan Hedberg890ea892013-03-15 17:06:52 -05001228 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001229}
1230
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001231static void disable_advertising(struct hci_request *req)
1232{
1233 u8 enable = 0x00;
1234
1235 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1236}
1237
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001238static void enable_advertising(struct hci_request *req)
1239{
1240 struct hci_dev *hdev = req->hdev;
1241 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001242 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001243 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001244 u8 instance;
1245 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001246
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001247 if (hci_conn_num(hdev, LE_LINK) > 0)
1248 return;
1249
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001250 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001251 disable_advertising(req);
1252
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001253 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001254 * hci_update_random_address knows that it's safe to go ahead
1255 * and write a new random address. The flag will be set back on
1256 * as soon as the SET_ADV_ENABLE HCI command completes.
1257 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001258 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001259
Arman Uguraye7a685d2015-03-25 18:53:40 -07001260 instance = get_current_adv_instance(hdev);
1261 flags = get_adv_instance_flags(hdev, instance);
1262 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001263
Johan Hedberga4858cb2014-02-25 19:56:31 +02001264 /* Set require_privacy to true only when non-connectable
1265 * advertising is used. In that case it is fine to use a
1266 * non-resolvable private address.
1267 */
1268 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001269 return;
1270
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001271 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001272 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1273 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001274 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001275 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001276 cp.channel_map = hdev->le_adv_channel_map;
1277
1278 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1279
1280 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1281}
1282
Johan Hedberg7d785252011-12-15 00:47:39 +02001283static void service_cache_off(struct work_struct *work)
1284{
1285 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001286 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001287 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001288
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001289 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001290 return;
1291
Johan Hedberg890ea892013-03-15 17:06:52 -05001292 hci_req_init(&req, hdev);
1293
Johan Hedberg7d785252011-12-15 00:47:39 +02001294 hci_dev_lock(hdev);
1295
Johan Hedberg890ea892013-03-15 17:06:52 -05001296 update_eir(&req);
1297 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001298
1299 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001300
1301 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001302}
1303
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001304static void rpa_expired(struct work_struct *work)
1305{
1306 struct hci_dev *hdev = container_of(work, struct hci_dev,
1307 rpa_expired.work);
1308 struct hci_request req;
1309
1310 BT_DBG("");
1311
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001312 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001313
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001314 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001315 return;
1316
1317 /* The generation of a new RPA and programming it into the
1318 * controller happens in the enable_advertising() function.
1319 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001320 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001321 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001322 hci_req_run(&req, NULL);
1323}
1324
Johan Hedberg6a919082012-02-28 06:17:26 +02001325static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001326{
Marcel Holtmann238be782015-03-13 02:11:06 -07001327 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001328 return;
1329
Johan Hedberg4f87da82012-03-02 19:55:56 +02001330 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001331 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001332
Johan Hedberg4f87da82012-03-02 19:55:56 +02001333 /* Non-mgmt controlled devices get this bit set
1334 * implicitly so that pairing works for them, however
1335 * for mgmt we require user-space to explicitly enable
1336 * it
1337 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001338 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001339}
1340
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001341static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001342 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001343{
1344 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001345
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001346 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001347
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001348 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001349
Johan Hedberg03811012010-12-08 00:21:06 +02001350 memset(&rp, 0, sizeof(rp));
1351
Johan Hedberg03811012010-12-08 00:21:06 +02001352 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001353
1354 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001355 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001356
1357 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1358 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1359
1360 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001361
1362 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001363 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001364
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001365 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001366
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001367 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1368 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001369}
1370
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001371static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001372{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001373 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001374
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001375 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1376 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001377}
1378
Marcel Holtmann1904a852015-01-11 13:50:44 -08001379static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001380{
1381 BT_DBG("%s status 0x%02x", hdev->name, status);
1382
Johan Hedberga3172b72014-02-28 09:33:44 +02001383 if (hci_conn_count(hdev) == 0) {
1384 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001385 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001386 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001387}
1388
Johan Hedberg23a48092014-07-08 16:05:06 +03001389static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001390{
1391 struct hci_dev *hdev = req->hdev;
1392 struct hci_cp_remote_name_req_cancel cp;
1393 struct inquiry_entry *e;
1394
1395 switch (hdev->discovery.state) {
1396 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001397 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001398 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001399
1400 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001401 cancel_delayed_work(&hdev->le_scan_disable);
1402 hci_req_add_le_scan_disable(req);
1403 }
1404
Johan Hedberg23a48092014-07-08 16:05:06 +03001405 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001406
1407 case DISCOVERY_RESOLVING:
1408 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1409 NAME_PENDING);
1410 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001411 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001412
1413 bacpy(&cp.bdaddr, &e->data.bdaddr);
1414 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1415 &cp);
1416
Johan Hedberg23a48092014-07-08 16:05:06 +03001417 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001418
1419 default:
1420 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001421 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001422 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001423 return true;
1424 }
1425
Johan Hedberg21a60d32014-06-10 14:05:58 +03001426 break;
1427 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001428
1429 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001430}
1431
Arman Uguray912098a2015-03-23 15:57:15 -07001432static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1433 u8 instance)
1434{
1435 struct mgmt_ev_advertising_added ev;
1436
1437 ev.instance = instance;
1438
1439 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1440}
1441
1442static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1443 u8 instance)
1444{
1445 struct mgmt_ev_advertising_removed ev;
1446
1447 ev.instance = instance;
1448
1449 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1450}
1451
1452static void clear_adv_instance(struct hci_dev *hdev)
1453{
1454 struct hci_request req;
1455
1456 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1457 return;
1458
1459 if (hdev->adv_instance.timeout)
1460 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
1461
1462 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1463 advertising_removed(NULL, hdev, 1);
1464 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1465
1466 if (!hdev_is_powered(hdev) ||
1467 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1468 return;
1469
1470 hci_req_init(&req, hdev);
1471 disable_advertising(&req);
1472 hci_req_run(&req, NULL);
1473}
1474
Johan Hedberg8b064a32014-02-24 14:52:22 +02001475static int clean_up_hci_state(struct hci_dev *hdev)
1476{
1477 struct hci_request req;
1478 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001479 bool discov_stopped;
1480 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001481
1482 hci_req_init(&req, hdev);
1483
1484 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1485 test_bit(HCI_PSCAN, &hdev->flags)) {
1486 u8 scan = 0x00;
1487 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1488 }
1489
Arman Uguray912098a2015-03-23 15:57:15 -07001490 if (hdev->adv_instance.timeout)
1491 clear_adv_instance(hdev);
1492
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001493 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001494 disable_advertising(&req);
1495
Johan Hedberg23a48092014-07-08 16:05:06 +03001496 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001497
1498 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1499 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001500 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001501
Johan Hedbergc9910d02014-02-27 14:35:12 +02001502 switch (conn->state) {
1503 case BT_CONNECTED:
1504 case BT_CONFIG:
1505 dc.handle = cpu_to_le16(conn->handle);
1506 dc.reason = 0x15; /* Terminated due to Power Off */
1507 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1508 break;
1509 case BT_CONNECT:
1510 if (conn->type == LE_LINK)
1511 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1512 0, NULL);
1513 else if (conn->type == ACL_LINK)
1514 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1515 6, &conn->dst);
1516 break;
1517 case BT_CONNECT2:
1518 bacpy(&rej.bdaddr, &conn->dst);
1519 rej.reason = 0x15; /* Terminated due to Power Off */
1520 if (conn->type == ACL_LINK)
1521 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1522 sizeof(rej), &rej);
1523 else if (conn->type == SCO_LINK)
1524 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1525 sizeof(rej), &rej);
1526 break;
1527 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001528 }
1529
Johan Hedberg23a48092014-07-08 16:05:06 +03001530 err = hci_req_run(&req, clean_up_hci_complete);
1531 if (!err && discov_stopped)
1532 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1533
1534 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001535}
1536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001537static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001538 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001539{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001540 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001541 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001542 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001543
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001544 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001545
Johan Hedberga7e80f22013-01-09 16:05:19 +02001546 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001547 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1548 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001549
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001550 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001551
Johan Hedberg333ae952015-03-17 13:48:47 +02001552 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001553 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1554 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001555 goto failed;
1556 }
1557
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001558 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001559 cancel_delayed_work(&hdev->power_off);
1560
1561 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001562 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1563 data, len);
1564 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001565 goto failed;
1566 }
1567 }
1568
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001569 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001570 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001571 goto failed;
1572 }
1573
Johan Hedberg03811012010-12-08 00:21:06 +02001574 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1575 if (!cmd) {
1576 err = -ENOMEM;
1577 goto failed;
1578 }
1579
Johan Hedberg8b064a32014-02-24 14:52:22 +02001580 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001581 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001582 err = 0;
1583 } else {
1584 /* Disconnect connections, stop scans, etc */
1585 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001586 if (!err)
1587 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1588 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001589
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590 /* ENODATA means there were no HCI commands queued */
1591 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001592 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001593 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1594 err = 0;
1595 }
1596 }
Johan Hedberg03811012010-12-08 00:21:06 +02001597
1598failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001599 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001600 return err;
1601}
1602
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001603static int new_settings(struct hci_dev *hdev, struct sock *skip)
1604{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001605 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001606
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001607 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1608 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001609}
1610
Johan Hedberg91a668b2014-07-09 13:28:26 +03001611int mgmt_new_settings(struct hci_dev *hdev)
1612{
1613 return new_settings(hdev, NULL);
1614}
1615
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001616struct cmd_lookup {
1617 struct sock *sk;
1618 struct hci_dev *hdev;
1619 u8 mgmt_status;
1620};
1621
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001622static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001623{
1624 struct cmd_lookup *match = data;
1625
1626 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1627
1628 list_del(&cmd->list);
1629
1630 if (match->sk == NULL) {
1631 match->sk = cmd->sk;
1632 sock_hold(match->sk);
1633 }
1634
1635 mgmt_pending_free(cmd);
1636}
1637
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001638static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001639{
1640 u8 *status = data;
1641
Johan Hedberga69e8372015-03-06 21:08:53 +02001642 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001643 mgmt_pending_remove(cmd);
1644}
1645
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001646static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001647{
1648 if (cmd->cmd_complete) {
1649 u8 *status = data;
1650
1651 cmd->cmd_complete(cmd, *status);
1652 mgmt_pending_remove(cmd);
1653
1654 return;
1655 }
1656
1657 cmd_status_rsp(cmd, data);
1658}
1659
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001660static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001661{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001662 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1663 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001664}
1665
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001666static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001667{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001668 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1669 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001670}
1671
Johan Hedberge6fe7982013-10-02 15:45:22 +03001672static u8 mgmt_bredr_support(struct hci_dev *hdev)
1673{
1674 if (!lmp_bredr_capable(hdev))
1675 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001676 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001677 return MGMT_STATUS_REJECTED;
1678 else
1679 return MGMT_STATUS_SUCCESS;
1680}
1681
1682static u8 mgmt_le_support(struct hci_dev *hdev)
1683{
1684 if (!lmp_le_capable(hdev))
1685 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001686 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001687 return MGMT_STATUS_REJECTED;
1688 else
1689 return MGMT_STATUS_SUCCESS;
1690}
1691
Marcel Holtmann1904a852015-01-11 13:50:44 -08001692static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1693 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001694{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001695 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001696 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001697 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001698 bool changed;
1699
1700 BT_DBG("status 0x%02x", status);
1701
1702 hci_dev_lock(hdev);
1703
Johan Hedberg333ae952015-03-17 13:48:47 +02001704 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001705 if (!cmd)
1706 goto unlock;
1707
1708 if (status) {
1709 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001710 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001711 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001712 goto remove_cmd;
1713 }
1714
1715 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001716 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001717 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001718
1719 if (hdev->discov_timeout > 0) {
1720 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1721 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1722 to);
1723 }
1724 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001725 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001726 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001727
1728 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1729
1730 if (changed)
1731 new_settings(hdev, cmd->sk);
1732
Marcel Holtmann970ba522013-10-15 06:33:57 -07001733 /* When the discoverable mode gets changed, make sure
1734 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001735 * bit correctly set. Also update page scan based on whitelist
1736 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001737 */
1738 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001739 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001740 update_class(&req);
1741 hci_req_run(&req, NULL);
1742
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001743remove_cmd:
1744 mgmt_pending_remove(cmd);
1745
1746unlock:
1747 hci_dev_unlock(hdev);
1748}
1749
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001750static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001751 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001752{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001753 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001754 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001755 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001756 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001757 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001758 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001759
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001760 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001761
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001762 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1763 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001764 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1765 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001766
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001767 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001768 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1769 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001770
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001771 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001772
1773 /* Disabling discoverable requires that no timeout is set,
1774 * and enabling limited discoverable requires a timeout.
1775 */
1776 if ((cp->val == 0x00 && timeout > 0) ||
1777 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001778 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1779 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001780
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001781 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001782
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001783 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001784 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1785 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001786 goto failed;
1787 }
1788
Johan Hedberg333ae952015-03-17 13:48:47 +02001789 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1790 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001791 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1792 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001793 goto failed;
1794 }
1795
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001796 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001797 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1798 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001799 goto failed;
1800 }
1801
1802 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001803 bool changed = false;
1804
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001805 /* Setting limited discoverable when powered off is
1806 * not a valid operation since it requires a timeout
1807 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1808 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001809 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001810 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001811 changed = true;
1812 }
1813
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001814 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001815 if (err < 0)
1816 goto failed;
1817
1818 if (changed)
1819 err = new_settings(hdev, sk);
1820
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001821 goto failed;
1822 }
1823
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001824 /* If the current mode is the same, then just update the timeout
1825 * value with the new value. And if only the timeout gets updated,
1826 * then no need for any HCI transactions.
1827 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001828 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1829 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1830 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001831 cancel_delayed_work(&hdev->discov_off);
1832 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001833
Marcel Holtmann36261542013-10-15 08:28:51 -07001834 if (cp->val && hdev->discov_timeout > 0) {
1835 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001836 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001837 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001838 }
1839
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001840 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001841 goto failed;
1842 }
1843
1844 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1845 if (!cmd) {
1846 err = -ENOMEM;
1847 goto failed;
1848 }
1849
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001850 /* Cancel any potential discoverable timeout that might be
1851 * still active and store new timeout value. The arming of
1852 * the timeout happens in the complete handler.
1853 */
1854 cancel_delayed_work(&hdev->discov_off);
1855 hdev->discov_timeout = timeout;
1856
Johan Hedbergb456f872013-10-19 23:38:22 +03001857 /* Limited discoverable mode */
1858 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001859 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001860 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001861 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001862
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001863 hci_req_init(&req, hdev);
1864
Johan Hedberg9a43e252013-10-20 19:00:07 +03001865 /* The procedure for LE-only controllers is much simpler - just
1866 * update the advertising data.
1867 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001868 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001869 goto update_ad;
1870
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001871 scan = SCAN_PAGE;
1872
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001873 if (cp->val) {
1874 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001875
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001876 if (cp->val == 0x02) {
1877 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001878 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001879 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1880 hci_cp.iac_lap[1] = 0x8b;
1881 hci_cp.iac_lap[2] = 0x9e;
1882 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1883 hci_cp.iac_lap[4] = 0x8b;
1884 hci_cp.iac_lap[5] = 0x9e;
1885 } else {
1886 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001887 hci_cp.num_iac = 1;
1888 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1889 hci_cp.iac_lap[1] = 0x8b;
1890 hci_cp.iac_lap[2] = 0x9e;
1891 }
1892
1893 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1894 (hci_cp.num_iac * 3) + 1, &hci_cp);
1895
1896 scan |= SCAN_INQUIRY;
1897 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001898 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001899 }
1900
1901 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001902
Johan Hedberg9a43e252013-10-20 19:00:07 +03001903update_ad:
1904 update_adv_data(&req);
1905
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001906 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001907 if (err < 0)
1908 mgmt_pending_remove(cmd);
1909
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001910failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001911 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001912 return err;
1913}
1914
Johan Hedberg406d7802013-03-15 17:07:09 -05001915static void write_fast_connectable(struct hci_request *req, bool enable)
1916{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001917 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001918 struct hci_cp_write_page_scan_activity acp;
1919 u8 type;
1920
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001921 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001922 return;
1923
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001924 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1925 return;
1926
Johan Hedberg406d7802013-03-15 17:07:09 -05001927 if (enable) {
1928 type = PAGE_SCAN_TYPE_INTERLACED;
1929
1930 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001931 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001932 } else {
1933 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1934
1935 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001936 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001937 }
1938
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001939 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001940
Johan Hedbergbd98b992013-03-15 17:07:13 -05001941 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1942 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1943 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1944 sizeof(acp), &acp);
1945
1946 if (hdev->page_scan_type != type)
1947 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001948}
1949
Marcel Holtmann1904a852015-01-11 13:50:44 -08001950static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1951 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001952{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001953 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001954 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001955 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001956
1957 BT_DBG("status 0x%02x", status);
1958
1959 hci_dev_lock(hdev);
1960
Johan Hedberg333ae952015-03-17 13:48:47 +02001961 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001962 if (!cmd)
1963 goto unlock;
1964
Johan Hedberg37438c12013-10-14 16:20:05 +03001965 if (status) {
1966 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001967 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001968 goto remove_cmd;
1969 }
1970
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001971 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001972 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001973 conn_changed = !hci_dev_test_and_set_flag(hdev,
1974 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001975 discov_changed = false;
1976 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001977 conn_changed = hci_dev_test_and_clear_flag(hdev,
1978 HCI_CONNECTABLE);
1979 discov_changed = hci_dev_test_and_clear_flag(hdev,
1980 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001981 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001982
Johan Hedberg2b76f452013-03-15 17:07:04 -05001983 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1984
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001985 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001986 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001987 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001988 if (discov_changed)
1989 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001990 hci_update_background_scan(hdev);
1991 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001992
Johan Hedberg37438c12013-10-14 16:20:05 +03001993remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001994 mgmt_pending_remove(cmd);
1995
1996unlock:
1997 hci_dev_unlock(hdev);
1998}
1999
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002000static int set_connectable_update_settings(struct hci_dev *hdev,
2001 struct sock *sk, u8 val)
2002{
2003 bool changed = false;
2004 int err;
2005
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002006 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002007 changed = true;
2008
2009 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002010 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002011 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002012 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2013 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002014 }
2015
2016 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2017 if (err < 0)
2018 return err;
2019
Johan Hedberg562064e2014-07-08 16:35:34 +03002020 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002021 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002022 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002023 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002024 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002025
2026 return 0;
2027}
2028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002029static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002030 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002031{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002032 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002033 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002034 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002035 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002036 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002037
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002038 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002039
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002040 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2041 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002042 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2043 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002044
Johan Hedberga7e80f22013-01-09 16:05:19 +02002045 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002046 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2047 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002048
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002049 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002050
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002051 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002052 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002053 goto failed;
2054 }
2055
Johan Hedberg333ae952015-03-17 13:48:47 +02002056 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2057 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002058 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2059 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002060 goto failed;
2061 }
2062
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002063 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2064 if (!cmd) {
2065 err = -ENOMEM;
2066 goto failed;
2067 }
2068
Johan Hedberg2b76f452013-03-15 17:07:04 -05002069 hci_req_init(&req, hdev);
2070
Johan Hedberg9a43e252013-10-20 19:00:07 +03002071 /* If BR/EDR is not enabled and we disable advertising as a
2072 * by-product of disabling connectable, we need to update the
2073 * advertising flags.
2074 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002075 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002076 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002077 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2078 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002079 }
2080 update_adv_data(&req);
2081 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002082 if (cp->val) {
2083 scan = SCAN_PAGE;
2084 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002085 /* If we don't have any whitelist entries just
2086 * disable all scanning. If there are entries
2087 * and we had both page and inquiry scanning
2088 * enabled then fall back to only page scanning.
2089 * Otherwise no changes are needed.
2090 */
2091 if (list_empty(&hdev->whitelist))
2092 scan = SCAN_DISABLED;
2093 else if (test_bit(HCI_ISCAN, &hdev->flags))
2094 scan = SCAN_PAGE;
2095 else
2096 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002097
2098 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002099 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002100 cancel_delayed_work(&hdev->discov_off);
2101 }
2102
2103 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2104 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002105
Johan Hedberg3bd27242014-07-28 20:53:58 +03002106no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002107 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002108 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002109 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002110
Johan Hedberg2b76f452013-03-15 17:07:04 -05002111 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002112 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002113 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002114 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002115 err = set_connectable_update_settings(hdev, sk,
2116 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002117 goto failed;
2118 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002119
2120failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002121 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002122 return err;
2123}
2124
Johan Hedbergb2939472014-07-30 09:22:23 +03002125static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002126 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002127{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002128 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002129 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002130 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002131
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002132 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002133
Johan Hedberga7e80f22013-01-09 16:05:19 +02002134 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002135 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2136 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002137
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002138 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002139
2140 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002141 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002142 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002143 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002144
Johan Hedbergb2939472014-07-30 09:22:23 +03002145 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002146 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002147 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002148
Marcel Holtmann55594352013-10-06 16:11:57 -07002149 if (changed)
2150 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002151
Marcel Holtmann55594352013-10-06 16:11:57 -07002152unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002153 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002154 return err;
2155}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002156
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002157static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2158 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002159{
2160 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002161 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002162 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002163 int err;
2164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002165 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002166
Johan Hedberge6fe7982013-10-02 15:45:22 +03002167 status = mgmt_bredr_support(hdev);
2168 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002169 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2170 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002171
Johan Hedberga7e80f22013-01-09 16:05:19 +02002172 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002173 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2174 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002175
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002176 hci_dev_lock(hdev);
2177
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002178 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002179 bool changed = false;
2180
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002181 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002182 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002183 changed = true;
2184 }
2185
2186 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2187 if (err < 0)
2188 goto failed;
2189
2190 if (changed)
2191 err = new_settings(hdev, sk);
2192
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002193 goto failed;
2194 }
2195
Johan Hedberg333ae952015-03-17 13:48:47 +02002196 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002197 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2198 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002199 goto failed;
2200 }
2201
2202 val = !!cp->val;
2203
2204 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2205 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2206 goto failed;
2207 }
2208
2209 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2210 if (!cmd) {
2211 err = -ENOMEM;
2212 goto failed;
2213 }
2214
2215 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2216 if (err < 0) {
2217 mgmt_pending_remove(cmd);
2218 goto failed;
2219 }
2220
2221failed:
2222 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002223 return err;
2224}
2225
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002226static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002227{
2228 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002229 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002230 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002231 int err;
2232
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002233 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002234
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002235 status = mgmt_bredr_support(hdev);
2236 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002237 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002238
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002239 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002240 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2241 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002242
Johan Hedberga7e80f22013-01-09 16:05:19 +02002243 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002244 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2245 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002246
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002247 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002248
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002249 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002250 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002251
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002252 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002253 changed = !hci_dev_test_and_set_flag(hdev,
2254 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002255 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002256 changed = hci_dev_test_and_clear_flag(hdev,
2257 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002258 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002259 changed = hci_dev_test_and_clear_flag(hdev,
2260 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002261 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002262 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002263 }
2264
2265 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2266 if (err < 0)
2267 goto failed;
2268
2269 if (changed)
2270 err = new_settings(hdev, sk);
2271
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002272 goto failed;
2273 }
2274
Johan Hedberg333ae952015-03-17 13:48:47 +02002275 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002276 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2277 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002278 goto failed;
2279 }
2280
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002281 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002282 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2283 goto failed;
2284 }
2285
2286 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2287 if (!cmd) {
2288 err = -ENOMEM;
2289 goto failed;
2290 }
2291
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002292 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002293 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2294 sizeof(cp->val), &cp->val);
2295
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002296 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002297 if (err < 0) {
2298 mgmt_pending_remove(cmd);
2299 goto failed;
2300 }
2301
2302failed:
2303 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002304 return err;
2305}
2306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002307static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002308{
2309 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002310 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002311 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002312 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002313
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002314 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002315
Johan Hedberge6fe7982013-10-02 15:45:22 +03002316 status = mgmt_bredr_support(hdev);
2317 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002318 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002319
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002320 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002321 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2322 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002323
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002324 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002325 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2326 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002327
Johan Hedberga7e80f22013-01-09 16:05:19 +02002328 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002329 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2330 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002331
Marcel Holtmannee392692013-10-01 22:59:23 -07002332 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002333
Johan Hedberg333ae952015-03-17 13:48:47 +02002334 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002335 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2336 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002337 goto unlock;
2338 }
2339
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002340 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002341 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002342 } else {
2343 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002344 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2345 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002346 goto unlock;
2347 }
2348
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002349 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002350 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002351
2352 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2353 if (err < 0)
2354 goto unlock;
2355
2356 if (changed)
2357 err = new_settings(hdev, sk);
2358
2359unlock:
2360 hci_dev_unlock(hdev);
2361 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002362}
2363
Marcel Holtmann1904a852015-01-11 13:50:44 -08002364static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002365{
2366 struct cmd_lookup match = { NULL, hdev };
2367
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302368 hci_dev_lock(hdev);
2369
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002370 if (status) {
2371 u8 mgmt_err = mgmt_status(status);
2372
2373 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2374 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302375 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002376 }
2377
2378 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2379
2380 new_settings(hdev, match.sk);
2381
2382 if (match.sk)
2383 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002384
2385 /* Make sure the controller has a good default for
2386 * advertising data. Restrict the update to when LE
2387 * has actually been enabled. During power on, the
2388 * update in powered_update_hci will take care of it.
2389 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002390 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002391 struct hci_request req;
2392
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002393 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002394 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002395 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002396 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002397 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002398 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302399
2400unlock:
2401 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002402}
2403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002404static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002405{
2406 struct mgmt_mode *cp = data;
2407 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002408 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002409 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002410 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002411 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002412
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002413 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002414
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002415 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002416 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2417 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002418
Johan Hedberga7e80f22013-01-09 16:05:19 +02002419 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002420 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2421 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002422
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002423 /* Bluetooth single mode LE only controllers or dual-mode
2424 * controllers configured as LE only devices, do not allow
2425 * switching LE off. These have either LE enabled explicitly
2426 * or BR/EDR has been previously switched off.
2427 *
2428 * When trying to enable an already enabled LE, then gracefully
2429 * send a positive response. Trying to disable it however will
2430 * result into rejection.
2431 */
2432 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2433 if (cp->val == 0x01)
2434 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2435
Johan Hedberga69e8372015-03-06 21:08:53 +02002436 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2437 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002438 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002439
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002440 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002441
2442 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002443 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002444
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002445 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002446 bool changed = false;
2447
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002448 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002449 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002450 changed = true;
2451 }
2452
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002453 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002454 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002455 changed = true;
2456 }
2457
Johan Hedberg06199cf2012-02-22 16:37:11 +02002458 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2459 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002460 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002461
2462 if (changed)
2463 err = new_settings(hdev, sk);
2464
Johan Hedberg1de028c2012-02-29 19:55:35 -08002465 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002466 }
2467
Johan Hedberg333ae952015-03-17 13:48:47 +02002468 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2469 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002470 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2471 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002472 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002473 }
2474
2475 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2476 if (!cmd) {
2477 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002478 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002479 }
2480
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002481 hci_req_init(&req, hdev);
2482
Johan Hedberg06199cf2012-02-22 16:37:11 +02002483 memset(&hci_cp, 0, sizeof(hci_cp));
2484
2485 if (val) {
2486 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002487 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002488 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002489 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002490 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002491 }
2492
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002493 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2494 &hci_cp);
2495
2496 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302497 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002498 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002499
Johan Hedberg1de028c2012-02-29 19:55:35 -08002500unlock:
2501 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002502 return err;
2503}
2504
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002505/* This is a helper function to test for pending mgmt commands that can
2506 * cause CoD or EIR HCI commands. We can only allow one such pending
2507 * mgmt command at a time since otherwise we cannot easily track what
2508 * the current values are, will be, and based on that calculate if a new
2509 * HCI command needs to be sent and if yes with what value.
2510 */
2511static bool pending_eir_or_class(struct hci_dev *hdev)
2512{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002513 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002514
2515 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2516 switch (cmd->opcode) {
2517 case MGMT_OP_ADD_UUID:
2518 case MGMT_OP_REMOVE_UUID:
2519 case MGMT_OP_SET_DEV_CLASS:
2520 case MGMT_OP_SET_POWERED:
2521 return true;
2522 }
2523 }
2524
2525 return false;
2526}
2527
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002528static const u8 bluetooth_base_uuid[] = {
2529 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2530 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2531};
2532
2533static u8 get_uuid_size(const u8 *uuid)
2534{
2535 u32 val;
2536
2537 if (memcmp(uuid, bluetooth_base_uuid, 12))
2538 return 128;
2539
2540 val = get_unaligned_le32(&uuid[12]);
2541 if (val > 0xffff)
2542 return 32;
2543
2544 return 16;
2545}
2546
Johan Hedberg92da6092013-03-15 17:06:55 -05002547static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2548{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002549 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002550
2551 hci_dev_lock(hdev);
2552
Johan Hedberg333ae952015-03-17 13:48:47 +02002553 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002554 if (!cmd)
2555 goto unlock;
2556
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002557 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2558 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002559
2560 mgmt_pending_remove(cmd);
2561
2562unlock:
2563 hci_dev_unlock(hdev);
2564}
2565
Marcel Holtmann1904a852015-01-11 13:50:44 -08002566static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002567{
2568 BT_DBG("status 0x%02x", status);
2569
2570 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2571}
2572
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002573static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002574{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002575 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002576 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002577 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002578 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002579 int err;
2580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002581 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002582
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002583 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002584
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002585 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002586 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2587 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002588 goto failed;
2589 }
2590
Andre Guedes92c4c202012-06-07 19:05:44 -03002591 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002592 if (!uuid) {
2593 err = -ENOMEM;
2594 goto failed;
2595 }
2596
2597 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002598 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002599 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002600
Johan Hedbergde66aa62013-01-27 00:31:27 +02002601 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002602
Johan Hedberg890ea892013-03-15 17:06:52 -05002603 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002604
Johan Hedberg890ea892013-03-15 17:06:52 -05002605 update_class(&req);
2606 update_eir(&req);
2607
Johan Hedberg92da6092013-03-15 17:06:55 -05002608 err = hci_req_run(&req, add_uuid_complete);
2609 if (err < 0) {
2610 if (err != -ENODATA)
2611 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002612
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002613 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2614 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002615 goto failed;
2616 }
2617
2618 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002619 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002620 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002621 goto failed;
2622 }
2623
2624 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002625
2626failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002627 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002628 return err;
2629}
2630
Johan Hedberg24b78d02012-02-23 23:24:30 +02002631static bool enable_service_cache(struct hci_dev *hdev)
2632{
2633 if (!hdev_is_powered(hdev))
2634 return false;
2635
Marcel Holtmann238be782015-03-13 02:11:06 -07002636 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002637 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2638 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002639 return true;
2640 }
2641
2642 return false;
2643}
2644
Marcel Holtmann1904a852015-01-11 13:50:44 -08002645static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002646{
2647 BT_DBG("status 0x%02x", status);
2648
2649 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2650}
2651
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002652static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002653 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002654{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002655 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002656 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002657 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002658 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 -05002659 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002660 int err, found;
2661
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002662 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002663
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002664 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002665
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002666 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002667 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2668 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002669 goto unlock;
2670 }
2671
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002672 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002673 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002674
Johan Hedberg24b78d02012-02-23 23:24:30 +02002675 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002676 err = mgmt_cmd_complete(sk, hdev->id,
2677 MGMT_OP_REMOVE_UUID,
2678 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002679 goto unlock;
2680 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002681
Johan Hedberg9246a862012-02-23 21:33:16 +02002682 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002683 }
2684
2685 found = 0;
2686
Johan Hedberg056341c2013-01-27 00:31:30 +02002687 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002688 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2689 continue;
2690
2691 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002692 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002693 found++;
2694 }
2695
2696 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002697 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2698 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002699 goto unlock;
2700 }
2701
Johan Hedberg9246a862012-02-23 21:33:16 +02002702update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002703 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002704
Johan Hedberg890ea892013-03-15 17:06:52 -05002705 update_class(&req);
2706 update_eir(&req);
2707
Johan Hedberg92da6092013-03-15 17:06:55 -05002708 err = hci_req_run(&req, remove_uuid_complete);
2709 if (err < 0) {
2710 if (err != -ENODATA)
2711 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002712
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002713 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2714 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002715 goto unlock;
2716 }
2717
2718 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002719 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002720 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002721 goto unlock;
2722 }
2723
2724 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002725
2726unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002727 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002728 return err;
2729}
2730
Marcel Holtmann1904a852015-01-11 13:50:44 -08002731static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002732{
2733 BT_DBG("status 0x%02x", status);
2734
2735 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2736}
2737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002738static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002739 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002740{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002741 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002742 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002743 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002744 int err;
2745
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002746 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002747
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002748 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002749 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2750 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002751
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002752 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002753
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002754 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002755 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2756 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002757 goto unlock;
2758 }
2759
2760 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002761 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2762 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002763 goto unlock;
2764 }
2765
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002766 hdev->major_class = cp->major;
2767 hdev->minor_class = cp->minor;
2768
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002769 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002770 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2771 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002772 goto unlock;
2773 }
2774
Johan Hedberg890ea892013-03-15 17:06:52 -05002775 hci_req_init(&req, hdev);
2776
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002777 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002778 hci_dev_unlock(hdev);
2779 cancel_delayed_work_sync(&hdev->service_cache);
2780 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002781 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002782 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002783
Johan Hedberg890ea892013-03-15 17:06:52 -05002784 update_class(&req);
2785
Johan Hedberg92da6092013-03-15 17:06:55 -05002786 err = hci_req_run(&req, set_class_complete);
2787 if (err < 0) {
2788 if (err != -ENODATA)
2789 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002790
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002791 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2792 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002793 goto unlock;
2794 }
2795
2796 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002797 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002798 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002799 goto unlock;
2800 }
2801
2802 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002803
Johan Hedbergb5235a62012-02-21 14:32:24 +02002804unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002805 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002806 return err;
2807}
2808
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002809static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002810 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002811{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002812 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002813 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2814 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002815 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002816 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002817 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002818
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002819 BT_DBG("request for %s", hdev->name);
2820
2821 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002822 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2823 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002824
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002825 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002826 if (key_count > max_key_count) {
2827 BT_ERR("load_link_keys: too big key_count value %u",
2828 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002829 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2830 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002831 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002832
Johan Hedberg86742e12011-11-07 23:13:38 +02002833 expected_len = sizeof(*cp) + key_count *
2834 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002835 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002836 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002837 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002838 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2839 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002840 }
2841
Johan Hedberg4ae14302013-01-20 14:27:13 +02002842 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002843 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2844 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002845
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002846 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002847 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002848
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002849 for (i = 0; i < key_count; i++) {
2850 struct mgmt_link_key_info *key = &cp->keys[i];
2851
Marcel Holtmann8e991132014-01-10 02:07:25 -08002852 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002853 return mgmt_cmd_status(sk, hdev->id,
2854 MGMT_OP_LOAD_LINK_KEYS,
2855 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002856 }
2857
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002858 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002859
2860 hci_link_keys_clear(hdev);
2861
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002862 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002863 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002864 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002865 changed = hci_dev_test_and_clear_flag(hdev,
2866 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002867
2868 if (changed)
2869 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002870
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002871 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002872 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002873
Johan Hedberg58e92932014-06-24 14:00:26 +03002874 /* Always ignore debug keys and require a new pairing if
2875 * the user wants to use them.
2876 */
2877 if (key->type == HCI_LK_DEBUG_COMBINATION)
2878 continue;
2879
Johan Hedberg7652ff62014-06-24 13:15:49 +03002880 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2881 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002882 }
2883
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002884 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002885
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002886 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002887
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002888 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002889}
2890
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002891static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002892 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002893{
2894 struct mgmt_ev_device_unpaired ev;
2895
2896 bacpy(&ev.addr.bdaddr, bdaddr);
2897 ev.addr.type = addr_type;
2898
2899 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002900 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002901}
2902
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002903static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002904 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002905{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002906 struct mgmt_cp_unpair_device *cp = data;
2907 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002908 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002909 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002910 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002911 int err;
2912
Johan Hedberga8a1d192011-11-10 15:54:38 +02002913 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002914 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2915 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002916
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002917 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002918 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2919 MGMT_STATUS_INVALID_PARAMS,
2920 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002921
Johan Hedberg118da702013-01-20 14:27:20 +02002922 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002923 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2924 MGMT_STATUS_INVALID_PARAMS,
2925 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002926
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002927 hci_dev_lock(hdev);
2928
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002929 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002930 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2931 MGMT_STATUS_NOT_POWERED, &rp,
2932 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002933 goto unlock;
2934 }
2935
Johan Hedberge0b2b272014-02-18 17:14:31 +02002936 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002937 /* If disconnection is requested, then look up the
2938 * connection. If the remote device is connected, it
2939 * will be later used to terminate the link.
2940 *
2941 * Setting it to NULL explicitly will cause no
2942 * termination of the link.
2943 */
2944 if (cp->disconnect)
2945 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2946 &cp->addr.bdaddr);
2947 else
2948 conn = NULL;
2949
Johan Hedberg124f6e32012-02-09 13:50:12 +02002950 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002951 } else {
2952 u8 addr_type;
2953
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002954 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2955 &cp->addr.bdaddr);
2956 if (conn) {
2957 /* Defer clearing up the connection parameters
2958 * until closing to give a chance of keeping
2959 * them if a repairing happens.
2960 */
2961 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2962
2963 /* If disconnection is not requested, then
2964 * clear the connection variable so that the
2965 * link is not terminated.
2966 */
2967 if (!cp->disconnect)
2968 conn = NULL;
2969 }
2970
Johan Hedberge0b2b272014-02-18 17:14:31 +02002971 if (cp->addr.type == BDADDR_LE_PUBLIC)
2972 addr_type = ADDR_LE_DEV_PUBLIC;
2973 else
2974 addr_type = ADDR_LE_DEV_RANDOM;
2975
Johan Hedberga7ec7332014-02-18 17:14:35 +02002976 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2977
Johan Hedberge0b2b272014-02-18 17:14:31 +02002978 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2979 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002980
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002981 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002982 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2983 MGMT_STATUS_NOT_PAIRED, &rp,
2984 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002985 goto unlock;
2986 }
2987
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002988 /* If the connection variable is set, then termination of the
2989 * link is requested.
2990 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002991 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002992 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2993 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002994 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002995 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002996 }
2997
Johan Hedberg124f6e32012-02-09 13:50:12 +02002998 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002999 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003000 if (!cmd) {
3001 err = -ENOMEM;
3002 goto unlock;
3003 }
3004
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003005 cmd->cmd_complete = addr_cmd_complete;
3006
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003007 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003008 dc.reason = 0x13; /* Remote User Terminated Connection */
3009 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3010 if (err < 0)
3011 mgmt_pending_remove(cmd);
3012
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003013unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003014 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003015 return err;
3016}
3017
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003018static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003019 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003020{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003021 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003022 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003023 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003024 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003025 int err;
3026
3027 BT_DBG("");
3028
Johan Hedberg06a63b12013-01-20 14:27:21 +02003029 memset(&rp, 0, sizeof(rp));
3030 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3031 rp.addr.type = cp->addr.type;
3032
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003033 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003034 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3035 MGMT_STATUS_INVALID_PARAMS,
3036 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003037
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003038 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003039
3040 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003041 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3042 MGMT_STATUS_NOT_POWERED, &rp,
3043 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003044 goto failed;
3045 }
3046
Johan Hedberg333ae952015-03-17 13:48:47 +02003047 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003048 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3049 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003050 goto failed;
3051 }
3052
Andre Guedes591f47f2012-04-24 21:02:49 -03003053 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003054 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3055 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003056 else
3057 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003058
Vishal Agarwalf9607272012-06-13 05:32:43 +05303059 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003060 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3061 MGMT_STATUS_NOT_CONNECTED, &rp,
3062 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003063 goto failed;
3064 }
3065
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003066 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003067 if (!cmd) {
3068 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003069 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003070 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003071
Johan Hedbergf5818c22014-12-05 13:36:02 +02003072 cmd->cmd_complete = generic_cmd_complete;
3073
Johan Hedberge3f2f922014-08-18 20:33:33 +03003074 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003075 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003076 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003077
3078failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003079 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003080 return err;
3081}
3082
Andre Guedes57c14772012-04-24 21:02:50 -03003083static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003084{
3085 switch (link_type) {
3086 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003087 switch (addr_type) {
3088 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003089 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003090
Johan Hedberg48264f02011-11-09 13:58:58 +02003091 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003092 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003093 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003094 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003095
Johan Hedberg4c659c32011-11-07 23:13:39 +02003096 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003097 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003098 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003099 }
3100}
3101
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003102static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3103 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003104{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003105 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003106 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003107 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003108 int err;
3109 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003110
3111 BT_DBG("");
3112
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003113 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003114
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003115 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003116 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3117 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003118 goto unlock;
3119 }
3120
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003121 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003122 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3123 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003124 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003125 }
3126
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003127 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003128 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003129 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003130 err = -ENOMEM;
3131 goto unlock;
3132 }
3133
Johan Hedberg2784eb42011-01-21 13:56:35 +02003134 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003135 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003136 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3137 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003138 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003139 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003140 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003141 continue;
3142 i++;
3143 }
3144
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003145 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003146
Johan Hedberg4c659c32011-11-07 23:13:39 +02003147 /* Recalculate length in case of filtered SCO connections, etc */
3148 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003149
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003150 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3151 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003152
Johan Hedberga38528f2011-01-22 06:46:43 +02003153 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003154
3155unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003156 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003157 return err;
3158}
3159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003160static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003161 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003162{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003163 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003164 int err;
3165
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003166 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003167 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003168 if (!cmd)
3169 return -ENOMEM;
3170
Johan Hedbergd8457692012-02-17 14:24:57 +02003171 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003172 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003173 if (err < 0)
3174 mgmt_pending_remove(cmd);
3175
3176 return err;
3177}
3178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003179static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003180 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003181{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003182 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003183 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003184 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003185 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003186 int err;
3187
3188 BT_DBG("");
3189
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003190 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003191
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003192 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003193 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3194 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003195 goto failed;
3196 }
3197
Johan Hedbergd8457692012-02-17 14:24:57 +02003198 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003199 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003200 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3201 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003202 goto failed;
3203 }
3204
3205 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003206 struct mgmt_cp_pin_code_neg_reply ncp;
3207
3208 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003209
3210 BT_ERR("PIN code is not 16 bytes long");
3211
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003212 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003213 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003214 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3215 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003216
3217 goto failed;
3218 }
3219
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003220 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003221 if (!cmd) {
3222 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003223 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003224 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003225
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003226 cmd->cmd_complete = addr_cmd_complete;
3227
Johan Hedbergd8457692012-02-17 14:24:57 +02003228 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003229 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003230 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003231
3232 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3233 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003234 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003235
3236failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003237 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003238 return err;
3239}
3240
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003241static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3242 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003243{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003244 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003245
3246 BT_DBG("");
3247
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003248 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003249 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3250 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003251
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003252 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003253
3254 hdev->io_capability = cp->io_capability;
3255
3256 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003257 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003258
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003259 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003260
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003261 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3262 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003263}
3264
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003265static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003266{
3267 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003268 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003269
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003270 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003271 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3272 continue;
3273
Johan Hedberge9a416b2011-02-19 12:05:56 -03003274 if (cmd->user_data != conn)
3275 continue;
3276
3277 return cmd;
3278 }
3279
3280 return NULL;
3281}
3282
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003283static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003284{
3285 struct mgmt_rp_pair_device rp;
3286 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003287 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003288
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003289 bacpy(&rp.addr.bdaddr, &conn->dst);
3290 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003291
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003292 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3293 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003294
3295 /* So we don't get further callbacks for this connection */
3296 conn->connect_cfm_cb = NULL;
3297 conn->security_cfm_cb = NULL;
3298 conn->disconn_cfm_cb = NULL;
3299
David Herrmann76a68ba2013-04-06 20:28:37 +02003300 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003301
3302 /* The device is paired so there is no need to remove
3303 * its connection parameters anymore.
3304 */
3305 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003306
3307 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003308
3309 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003310}
3311
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003312void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3313{
3314 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003315 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003316
3317 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003318 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003319 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003320 mgmt_pending_remove(cmd);
3321 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003322}
3323
Johan Hedberge9a416b2011-02-19 12:05:56 -03003324static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3325{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003326 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003327
3328 BT_DBG("status %u", status);
3329
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003330 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003331 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003332 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003333 return;
3334 }
3335
3336 cmd->cmd_complete(cmd, mgmt_status(status));
3337 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003338}
3339
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003340static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303341{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003342 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303343
3344 BT_DBG("status %u", status);
3345
3346 if (!status)
3347 return;
3348
3349 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003350 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303351 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003352 return;
3353 }
3354
3355 cmd->cmd_complete(cmd, mgmt_status(status));
3356 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303357}
3358
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003359static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003360 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003361{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003362 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003363 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003364 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003365 u8 sec_level, auth_type;
3366 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003367 int err;
3368
3369 BT_DBG("");
3370
Szymon Jancf950a30e2013-01-18 12:48:07 +01003371 memset(&rp, 0, sizeof(rp));
3372 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3373 rp.addr.type = cp->addr.type;
3374
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003375 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003376 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3377 MGMT_STATUS_INVALID_PARAMS,
3378 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003379
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003380 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003381 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3382 MGMT_STATUS_INVALID_PARAMS,
3383 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003384
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003385 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003386
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003387 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003388 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3389 MGMT_STATUS_NOT_POWERED, &rp,
3390 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003391 goto unlock;
3392 }
3393
Johan Hedberg55e76b32015-03-10 22:34:40 +02003394 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3395 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3396 MGMT_STATUS_ALREADY_PAIRED, &rp,
3397 sizeof(rp));
3398 goto unlock;
3399 }
3400
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003401 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003402 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003403
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003404 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003405 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3406 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003407 } else {
3408 u8 addr_type;
3409
3410 /* Convert from L2CAP channel address type to HCI address type
3411 */
3412 if (cp->addr.type == BDADDR_LE_PUBLIC)
3413 addr_type = ADDR_LE_DEV_PUBLIC;
3414 else
3415 addr_type = ADDR_LE_DEV_RANDOM;
3416
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003417 /* When pairing a new device, it is expected to remember
3418 * this device for future connections. Adding the connection
3419 * parameter information ahead of time allows tracking
3420 * of the slave preferred values and will speed up any
3421 * further connection establishment.
3422 *
3423 * If connection parameters already exist, then they
3424 * will be kept and this function does nothing.
3425 */
3426 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3427
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003428 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003429 sec_level, HCI_LE_CONN_TIMEOUT,
3430 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003431 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003432
Ville Tervo30e76272011-02-22 16:10:53 -03003433 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003434 int status;
3435
3436 if (PTR_ERR(conn) == -EBUSY)
3437 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003438 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3439 status = MGMT_STATUS_NOT_SUPPORTED;
3440 else if (PTR_ERR(conn) == -ECONNREFUSED)
3441 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003442 else
3443 status = MGMT_STATUS_CONNECT_FAILED;
3444
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003445 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3446 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003447 goto unlock;
3448 }
3449
3450 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003451 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003452 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3453 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003454 goto unlock;
3455 }
3456
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003457 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003458 if (!cmd) {
3459 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003460 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003461 goto unlock;
3462 }
3463
Johan Hedberg04ab2742014-12-05 13:36:04 +02003464 cmd->cmd_complete = pairing_complete;
3465
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003466 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003467 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003468 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003469 conn->security_cfm_cb = pairing_complete_cb;
3470 conn->disconn_cfm_cb = pairing_complete_cb;
3471 } else {
3472 conn->connect_cfm_cb = le_pairing_complete_cb;
3473 conn->security_cfm_cb = le_pairing_complete_cb;
3474 conn->disconn_cfm_cb = le_pairing_complete_cb;
3475 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003476
Johan Hedberge9a416b2011-02-19 12:05:56 -03003477 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003478 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003479
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003480 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003481 hci_conn_security(conn, sec_level, auth_type, true)) {
3482 cmd->cmd_complete(cmd, 0);
3483 mgmt_pending_remove(cmd);
3484 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003485
3486 err = 0;
3487
3488unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003489 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003490 return err;
3491}
3492
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003493static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3494 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003495{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003496 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003497 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003498 struct hci_conn *conn;
3499 int err;
3500
3501 BT_DBG("");
3502
Johan Hedberg28424702012-02-02 04:02:29 +02003503 hci_dev_lock(hdev);
3504
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003505 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003506 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3507 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003508 goto unlock;
3509 }
3510
Johan Hedberg333ae952015-03-17 13:48:47 +02003511 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003512 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003513 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3514 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003515 goto unlock;
3516 }
3517
3518 conn = cmd->user_data;
3519
3520 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003521 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3522 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003523 goto unlock;
3524 }
3525
Johan Hedberga511b352014-12-11 21:45:45 +02003526 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3527 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003528
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003529 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3530 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003531unlock:
3532 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003533 return err;
3534}
3535
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003536static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003537 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003538 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003539{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003540 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003541 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003542 int err;
3543
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003544 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003545
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003546 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003547 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3548 MGMT_STATUS_NOT_POWERED, addr,
3549 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003550 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003551 }
3552
Johan Hedberg1707c602013-03-15 17:07:15 -05003553 if (addr->type == BDADDR_BREDR)
3554 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003555 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003556 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003557
Johan Hedberg272d90d2012-02-09 15:26:12 +02003558 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003559 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3560 MGMT_STATUS_NOT_CONNECTED, addr,
3561 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003562 goto done;
3563 }
3564
Johan Hedberg1707c602013-03-15 17:07:15 -05003565 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003566 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003567 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003568 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3569 MGMT_STATUS_SUCCESS, addr,
3570 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003571 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003572 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3573 MGMT_STATUS_FAILED, addr,
3574 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003575
Brian Gix47c15e22011-11-16 13:53:14 -08003576 goto done;
3577 }
3578
Johan Hedberg1707c602013-03-15 17:07:15 -05003579 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003580 if (!cmd) {
3581 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003582 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003583 }
3584
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003585 cmd->cmd_complete = addr_cmd_complete;
3586
Brian Gix0df4c182011-11-16 13:53:13 -08003587 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003588 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3589 struct hci_cp_user_passkey_reply cp;
3590
Johan Hedberg1707c602013-03-15 17:07:15 -05003591 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003592 cp.passkey = passkey;
3593 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3594 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003595 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3596 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003597
Johan Hedberga664b5b2011-02-19 12:06:02 -03003598 if (err < 0)
3599 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003600
Brian Gix0df4c182011-11-16 13:53:13 -08003601done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003602 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003603 return err;
3604}
3605
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303606static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3607 void *data, u16 len)
3608{
3609 struct mgmt_cp_pin_code_neg_reply *cp = data;
3610
3611 BT_DBG("");
3612
Johan Hedberg1707c602013-03-15 17:07:15 -05003613 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303614 MGMT_OP_PIN_CODE_NEG_REPLY,
3615 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3616}
3617
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003618static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3619 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003620{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003621 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003622
3623 BT_DBG("");
3624
3625 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003626 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3627 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003628
Johan Hedberg1707c602013-03-15 17:07:15 -05003629 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003630 MGMT_OP_USER_CONFIRM_REPLY,
3631 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003632}
3633
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003634static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003635 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003636{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003637 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003638
3639 BT_DBG("");
3640
Johan Hedberg1707c602013-03-15 17:07:15 -05003641 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003642 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3643 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003644}
3645
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003646static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3647 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003648{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003649 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003650
3651 BT_DBG("");
3652
Johan Hedberg1707c602013-03-15 17:07:15 -05003653 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003654 MGMT_OP_USER_PASSKEY_REPLY,
3655 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003656}
3657
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003658static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003659 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003660{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003661 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003662
3663 BT_DBG("");
3664
Johan Hedberg1707c602013-03-15 17:07:15 -05003665 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003666 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3667 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003668}
3669
Johan Hedberg13928972013-03-15 17:07:00 -05003670static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003671{
Johan Hedberg13928972013-03-15 17:07:00 -05003672 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003673 struct hci_cp_write_local_name cp;
3674
Johan Hedberg13928972013-03-15 17:07:00 -05003675 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003676
Johan Hedberg890ea892013-03-15 17:06:52 -05003677 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003678}
3679
Marcel Holtmann1904a852015-01-11 13:50:44 -08003680static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003681{
3682 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003683 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003684
3685 BT_DBG("status 0x%02x", status);
3686
3687 hci_dev_lock(hdev);
3688
Johan Hedberg333ae952015-03-17 13:48:47 +02003689 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003690 if (!cmd)
3691 goto unlock;
3692
3693 cp = cmd->param;
3694
3695 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003696 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3697 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003698 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003699 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3700 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003701
3702 mgmt_pending_remove(cmd);
3703
3704unlock:
3705 hci_dev_unlock(hdev);
3706}
3707
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003708static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003709 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003710{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003711 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003712 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003713 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003714 int err;
3715
3716 BT_DBG("");
3717
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003718 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003719
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003720 /* If the old values are the same as the new ones just return a
3721 * direct command complete event.
3722 */
3723 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3724 !memcmp(hdev->short_name, cp->short_name,
3725 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003726 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3727 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003728 goto failed;
3729 }
3730
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003731 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003732
Johan Hedbergb5235a62012-02-21 14:32:24 +02003733 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003734 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003735
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003736 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3737 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003738 if (err < 0)
3739 goto failed;
3740
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003741 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3742 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003743
Johan Hedbergb5235a62012-02-21 14:32:24 +02003744 goto failed;
3745 }
3746
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003747 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003748 if (!cmd) {
3749 err = -ENOMEM;
3750 goto failed;
3751 }
3752
Johan Hedberg13928972013-03-15 17:07:00 -05003753 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3754
Johan Hedberg890ea892013-03-15 17:06:52 -05003755 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003756
3757 if (lmp_bredr_capable(hdev)) {
3758 update_name(&req);
3759 update_eir(&req);
3760 }
3761
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003762 /* The name is stored in the scan response data and so
3763 * no need to udpate the advertising data here.
3764 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003765 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003766 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003767
Johan Hedberg13928972013-03-15 17:07:00 -05003768 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003769 if (err < 0)
3770 mgmt_pending_remove(cmd);
3771
3772failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003773 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003774 return err;
3775}
3776
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003777static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003778 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003779{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003780 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003781 int err;
3782
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003783 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003784
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003785 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003786
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003787 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003788 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3789 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003790 goto unlock;
3791 }
3792
Andre Guedes9a1a1992012-07-24 15:03:48 -03003793 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003794 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3795 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003796 goto unlock;
3797 }
3798
Johan Hedberg333ae952015-03-17 13:48:47 +02003799 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003800 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3801 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003802 goto unlock;
3803 }
3804
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003805 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003806 if (!cmd) {
3807 err = -ENOMEM;
3808 goto unlock;
3809 }
3810
Johan Hedberg710f11c2014-05-26 11:21:22 +03003811 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003812 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3813 0, NULL);
3814 else
3815 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3816
Szymon Jancc35938b2011-03-22 13:12:21 +01003817 if (err < 0)
3818 mgmt_pending_remove(cmd);
3819
3820unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003821 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003822 return err;
3823}
3824
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003825static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003826 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003827{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003828 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003829 int err;
3830
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003831 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003832
Johan Hedberg5d57e792015-01-23 10:10:38 +02003833 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003834 return mgmt_cmd_complete(sk, hdev->id,
3835 MGMT_OP_ADD_REMOTE_OOB_DATA,
3836 MGMT_STATUS_INVALID_PARAMS,
3837 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003838
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003839 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003840
Marcel Holtmannec109112014-01-10 02:07:30 -08003841 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3842 struct mgmt_cp_add_remote_oob_data *cp = data;
3843 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003844
Johan Hedbergc19a4952014-11-17 20:52:19 +02003845 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003846 err = mgmt_cmd_complete(sk, hdev->id,
3847 MGMT_OP_ADD_REMOTE_OOB_DATA,
3848 MGMT_STATUS_INVALID_PARAMS,
3849 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003850 goto unlock;
3851 }
3852
Marcel Holtmannec109112014-01-10 02:07:30 -08003853 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003854 cp->addr.type, cp->hash,
3855 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003856 if (err < 0)
3857 status = MGMT_STATUS_FAILED;
3858 else
3859 status = MGMT_STATUS_SUCCESS;
3860
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003861 err = mgmt_cmd_complete(sk, hdev->id,
3862 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3863 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003864 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3865 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003866 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003867 u8 status;
3868
Johan Hedberg86df9202014-10-26 20:52:27 +01003869 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003870 /* Enforce zero-valued 192-bit parameters as
3871 * long as legacy SMP OOB isn't implemented.
3872 */
3873 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3874 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003875 err = mgmt_cmd_complete(sk, hdev->id,
3876 MGMT_OP_ADD_REMOTE_OOB_DATA,
3877 MGMT_STATUS_INVALID_PARAMS,
3878 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003879 goto unlock;
3880 }
3881
Johan Hedberg86df9202014-10-26 20:52:27 +01003882 rand192 = NULL;
3883 hash192 = NULL;
3884 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003885 /* In case one of the P-192 values is set to zero,
3886 * then just disable OOB data for P-192.
3887 */
3888 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3889 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3890 rand192 = NULL;
3891 hash192 = NULL;
3892 } else {
3893 rand192 = cp->rand192;
3894 hash192 = cp->hash192;
3895 }
3896 }
3897
3898 /* In case one of the P-256 values is set to zero, then just
3899 * disable OOB data for P-256.
3900 */
3901 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3902 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3903 rand256 = NULL;
3904 hash256 = NULL;
3905 } else {
3906 rand256 = cp->rand256;
3907 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003908 }
3909
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003910 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003911 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003912 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003913 if (err < 0)
3914 status = MGMT_STATUS_FAILED;
3915 else
3916 status = MGMT_STATUS_SUCCESS;
3917
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003918 err = mgmt_cmd_complete(sk, hdev->id,
3919 MGMT_OP_ADD_REMOTE_OOB_DATA,
3920 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003921 } else {
3922 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003923 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3924 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003925 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003926
Johan Hedbergc19a4952014-11-17 20:52:19 +02003927unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003928 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003929 return err;
3930}
3931
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003932static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003933 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003934{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003935 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003936 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003937 int err;
3938
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003939 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003940
Johan Hedbergc19a4952014-11-17 20:52:19 +02003941 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003942 return mgmt_cmd_complete(sk, hdev->id,
3943 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3944 MGMT_STATUS_INVALID_PARAMS,
3945 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003946
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003947 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003948
Johan Hedbergeedbd582014-11-15 09:34:23 +02003949 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3950 hci_remote_oob_data_clear(hdev);
3951 status = MGMT_STATUS_SUCCESS;
3952 goto done;
3953 }
3954
Johan Hedberg6928a922014-10-26 20:46:09 +01003955 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003956 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003957 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003958 else
Szymon Janca6785be2012-12-13 15:11:21 +01003959 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003960
Johan Hedbergeedbd582014-11-15 09:34:23 +02003961done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003962 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3963 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003964
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003965 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003966 return err;
3967}
3968
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003969static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
3970{
3971 struct hci_dev *hdev = req->hdev;
3972 struct hci_cp_inquiry cp;
3973 /* General inquiry access code (GIAC) */
3974 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3975
3976 *status = mgmt_bredr_support(hdev);
3977 if (*status)
3978 return false;
3979
3980 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
3981 *status = MGMT_STATUS_BUSY;
3982 return false;
3983 }
3984
3985 hci_inquiry_cache_flush(hdev);
3986
3987 memset(&cp, 0, sizeof(cp));
3988 memcpy(&cp.lap, lap, sizeof(cp.lap));
3989 cp.length = DISCOV_BREDR_INQUIRY_LEN;
3990
3991 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
3992
3993 return true;
3994}
3995
3996static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003997{
Marcel Holtmann80190442014-12-04 11:36:36 +01003998 struct hci_dev *hdev = req->hdev;
3999 struct hci_cp_le_set_scan_param param_cp;
4000 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004001 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004002 int err;
4003
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004004 *status = mgmt_le_support(hdev);
4005 if (*status)
4006 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004007
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004008 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4009 /* Don't let discovery abort an outgoing connection attempt
4010 * that's using directed advertising.
4011 */
4012 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4013 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004014 return false;
4015 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004016
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004017 disable_advertising(req);
4018 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004019
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004020 /* If controller is scanning, it means the background scanning is
4021 * running. Thus, we should temporarily stop it in order to set the
4022 * discovery scanning parameters.
4023 */
4024 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4025 hci_req_add_le_scan_disable(req);
4026
4027 /* All active scans will be done with either a resolvable private
4028 * address (when privacy feature has been enabled) or non-resolvable
4029 * private address.
4030 */
4031 err = hci_update_random_address(req, true, &own_addr_type);
4032 if (err < 0) {
4033 *status = MGMT_STATUS_FAILED;
4034 return false;
4035 }
4036
4037 memset(&param_cp, 0, sizeof(param_cp));
4038 param_cp.type = LE_SCAN_ACTIVE;
4039 param_cp.interval = cpu_to_le16(interval);
4040 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4041 param_cp.own_address_type = own_addr_type;
4042
4043 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4044 &param_cp);
4045
4046 memset(&enable_cp, 0, sizeof(enable_cp));
4047 enable_cp.enable = LE_SCAN_ENABLE;
4048 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4049
4050 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4051 &enable_cp);
4052
4053 return true;
4054}
4055
4056static bool trigger_discovery(struct hci_request *req, u8 *status)
4057{
4058 struct hci_dev *hdev = req->hdev;
4059
4060 switch (hdev->discovery.type) {
4061 case DISCOV_TYPE_BREDR:
4062 if (!trigger_bredr_inquiry(req, status))
4063 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004064 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004065
Marcel Holtmann80190442014-12-04 11:36:36 +01004066 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004067 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4068 &hdev->quirks)) {
4069 /* During simultaneous discovery, we double LE scan
4070 * interval. We must leave some time for the controller
4071 * to do BR/EDR inquiry.
4072 */
4073 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4074 status))
4075 return false;
4076
4077 if (!trigger_bredr_inquiry(req, status))
4078 return false;
4079
4080 return true;
4081 }
4082
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004083 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004084 *status = MGMT_STATUS_NOT_SUPPORTED;
4085 return false;
4086 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004087 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004088
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004089 case DISCOV_TYPE_LE:
4090 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004091 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004092 break;
4093
4094 default:
4095 *status = MGMT_STATUS_INVALID_PARAMS;
4096 return false;
4097 }
4098
4099 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004100}
4101
Marcel Holtmann1904a852015-01-11 13:50:44 -08004102static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4103 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004104{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004105 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004106 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004107
Andre Guedes7c307722013-04-30 15:29:28 -03004108 BT_DBG("status %d", status);
4109
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004110 hci_dev_lock(hdev);
4111
Johan Hedberg333ae952015-03-17 13:48:47 +02004112 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004113 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004114 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004115
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004116 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004117 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004118 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004119 }
4120
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004121 if (status) {
4122 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4123 goto unlock;
4124 }
4125
Andre Guedes7c307722013-04-30 15:29:28 -03004126 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004127
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004128 /* If the scan involves LE scan, pick proper timeout to schedule
4129 * hdev->le_scan_disable that will stop it.
4130 */
Andre Guedes7c307722013-04-30 15:29:28 -03004131 switch (hdev->discovery.type) {
4132 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004133 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004134 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004135 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004136 /* When running simultaneous discovery, the LE scanning time
4137 * should occupy the whole discovery time sine BR/EDR inquiry
4138 * and LE scanning are scheduled by the controller.
4139 *
4140 * For interleaving discovery in comparison, BR/EDR inquiry
4141 * and LE scanning are done sequentially with separate
4142 * timeouts.
4143 */
4144 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4145 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4146 else
4147 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004148 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004149 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004150 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004151 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004152 default:
4153 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004154 timeout = 0;
4155 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004156 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004157
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004158 if (timeout) {
4159 /* When service discovery is used and the controller has
4160 * a strict duplicate filter, it is important to remember
4161 * the start and duration of the scan. This is required
4162 * for restarting scanning during the discovery phase.
4163 */
4164 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4165 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004166 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004167 hdev->discovery.scan_start = jiffies;
4168 hdev->discovery.scan_duration = timeout;
4169 }
4170
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004171 queue_delayed_work(hdev->workqueue,
4172 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004173 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004174
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004175unlock:
4176 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004177}
4178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004179static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004180 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004181{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004182 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004183 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004184 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004185 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004186 int err;
4187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004188 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004189
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004190 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004191
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004192 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004193 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4194 MGMT_STATUS_NOT_POWERED,
4195 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004196 goto failed;
4197 }
4198
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004199 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004200 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004201 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4202 MGMT_STATUS_BUSY, &cp->type,
4203 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004204 goto failed;
4205 }
4206
Johan Hedberg2922a942014-12-05 13:36:06 +02004207 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004208 if (!cmd) {
4209 err = -ENOMEM;
4210 goto failed;
4211 }
4212
Johan Hedberg2922a942014-12-05 13:36:06 +02004213 cmd->cmd_complete = generic_cmd_complete;
4214
Marcel Holtmann22078802014-12-05 11:45:22 +01004215 /* Clear the discovery filter first to free any previously
4216 * allocated memory for the UUID list.
4217 */
4218 hci_discovery_filter_clear(hdev);
4219
Andre Guedes4aab14e2012-02-17 20:39:36 -03004220 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004221 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004222
Andre Guedes7c307722013-04-30 15:29:28 -03004223 hci_req_init(&req, hdev);
4224
Marcel Holtmann80190442014-12-04 11:36:36 +01004225 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004226 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4227 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004228 mgmt_pending_remove(cmd);
4229 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004230 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004231
Andre Guedes7c307722013-04-30 15:29:28 -03004232 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004233 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004234 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004235 goto failed;
4236 }
4237
4238 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004239
4240failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004241 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004242 return err;
4243}
4244
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004245static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4246 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004247{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004248 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4249 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004250}
4251
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004252static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4253 void *data, u16 len)
4254{
4255 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004256 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004257 struct hci_request req;
4258 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4259 u16 uuid_count, expected_len;
4260 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004261 int err;
4262
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004263 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004264
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004265 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004266
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004267 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004268 err = mgmt_cmd_complete(sk, hdev->id,
4269 MGMT_OP_START_SERVICE_DISCOVERY,
4270 MGMT_STATUS_NOT_POWERED,
4271 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004272 goto failed;
4273 }
4274
4275 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004276 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004277 err = mgmt_cmd_complete(sk, hdev->id,
4278 MGMT_OP_START_SERVICE_DISCOVERY,
4279 MGMT_STATUS_BUSY, &cp->type,
4280 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004281 goto failed;
4282 }
4283
4284 uuid_count = __le16_to_cpu(cp->uuid_count);
4285 if (uuid_count > max_uuid_count) {
4286 BT_ERR("service_discovery: too big uuid_count value %u",
4287 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004288 err = mgmt_cmd_complete(sk, hdev->id,
4289 MGMT_OP_START_SERVICE_DISCOVERY,
4290 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4291 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004292 goto failed;
4293 }
4294
4295 expected_len = sizeof(*cp) + uuid_count * 16;
4296 if (expected_len != len) {
4297 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4298 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004299 err = mgmt_cmd_complete(sk, hdev->id,
4300 MGMT_OP_START_SERVICE_DISCOVERY,
4301 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4302 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004303 goto failed;
4304 }
4305
4306 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004307 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004308 if (!cmd) {
4309 err = -ENOMEM;
4310 goto failed;
4311 }
4312
Johan Hedberg2922a942014-12-05 13:36:06 +02004313 cmd->cmd_complete = service_discovery_cmd_complete;
4314
Marcel Holtmann22078802014-12-05 11:45:22 +01004315 /* Clear the discovery filter first to free any previously
4316 * allocated memory for the UUID list.
4317 */
4318 hci_discovery_filter_clear(hdev);
4319
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004320 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004321 hdev->discovery.type = cp->type;
4322 hdev->discovery.rssi = cp->rssi;
4323 hdev->discovery.uuid_count = uuid_count;
4324
4325 if (uuid_count > 0) {
4326 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4327 GFP_KERNEL);
4328 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004329 err = mgmt_cmd_complete(sk, hdev->id,
4330 MGMT_OP_START_SERVICE_DISCOVERY,
4331 MGMT_STATUS_FAILED,
4332 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004333 mgmt_pending_remove(cmd);
4334 goto failed;
4335 }
4336 }
4337
4338 hci_req_init(&req, hdev);
4339
4340 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004341 err = mgmt_cmd_complete(sk, hdev->id,
4342 MGMT_OP_START_SERVICE_DISCOVERY,
4343 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004344 mgmt_pending_remove(cmd);
4345 goto failed;
4346 }
4347
4348 err = hci_req_run(&req, start_discovery_complete);
4349 if (err < 0) {
4350 mgmt_pending_remove(cmd);
4351 goto failed;
4352 }
4353
4354 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4355
4356failed:
4357 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004358 return err;
4359}
4360
Marcel Holtmann1904a852015-01-11 13:50:44 -08004361static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004362{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004363 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004364
Andre Guedes0e05bba2013-04-30 15:29:33 -03004365 BT_DBG("status %d", status);
4366
4367 hci_dev_lock(hdev);
4368
Johan Hedberg333ae952015-03-17 13:48:47 +02004369 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004370 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004371 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004372 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004373 }
4374
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004375 if (!status)
4376 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004377
Andre Guedes0e05bba2013-04-30 15:29:33 -03004378 hci_dev_unlock(hdev);
4379}
4380
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004381static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004382 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004383{
Johan Hedbergd9306502012-02-20 23:25:18 +02004384 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004385 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004386 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004387 int err;
4388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004389 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004390
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004391 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004392
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004393 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004394 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4395 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4396 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004397 goto unlock;
4398 }
4399
4400 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004401 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4402 MGMT_STATUS_INVALID_PARAMS,
4403 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004404 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004405 }
4406
Johan Hedberg2922a942014-12-05 13:36:06 +02004407 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004408 if (!cmd) {
4409 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004410 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004411 }
4412
Johan Hedberg2922a942014-12-05 13:36:06 +02004413 cmd->cmd_complete = generic_cmd_complete;
4414
Andre Guedes0e05bba2013-04-30 15:29:33 -03004415 hci_req_init(&req, hdev);
4416
Johan Hedberg21a60d32014-06-10 14:05:58 +03004417 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004418
Johan Hedberg21a60d32014-06-10 14:05:58 +03004419 err = hci_req_run(&req, stop_discovery_complete);
4420 if (!err) {
4421 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004422 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004423 }
4424
Johan Hedberg21a60d32014-06-10 14:05:58 +03004425 mgmt_pending_remove(cmd);
4426
4427 /* If no HCI commands were sent we're done */
4428 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004429 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4430 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004431 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4432 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004433
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004434unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004435 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004436 return err;
4437}
4438
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004439static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004440 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004441{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004442 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004443 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004444 int err;
4445
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004446 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004447
Johan Hedberg561aafb2012-01-04 13:31:59 +02004448 hci_dev_lock(hdev);
4449
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004450 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004451 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4452 MGMT_STATUS_FAILED, &cp->addr,
4453 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004454 goto failed;
4455 }
4456
Johan Hedberga198e7b2012-02-17 14:27:06 +02004457 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004458 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004459 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4460 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4461 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004462 goto failed;
4463 }
4464
4465 if (cp->name_known) {
4466 e->name_state = NAME_KNOWN;
4467 list_del(&e->list);
4468 } else {
4469 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004470 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004471 }
4472
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004473 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4474 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004475
4476failed:
4477 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004478 return err;
4479}
4480
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004481static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004482 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004483{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004484 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004485 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004486 int err;
4487
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004488 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004489
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004490 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004491 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4492 MGMT_STATUS_INVALID_PARAMS,
4493 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004494
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004495 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004496
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004497 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4498 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004499 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004500 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004501 goto done;
4502 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004503
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004504 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4505 sk);
4506 status = MGMT_STATUS_SUCCESS;
4507
4508done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004509 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4510 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004511
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004512 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004513
4514 return err;
4515}
4516
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004517static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004518 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004519{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004520 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004521 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004522 int err;
4523
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004524 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004525
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004526 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004527 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4528 MGMT_STATUS_INVALID_PARAMS,
4529 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004530
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004531 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004532
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004533 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4534 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004535 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004536 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004537 goto done;
4538 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004539
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004540 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4541 sk);
4542 status = MGMT_STATUS_SUCCESS;
4543
4544done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004545 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4546 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004547
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004548 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004549
4550 return err;
4551}
4552
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004553static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4554 u16 len)
4555{
4556 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004557 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004558 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004559 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004560
4561 BT_DBG("%s", hdev->name);
4562
Szymon Jancc72d4b82012-03-16 16:02:57 +01004563 source = __le16_to_cpu(cp->source);
4564
4565 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004566 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4567 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004568
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004569 hci_dev_lock(hdev);
4570
Szymon Jancc72d4b82012-03-16 16:02:57 +01004571 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004572 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4573 hdev->devid_product = __le16_to_cpu(cp->product);
4574 hdev->devid_version = __le16_to_cpu(cp->version);
4575
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004576 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4577 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004578
Johan Hedberg890ea892013-03-15 17:06:52 -05004579 hci_req_init(&req, hdev);
4580 update_eir(&req);
4581 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004582
4583 hci_dev_unlock(hdev);
4584
4585 return err;
4586}
4587
Arman Uguray24b4f382015-03-23 15:57:12 -07004588static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4589 u16 opcode)
4590{
4591 BT_DBG("status %d", status);
4592}
4593
Marcel Holtmann1904a852015-01-11 13:50:44 -08004594static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4595 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004596{
4597 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004598 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004599
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304600 hci_dev_lock(hdev);
4601
Johan Hedberg4375f102013-09-25 13:26:10 +03004602 if (status) {
4603 u8 mgmt_err = mgmt_status(status);
4604
4605 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4606 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304607 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004608 }
4609
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004610 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004611 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004612 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004613 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004614
Johan Hedberg4375f102013-09-25 13:26:10 +03004615 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4616 &match);
4617
4618 new_settings(hdev, match.sk);
4619
4620 if (match.sk)
4621 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304622
Arman Uguray24b4f382015-03-23 15:57:12 -07004623 /* If "Set Advertising" was just disabled and instance advertising was
4624 * set up earlier, then enable the advertising instance.
4625 */
4626 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4627 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4628 goto unlock;
4629
4630 hci_req_init(&req, hdev);
4631
4632 update_adv_data(&req);
4633 enable_advertising(&req);
4634
4635 if (hci_req_run(&req, enable_advertising_instance) < 0)
4636 BT_ERR("Failed to re-configure advertising");
4637
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304638unlock:
4639 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004640}
4641
Marcel Holtmann21b51872013-10-10 09:47:53 -07004642static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4643 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004644{
4645 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004646 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004647 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004648 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004649 int err;
4650
4651 BT_DBG("request for %s", hdev->name);
4652
Johan Hedberge6fe7982013-10-02 15:45:22 +03004653 status = mgmt_le_support(hdev);
4654 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004655 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4656 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004657
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004658 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004659 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4660 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004661
4662 hci_dev_lock(hdev);
4663
4664 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004665
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004666 /* The following conditions are ones which mean that we should
4667 * not do any HCI communication but directly send a mgmt
4668 * response to user space (after toggling the flag if
4669 * necessary).
4670 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004671 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004672 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4673 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004674 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004675 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004676 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004677 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004678
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004679 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004680 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004681 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004682 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004683 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004684 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004685 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004686 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004687 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004688 }
4689
4690 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4691 if (err < 0)
4692 goto unlock;
4693
4694 if (changed)
4695 err = new_settings(hdev, sk);
4696
4697 goto unlock;
4698 }
4699
Johan Hedberg333ae952015-03-17 13:48:47 +02004700 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4701 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004702 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4703 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004704 goto unlock;
4705 }
4706
4707 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4708 if (!cmd) {
4709 err = -ENOMEM;
4710 goto unlock;
4711 }
4712
4713 hci_req_init(&req, hdev);
4714
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004715 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004716 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004717 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004718 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004719
Arman Uguray24b4f382015-03-23 15:57:12 -07004720 if (val) {
4721 /* Switch to instance "0" for the Set Advertising setting. */
4722 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004723 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004724 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004725 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004726 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004727 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004728
4729 err = hci_req_run(&req, set_advertising_complete);
4730 if (err < 0)
4731 mgmt_pending_remove(cmd);
4732
4733unlock:
4734 hci_dev_unlock(hdev);
4735 return err;
4736}
4737
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004738static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4739 void *data, u16 len)
4740{
4741 struct mgmt_cp_set_static_address *cp = data;
4742 int err;
4743
4744 BT_DBG("%s", hdev->name);
4745
Marcel Holtmann62af4442013-10-02 22:10:32 -07004746 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004747 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4748 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004749
4750 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004751 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4752 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004753
4754 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4755 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004756 return mgmt_cmd_status(sk, hdev->id,
4757 MGMT_OP_SET_STATIC_ADDRESS,
4758 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004759
4760 /* Two most significant bits shall be set */
4761 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004762 return mgmt_cmd_status(sk, hdev->id,
4763 MGMT_OP_SET_STATIC_ADDRESS,
4764 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004765 }
4766
4767 hci_dev_lock(hdev);
4768
4769 bacpy(&hdev->static_addr, &cp->bdaddr);
4770
Marcel Holtmann93690c22015-03-06 10:11:21 -08004771 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4772 if (err < 0)
4773 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004774
Marcel Holtmann93690c22015-03-06 10:11:21 -08004775 err = new_settings(hdev, sk);
4776
4777unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004778 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004779 return err;
4780}
4781
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004782static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4783 void *data, u16 len)
4784{
4785 struct mgmt_cp_set_scan_params *cp = data;
4786 __u16 interval, window;
4787 int err;
4788
4789 BT_DBG("%s", hdev->name);
4790
4791 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004792 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4793 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004794
4795 interval = __le16_to_cpu(cp->interval);
4796
4797 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004798 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4799 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004800
4801 window = __le16_to_cpu(cp->window);
4802
4803 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004804 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4805 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004806
Marcel Holtmann899e1072013-10-14 09:55:32 -07004807 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004808 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4809 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004810
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004811 hci_dev_lock(hdev);
4812
4813 hdev->le_scan_interval = interval;
4814 hdev->le_scan_window = window;
4815
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004816 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4817 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004818
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004819 /* If background scan is running, restart it so new parameters are
4820 * loaded.
4821 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004822 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004823 hdev->discovery.state == DISCOVERY_STOPPED) {
4824 struct hci_request req;
4825
4826 hci_req_init(&req, hdev);
4827
4828 hci_req_add_le_scan_disable(&req);
4829 hci_req_add_le_passive_scan(&req);
4830
4831 hci_req_run(&req, NULL);
4832 }
4833
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004834 hci_dev_unlock(hdev);
4835
4836 return err;
4837}
4838
Marcel Holtmann1904a852015-01-11 13:50:44 -08004839static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4840 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004841{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004842 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004843
4844 BT_DBG("status 0x%02x", status);
4845
4846 hci_dev_lock(hdev);
4847
Johan Hedberg333ae952015-03-17 13:48:47 +02004848 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004849 if (!cmd)
4850 goto unlock;
4851
4852 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004853 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4854 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004855 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004856 struct mgmt_mode *cp = cmd->param;
4857
4858 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004859 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004860 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004861 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004862
Johan Hedberg33e38b32013-03-15 17:07:05 -05004863 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4864 new_settings(hdev, cmd->sk);
4865 }
4866
4867 mgmt_pending_remove(cmd);
4868
4869unlock:
4870 hci_dev_unlock(hdev);
4871}
4872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004873static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004874 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004875{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004876 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004877 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004878 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004879 int err;
4880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004881 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004882
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004883 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004884 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004885 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4886 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004887
Johan Hedberga7e80f22013-01-09 16:05:19 +02004888 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004889 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4890 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004891
Antti Julkuf6422ec2011-06-22 13:11:56 +03004892 hci_dev_lock(hdev);
4893
Johan Hedberg333ae952015-03-17 13:48:47 +02004894 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004895 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4896 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004897 goto unlock;
4898 }
4899
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004900 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004901 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4902 hdev);
4903 goto unlock;
4904 }
4905
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004906 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004907 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004908 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4909 hdev);
4910 new_settings(hdev, sk);
4911 goto unlock;
4912 }
4913
Johan Hedberg33e38b32013-03-15 17:07:05 -05004914 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4915 data, len);
4916 if (!cmd) {
4917 err = -ENOMEM;
4918 goto unlock;
4919 }
4920
4921 hci_req_init(&req, hdev);
4922
Johan Hedberg406d7802013-03-15 17:07:09 -05004923 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004924
4925 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004926 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004927 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4928 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004929 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004930 }
4931
Johan Hedberg33e38b32013-03-15 17:07:05 -05004932unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004933 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004934
Antti Julkuf6422ec2011-06-22 13:11:56 +03004935 return err;
4936}
4937
Marcel Holtmann1904a852015-01-11 13:50:44 -08004938static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004939{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004940 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004941
4942 BT_DBG("status 0x%02x", status);
4943
4944 hci_dev_lock(hdev);
4945
Johan Hedberg333ae952015-03-17 13:48:47 +02004946 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004947 if (!cmd)
4948 goto unlock;
4949
4950 if (status) {
4951 u8 mgmt_err = mgmt_status(status);
4952
4953 /* We need to restore the flag if related HCI commands
4954 * failed.
4955 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004956 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004957
Johan Hedberga69e8372015-03-06 21:08:53 +02004958 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004959 } else {
4960 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4961 new_settings(hdev, cmd->sk);
4962 }
4963
4964 mgmt_pending_remove(cmd);
4965
4966unlock:
4967 hci_dev_unlock(hdev);
4968}
4969
4970static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4971{
4972 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004973 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004974 struct hci_request req;
4975 int err;
4976
4977 BT_DBG("request for %s", hdev->name);
4978
4979 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004980 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4981 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004982
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004983 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004984 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4985 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004986
4987 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004988 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4989 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004990
4991 hci_dev_lock(hdev);
4992
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004993 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004994 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4995 goto unlock;
4996 }
4997
4998 if (!hdev_is_powered(hdev)) {
4999 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005000 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5001 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5002 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5003 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5004 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005005 }
5006
Marcel Holtmannce05d602015-03-13 02:11:03 -07005007 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005008
5009 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5010 if (err < 0)
5011 goto unlock;
5012
5013 err = new_settings(hdev, sk);
5014 goto unlock;
5015 }
5016
5017 /* Reject disabling when powered on */
5018 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005019 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5020 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005021 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005022 } else {
5023 /* When configuring a dual-mode controller to operate
5024 * with LE only and using a static address, then switching
5025 * BR/EDR back on is not allowed.
5026 *
5027 * Dual-mode controllers shall operate with the public
5028 * address as its identity address for BR/EDR and LE. So
5029 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005030 *
5031 * The same restrictions applies when secure connections
5032 * has been enabled. For BR/EDR this is a controller feature
5033 * while for LE it is a host stack feature. This means that
5034 * switching BR/EDR back on when secure connections has been
5035 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005036 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005037 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005038 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005039 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005040 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5041 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005042 goto unlock;
5043 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005044 }
5045
Johan Hedberg333ae952015-03-17 13:48:47 +02005046 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005047 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5048 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005049 goto unlock;
5050 }
5051
5052 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5053 if (!cmd) {
5054 err = -ENOMEM;
5055 goto unlock;
5056 }
5057
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005058 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005059 * generates the correct flags.
5060 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005061 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005062
5063 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005064
Johan Hedberg432df052014-08-01 11:13:31 +03005065 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005066 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005067
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005068 /* Since only the advertising data flags will change, there
5069 * is no need to update the scan response data.
5070 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005071 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005072
Johan Hedberg0663ca22013-10-02 13:43:14 +03005073 err = hci_req_run(&req, set_bredr_complete);
5074 if (err < 0)
5075 mgmt_pending_remove(cmd);
5076
5077unlock:
5078 hci_dev_unlock(hdev);
5079 return err;
5080}
5081
Johan Hedberga1443f52015-01-23 15:42:46 +02005082static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5083{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005084 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005085 struct mgmt_mode *cp;
5086
5087 BT_DBG("%s status %u", hdev->name, status);
5088
5089 hci_dev_lock(hdev);
5090
Johan Hedberg333ae952015-03-17 13:48:47 +02005091 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005092 if (!cmd)
5093 goto unlock;
5094
5095 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005096 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5097 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005098 goto remove;
5099 }
5100
5101 cp = cmd->param;
5102
5103 switch (cp->val) {
5104 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005105 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5106 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005107 break;
5108 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005109 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005110 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005111 break;
5112 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005113 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5114 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005115 break;
5116 }
5117
5118 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5119 new_settings(hdev, cmd->sk);
5120
5121remove:
5122 mgmt_pending_remove(cmd);
5123unlock:
5124 hci_dev_unlock(hdev);
5125}
5126
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005127static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5128 void *data, u16 len)
5129{
5130 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005131 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005132 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005133 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005134 int err;
5135
5136 BT_DBG("request for %s", hdev->name);
5137
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005138 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005139 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005140 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5141 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005142
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005143 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005144 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005145 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005146 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5147 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005148
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005149 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005150 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005151 MGMT_STATUS_INVALID_PARAMS);
5152
5153 hci_dev_lock(hdev);
5154
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005155 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005156 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005157 bool changed;
5158
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005159 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005160 changed = !hci_dev_test_and_set_flag(hdev,
5161 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005162 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005163 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005164 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005165 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005166 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005167 changed = hci_dev_test_and_clear_flag(hdev,
5168 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005169 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005170 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005171
5172 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5173 if (err < 0)
5174 goto failed;
5175
5176 if (changed)
5177 err = new_settings(hdev, sk);
5178
5179 goto failed;
5180 }
5181
Johan Hedberg333ae952015-03-17 13:48:47 +02005182 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005183 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5184 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005185 goto failed;
5186 }
5187
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005188 val = !!cp->val;
5189
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005190 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5191 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005192 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5193 goto failed;
5194 }
5195
5196 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5197 if (!cmd) {
5198 err = -ENOMEM;
5199 goto failed;
5200 }
5201
Johan Hedberga1443f52015-01-23 15:42:46 +02005202 hci_req_init(&req, hdev);
5203 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5204 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005205 if (err < 0) {
5206 mgmt_pending_remove(cmd);
5207 goto failed;
5208 }
5209
5210failed:
5211 hci_dev_unlock(hdev);
5212 return err;
5213}
5214
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005215static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5216 void *data, u16 len)
5217{
5218 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005219 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005220 int err;
5221
5222 BT_DBG("request for %s", hdev->name);
5223
Johan Hedbergb97109792014-06-24 14:00:28 +03005224 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005225 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5226 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005227
5228 hci_dev_lock(hdev);
5229
5230 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005231 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005232 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005233 changed = hci_dev_test_and_clear_flag(hdev,
5234 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005235
Johan Hedbergb97109792014-06-24 14:00:28 +03005236 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005237 use_changed = !hci_dev_test_and_set_flag(hdev,
5238 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005239 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005240 use_changed = hci_dev_test_and_clear_flag(hdev,
5241 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005242
5243 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005244 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005245 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5246 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5247 sizeof(mode), &mode);
5248 }
5249
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005250 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5251 if (err < 0)
5252 goto unlock;
5253
5254 if (changed)
5255 err = new_settings(hdev, sk);
5256
5257unlock:
5258 hci_dev_unlock(hdev);
5259 return err;
5260}
5261
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005262static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5263 u16 len)
5264{
5265 struct mgmt_cp_set_privacy *cp = cp_data;
5266 bool changed;
5267 int err;
5268
5269 BT_DBG("request for %s", hdev->name);
5270
5271 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005272 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5273 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005274
5275 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005276 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5277 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005278
5279 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005280 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5281 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005282
5283 hci_dev_lock(hdev);
5284
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005285 /* If user space supports this command it is also expected to
5286 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5287 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005288 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005289
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005290 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005291 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005292 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005293 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005294 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005295 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005296 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005297 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005298 }
5299
5300 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5301 if (err < 0)
5302 goto unlock;
5303
5304 if (changed)
5305 err = new_settings(hdev, sk);
5306
5307unlock:
5308 hci_dev_unlock(hdev);
5309 return err;
5310}
5311
Johan Hedberg41edf162014-02-18 10:19:35 +02005312static bool irk_is_valid(struct mgmt_irk_info *irk)
5313{
5314 switch (irk->addr.type) {
5315 case BDADDR_LE_PUBLIC:
5316 return true;
5317
5318 case BDADDR_LE_RANDOM:
5319 /* Two most significant bits shall be set */
5320 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5321 return false;
5322 return true;
5323 }
5324
5325 return false;
5326}
5327
5328static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5329 u16 len)
5330{
5331 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005332 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5333 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005334 u16 irk_count, expected_len;
5335 int i, err;
5336
5337 BT_DBG("request for %s", hdev->name);
5338
5339 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005340 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5341 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005342
5343 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005344 if (irk_count > max_irk_count) {
5345 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005346 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5347 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005348 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005349
5350 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5351 if (expected_len != len) {
5352 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005353 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005354 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5355 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005356 }
5357
5358 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5359
5360 for (i = 0; i < irk_count; i++) {
5361 struct mgmt_irk_info *key = &cp->irks[i];
5362
5363 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005364 return mgmt_cmd_status(sk, hdev->id,
5365 MGMT_OP_LOAD_IRKS,
5366 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005367 }
5368
5369 hci_dev_lock(hdev);
5370
5371 hci_smp_irks_clear(hdev);
5372
5373 for (i = 0; i < irk_count; i++) {
5374 struct mgmt_irk_info *irk = &cp->irks[i];
5375 u8 addr_type;
5376
5377 if (irk->addr.type == BDADDR_LE_PUBLIC)
5378 addr_type = ADDR_LE_DEV_PUBLIC;
5379 else
5380 addr_type = ADDR_LE_DEV_RANDOM;
5381
5382 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5383 BDADDR_ANY);
5384 }
5385
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005386 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005387
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005388 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005389
5390 hci_dev_unlock(hdev);
5391
5392 return err;
5393}
5394
Johan Hedberg3f706b72013-01-20 14:27:16 +02005395static bool ltk_is_valid(struct mgmt_ltk_info *key)
5396{
5397 if (key->master != 0x00 && key->master != 0x01)
5398 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005399
5400 switch (key->addr.type) {
5401 case BDADDR_LE_PUBLIC:
5402 return true;
5403
5404 case BDADDR_LE_RANDOM:
5405 /* Two most significant bits shall be set */
5406 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5407 return false;
5408 return true;
5409 }
5410
5411 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005412}
5413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005414static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005415 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005416{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005417 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005418 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5419 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005420 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005421 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005422
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005423 BT_DBG("request for %s", hdev->name);
5424
5425 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005426 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5427 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005428
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005429 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005430 if (key_count > max_key_count) {
5431 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005432 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5433 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005434 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005435
5436 expected_len = sizeof(*cp) + key_count *
5437 sizeof(struct mgmt_ltk_info);
5438 if (expected_len != len) {
5439 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005440 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005441 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5442 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005443 }
5444
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005445 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005446
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005447 for (i = 0; i < key_count; i++) {
5448 struct mgmt_ltk_info *key = &cp->keys[i];
5449
Johan Hedberg3f706b72013-01-20 14:27:16 +02005450 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005451 return mgmt_cmd_status(sk, hdev->id,
5452 MGMT_OP_LOAD_LONG_TERM_KEYS,
5453 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005454 }
5455
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005456 hci_dev_lock(hdev);
5457
5458 hci_smp_ltks_clear(hdev);
5459
5460 for (i = 0; i < key_count; i++) {
5461 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005462 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005463
5464 if (key->addr.type == BDADDR_LE_PUBLIC)
5465 addr_type = ADDR_LE_DEV_PUBLIC;
5466 else
5467 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005468
Johan Hedberg61b43352014-05-29 19:36:53 +03005469 switch (key->type) {
5470 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005471 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005472 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005473 break;
5474 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005475 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005476 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005477 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005478 case MGMT_LTK_P256_UNAUTH:
5479 authenticated = 0x00;
5480 type = SMP_LTK_P256;
5481 break;
5482 case MGMT_LTK_P256_AUTH:
5483 authenticated = 0x01;
5484 type = SMP_LTK_P256;
5485 break;
5486 case MGMT_LTK_P256_DEBUG:
5487 authenticated = 0x00;
5488 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005489 default:
5490 continue;
5491 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005492
Johan Hedberg35d70272014-02-19 14:57:47 +02005493 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005494 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005495 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005496 }
5497
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005498 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005499 NULL, 0);
5500
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005501 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005502
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005503 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005504}
5505
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005506static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005507{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005508 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005509 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005510 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005511
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005512 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005513
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005514 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005515 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005516 rp.tx_power = conn->tx_power;
5517 rp.max_tx_power = conn->max_tx_power;
5518 } else {
5519 rp.rssi = HCI_RSSI_INVALID;
5520 rp.tx_power = HCI_TX_POWER_INVALID;
5521 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005522 }
5523
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005524 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5525 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005526
5527 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005528 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005529
5530 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005531}
5532
Marcel Holtmann1904a852015-01-11 13:50:44 -08005533static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5534 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005535{
5536 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005537 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005538 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005539 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005540 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005541
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005542 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005543
5544 hci_dev_lock(hdev);
5545
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005546 /* Commands sent in request are either Read RSSI or Read Transmit Power
5547 * Level so we check which one was last sent to retrieve connection
5548 * handle. Both commands have handle as first parameter so it's safe to
5549 * cast data on the same command struct.
5550 *
5551 * First command sent is always Read RSSI and we fail only if it fails.
5552 * In other case we simply override error to indicate success as we
5553 * already remembered if TX power value is actually valid.
5554 */
5555 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5556 if (!cp) {
5557 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005558 status = MGMT_STATUS_SUCCESS;
5559 } else {
5560 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005561 }
5562
5563 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005564 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005565 goto unlock;
5566 }
5567
5568 handle = __le16_to_cpu(cp->handle);
5569 conn = hci_conn_hash_lookup_handle(hdev, handle);
5570 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005571 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005572 goto unlock;
5573 }
5574
Johan Hedberg333ae952015-03-17 13:48:47 +02005575 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005576 if (!cmd)
5577 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005578
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005579 cmd->cmd_complete(cmd, status);
5580 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005581
5582unlock:
5583 hci_dev_unlock(hdev);
5584}
5585
5586static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5587 u16 len)
5588{
5589 struct mgmt_cp_get_conn_info *cp = data;
5590 struct mgmt_rp_get_conn_info rp;
5591 struct hci_conn *conn;
5592 unsigned long conn_info_age;
5593 int err = 0;
5594
5595 BT_DBG("%s", hdev->name);
5596
5597 memset(&rp, 0, sizeof(rp));
5598 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5599 rp.addr.type = cp->addr.type;
5600
5601 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005602 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5603 MGMT_STATUS_INVALID_PARAMS,
5604 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005605
5606 hci_dev_lock(hdev);
5607
5608 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005609 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5610 MGMT_STATUS_NOT_POWERED, &rp,
5611 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005612 goto unlock;
5613 }
5614
5615 if (cp->addr.type == BDADDR_BREDR)
5616 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5617 &cp->addr.bdaddr);
5618 else
5619 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5620
5621 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005622 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5623 MGMT_STATUS_NOT_CONNECTED, &rp,
5624 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005625 goto unlock;
5626 }
5627
Johan Hedberg333ae952015-03-17 13:48:47 +02005628 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005629 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5630 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005631 goto unlock;
5632 }
5633
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005634 /* To avoid client trying to guess when to poll again for information we
5635 * calculate conn info age as random value between min/max set in hdev.
5636 */
5637 conn_info_age = hdev->conn_info_min_age +
5638 prandom_u32_max(hdev->conn_info_max_age -
5639 hdev->conn_info_min_age);
5640
5641 /* Query controller to refresh cached values if they are too old or were
5642 * never read.
5643 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005644 if (time_after(jiffies, conn->conn_info_timestamp +
5645 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005646 !conn->conn_info_timestamp) {
5647 struct hci_request req;
5648 struct hci_cp_read_tx_power req_txp_cp;
5649 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005650 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005651
5652 hci_req_init(&req, hdev);
5653 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5654 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5655 &req_rssi_cp);
5656
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005657 /* For LE links TX power does not change thus we don't need to
5658 * query for it once value is known.
5659 */
5660 if (!bdaddr_type_is_le(cp->addr.type) ||
5661 conn->tx_power == HCI_TX_POWER_INVALID) {
5662 req_txp_cp.handle = cpu_to_le16(conn->handle);
5663 req_txp_cp.type = 0x00;
5664 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5665 sizeof(req_txp_cp), &req_txp_cp);
5666 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005667
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005668 /* Max TX power needs to be read only once per connection */
5669 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5670 req_txp_cp.handle = cpu_to_le16(conn->handle);
5671 req_txp_cp.type = 0x01;
5672 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5673 sizeof(req_txp_cp), &req_txp_cp);
5674 }
5675
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005676 err = hci_req_run(&req, conn_info_refresh_complete);
5677 if (err < 0)
5678 goto unlock;
5679
5680 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5681 data, len);
5682 if (!cmd) {
5683 err = -ENOMEM;
5684 goto unlock;
5685 }
5686
5687 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005688 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005689 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005690
5691 conn->conn_info_timestamp = jiffies;
5692 } else {
5693 /* Cache is valid, just reply with values cached in hci_conn */
5694 rp.rssi = conn->rssi;
5695 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005696 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005697
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005698 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5699 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005700 }
5701
5702unlock:
5703 hci_dev_unlock(hdev);
5704 return err;
5705}
5706
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005707static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005708{
5709 struct hci_conn *conn = cmd->user_data;
5710 struct mgmt_rp_get_clock_info rp;
5711 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005712 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005713
5714 memset(&rp, 0, sizeof(rp));
5715 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5716
5717 if (status)
5718 goto complete;
5719
5720 hdev = hci_dev_get(cmd->index);
5721 if (hdev) {
5722 rp.local_clock = cpu_to_le32(hdev->clock);
5723 hci_dev_put(hdev);
5724 }
5725
5726 if (conn) {
5727 rp.piconet_clock = cpu_to_le32(conn->clock);
5728 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5729 }
5730
5731complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005732 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5733 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005734
5735 if (conn) {
5736 hci_conn_drop(conn);
5737 hci_conn_put(conn);
5738 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005739
5740 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005741}
5742
Marcel Holtmann1904a852015-01-11 13:50:44 -08005743static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005744{
Johan Hedberg95868422014-06-28 17:54:07 +03005745 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005746 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005747 struct hci_conn *conn;
5748
5749 BT_DBG("%s status %u", hdev->name, status);
5750
5751 hci_dev_lock(hdev);
5752
5753 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5754 if (!hci_cp)
5755 goto unlock;
5756
5757 if (hci_cp->which) {
5758 u16 handle = __le16_to_cpu(hci_cp->handle);
5759 conn = hci_conn_hash_lookup_handle(hdev, handle);
5760 } else {
5761 conn = NULL;
5762 }
5763
Johan Hedberg333ae952015-03-17 13:48:47 +02005764 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005765 if (!cmd)
5766 goto unlock;
5767
Johan Hedberg69487372014-12-05 13:36:07 +02005768 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005769 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005770
5771unlock:
5772 hci_dev_unlock(hdev);
5773}
5774
5775static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5776 u16 len)
5777{
5778 struct mgmt_cp_get_clock_info *cp = data;
5779 struct mgmt_rp_get_clock_info rp;
5780 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005781 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005782 struct hci_request req;
5783 struct hci_conn *conn;
5784 int err;
5785
5786 BT_DBG("%s", hdev->name);
5787
5788 memset(&rp, 0, sizeof(rp));
5789 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5790 rp.addr.type = cp->addr.type;
5791
5792 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005793 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5794 MGMT_STATUS_INVALID_PARAMS,
5795 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005796
5797 hci_dev_lock(hdev);
5798
5799 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005800 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5801 MGMT_STATUS_NOT_POWERED, &rp,
5802 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005803 goto unlock;
5804 }
5805
5806 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5807 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5808 &cp->addr.bdaddr);
5809 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005810 err = mgmt_cmd_complete(sk, hdev->id,
5811 MGMT_OP_GET_CLOCK_INFO,
5812 MGMT_STATUS_NOT_CONNECTED,
5813 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005814 goto unlock;
5815 }
5816 } else {
5817 conn = NULL;
5818 }
5819
5820 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5821 if (!cmd) {
5822 err = -ENOMEM;
5823 goto unlock;
5824 }
5825
Johan Hedberg69487372014-12-05 13:36:07 +02005826 cmd->cmd_complete = clock_info_cmd_complete;
5827
Johan Hedberg95868422014-06-28 17:54:07 +03005828 hci_req_init(&req, hdev);
5829
5830 memset(&hci_cp, 0, sizeof(hci_cp));
5831 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5832
5833 if (conn) {
5834 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005835 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005836
5837 hci_cp.handle = cpu_to_le16(conn->handle);
5838 hci_cp.which = 0x01; /* Piconet clock */
5839 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5840 }
5841
5842 err = hci_req_run(&req, get_clock_info_complete);
5843 if (err < 0)
5844 mgmt_pending_remove(cmd);
5845
5846unlock:
5847 hci_dev_unlock(hdev);
5848 return err;
5849}
5850
Johan Hedberg5a154e62014-12-19 22:26:02 +02005851static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5852{
5853 struct hci_conn *conn;
5854
5855 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5856 if (!conn)
5857 return false;
5858
5859 if (conn->dst_type != type)
5860 return false;
5861
5862 if (conn->state != BT_CONNECTED)
5863 return false;
5864
5865 return true;
5866}
5867
5868/* This function requires the caller holds hdev->lock */
5869static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5870 u8 addr_type, u8 auto_connect)
5871{
5872 struct hci_dev *hdev = req->hdev;
5873 struct hci_conn_params *params;
5874
5875 params = hci_conn_params_add(hdev, addr, addr_type);
5876 if (!params)
5877 return -EIO;
5878
5879 if (params->auto_connect == auto_connect)
5880 return 0;
5881
5882 list_del_init(&params->action);
5883
5884 switch (auto_connect) {
5885 case HCI_AUTO_CONN_DISABLED:
5886 case HCI_AUTO_CONN_LINK_LOSS:
5887 __hci_update_background_scan(req);
5888 break;
5889 case HCI_AUTO_CONN_REPORT:
5890 list_add(&params->action, &hdev->pend_le_reports);
5891 __hci_update_background_scan(req);
5892 break;
5893 case HCI_AUTO_CONN_DIRECT:
5894 case HCI_AUTO_CONN_ALWAYS:
5895 if (!is_connected(hdev, addr, addr_type)) {
5896 list_add(&params->action, &hdev->pend_le_conns);
5897 __hci_update_background_scan(req);
5898 }
5899 break;
5900 }
5901
5902 params->auto_connect = auto_connect;
5903
5904 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5905 auto_connect);
5906
5907 return 0;
5908}
5909
Marcel Holtmann8afef092014-06-29 22:28:34 +02005910static void device_added(struct sock *sk, struct hci_dev *hdev,
5911 bdaddr_t *bdaddr, u8 type, u8 action)
5912{
5913 struct mgmt_ev_device_added ev;
5914
5915 bacpy(&ev.addr.bdaddr, bdaddr);
5916 ev.addr.type = type;
5917 ev.action = action;
5918
5919 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5920}
5921
Marcel Holtmann1904a852015-01-11 13:50:44 -08005922static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005923{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005924 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005925
5926 BT_DBG("status 0x%02x", status);
5927
5928 hci_dev_lock(hdev);
5929
Johan Hedberg333ae952015-03-17 13:48:47 +02005930 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005931 if (!cmd)
5932 goto unlock;
5933
5934 cmd->cmd_complete(cmd, mgmt_status(status));
5935 mgmt_pending_remove(cmd);
5936
5937unlock:
5938 hci_dev_unlock(hdev);
5939}
5940
Marcel Holtmann2faade52014-06-29 19:44:03 +02005941static int add_device(struct sock *sk, struct hci_dev *hdev,
5942 void *data, u16 len)
5943{
5944 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005945 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005946 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005947 u8 auto_conn, addr_type;
5948 int err;
5949
5950 BT_DBG("%s", hdev->name);
5951
Johan Hedberg66593582014-07-09 12:59:14 +03005952 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005953 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005954 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5955 MGMT_STATUS_INVALID_PARAMS,
5956 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005957
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005958 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005959 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5960 MGMT_STATUS_INVALID_PARAMS,
5961 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005962
Johan Hedberg5a154e62014-12-19 22:26:02 +02005963 hci_req_init(&req, hdev);
5964
Marcel Holtmann2faade52014-06-29 19:44:03 +02005965 hci_dev_lock(hdev);
5966
Johan Hedberg5a154e62014-12-19 22:26:02 +02005967 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5968 if (!cmd) {
5969 err = -ENOMEM;
5970 goto unlock;
5971 }
5972
5973 cmd->cmd_complete = addr_cmd_complete;
5974
Johan Hedberg66593582014-07-09 12:59:14 +03005975 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005976 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005977 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005978 err = cmd->cmd_complete(cmd,
5979 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005980 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005981 goto unlock;
5982 }
5983
5984 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5985 cp->addr.type);
5986 if (err)
5987 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005988
Johan Hedberg5a154e62014-12-19 22:26:02 +02005989 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005990
Johan Hedberg66593582014-07-09 12:59:14 +03005991 goto added;
5992 }
5993
Marcel Holtmann2faade52014-06-29 19:44:03 +02005994 if (cp->addr.type == BDADDR_LE_PUBLIC)
5995 addr_type = ADDR_LE_DEV_PUBLIC;
5996 else
5997 addr_type = ADDR_LE_DEV_RANDOM;
5998
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005999 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006000 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006001 else if (cp->action == 0x01)
6002 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006003 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006004 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006005
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006006 /* If the connection parameters don't exist for this device,
6007 * they will be created and configured with defaults.
6008 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006009 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006010 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006011 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006012 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006013 goto unlock;
6014 }
6015
Johan Hedberg66593582014-07-09 12:59:14 +03006016added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006017 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6018
Johan Hedberg5a154e62014-12-19 22:26:02 +02006019 err = hci_req_run(&req, add_device_complete);
6020 if (err < 0) {
6021 /* ENODATA means no HCI commands were needed (e.g. if
6022 * the adapter is powered off).
6023 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006024 if (err == -ENODATA)
6025 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006026 mgmt_pending_remove(cmd);
6027 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006028
6029unlock:
6030 hci_dev_unlock(hdev);
6031 return err;
6032}
6033
Marcel Holtmann8afef092014-06-29 22:28:34 +02006034static void device_removed(struct sock *sk, struct hci_dev *hdev,
6035 bdaddr_t *bdaddr, u8 type)
6036{
6037 struct mgmt_ev_device_removed ev;
6038
6039 bacpy(&ev.addr.bdaddr, bdaddr);
6040 ev.addr.type = type;
6041
6042 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6043}
6044
Marcel Holtmann1904a852015-01-11 13:50:44 -08006045static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006046{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006047 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006048
6049 BT_DBG("status 0x%02x", status);
6050
6051 hci_dev_lock(hdev);
6052
Johan Hedberg333ae952015-03-17 13:48:47 +02006053 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006054 if (!cmd)
6055 goto unlock;
6056
6057 cmd->cmd_complete(cmd, mgmt_status(status));
6058 mgmt_pending_remove(cmd);
6059
6060unlock:
6061 hci_dev_unlock(hdev);
6062}
6063
Marcel Holtmann2faade52014-06-29 19:44:03 +02006064static int remove_device(struct sock *sk, struct hci_dev *hdev,
6065 void *data, u16 len)
6066{
6067 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006068 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006069 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006070 int err;
6071
6072 BT_DBG("%s", hdev->name);
6073
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006074 hci_req_init(&req, hdev);
6075
Marcel Holtmann2faade52014-06-29 19:44:03 +02006076 hci_dev_lock(hdev);
6077
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006078 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6079 if (!cmd) {
6080 err = -ENOMEM;
6081 goto unlock;
6082 }
6083
6084 cmd->cmd_complete = addr_cmd_complete;
6085
Marcel Holtmann2faade52014-06-29 19:44:03 +02006086 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006087 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006088 u8 addr_type;
6089
Johan Hedberg66593582014-07-09 12:59:14 +03006090 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006091 err = cmd->cmd_complete(cmd,
6092 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006093 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006094 goto unlock;
6095 }
6096
Johan Hedberg66593582014-07-09 12:59:14 +03006097 if (cp->addr.type == BDADDR_BREDR) {
6098 err = hci_bdaddr_list_del(&hdev->whitelist,
6099 &cp->addr.bdaddr,
6100 cp->addr.type);
6101 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006102 err = cmd->cmd_complete(cmd,
6103 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006104 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006105 goto unlock;
6106 }
6107
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006108 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006109
Johan Hedberg66593582014-07-09 12:59:14 +03006110 device_removed(sk, hdev, &cp->addr.bdaddr,
6111 cp->addr.type);
6112 goto complete;
6113 }
6114
Marcel Holtmann2faade52014-06-29 19:44:03 +02006115 if (cp->addr.type == BDADDR_LE_PUBLIC)
6116 addr_type = ADDR_LE_DEV_PUBLIC;
6117 else
6118 addr_type = ADDR_LE_DEV_RANDOM;
6119
Johan Hedbergc71593d2014-07-02 17:37:28 +03006120 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6121 addr_type);
6122 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006123 err = cmd->cmd_complete(cmd,
6124 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006125 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006126 goto unlock;
6127 }
6128
6129 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006130 err = cmd->cmd_complete(cmd,
6131 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006132 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006133 goto unlock;
6134 }
6135
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006136 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006137 list_del(&params->list);
6138 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006139 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006140
6141 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006142 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006143 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006144 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006145
Marcel Holtmann2faade52014-06-29 19:44:03 +02006146 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006147 err = cmd->cmd_complete(cmd,
6148 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006149 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006150 goto unlock;
6151 }
6152
Johan Hedberg66593582014-07-09 12:59:14 +03006153 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6154 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6155 list_del(&b->list);
6156 kfree(b);
6157 }
6158
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006159 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006160
Johan Hedberg19de0822014-07-06 13:06:51 +03006161 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6162 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6163 continue;
6164 device_removed(sk, hdev, &p->addr, p->addr_type);
6165 list_del(&p->action);
6166 list_del(&p->list);
6167 kfree(p);
6168 }
6169
6170 BT_DBG("All LE connection parameters were removed");
6171
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006172 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006173 }
6174
Johan Hedberg66593582014-07-09 12:59:14 +03006175complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006176 err = hci_req_run(&req, remove_device_complete);
6177 if (err < 0) {
6178 /* ENODATA means no HCI commands were needed (e.g. if
6179 * the adapter is powered off).
6180 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006181 if (err == -ENODATA)
6182 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006183 mgmt_pending_remove(cmd);
6184 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006185
6186unlock:
6187 hci_dev_unlock(hdev);
6188 return err;
6189}
6190
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006191static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6192 u16 len)
6193{
6194 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006195 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6196 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006197 u16 param_count, expected_len;
6198 int i;
6199
6200 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006201 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6202 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006203
6204 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006205 if (param_count > max_param_count) {
6206 BT_ERR("load_conn_param: too big param_count value %u",
6207 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006208 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6209 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006210 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006211
6212 expected_len = sizeof(*cp) + param_count *
6213 sizeof(struct mgmt_conn_param);
6214 if (expected_len != len) {
6215 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6216 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006217 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6218 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006219 }
6220
6221 BT_DBG("%s param_count %u", hdev->name, param_count);
6222
6223 hci_dev_lock(hdev);
6224
6225 hci_conn_params_clear_disabled(hdev);
6226
6227 for (i = 0; i < param_count; i++) {
6228 struct mgmt_conn_param *param = &cp->params[i];
6229 struct hci_conn_params *hci_param;
6230 u16 min, max, latency, timeout;
6231 u8 addr_type;
6232
6233 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6234 param->addr.type);
6235
6236 if (param->addr.type == BDADDR_LE_PUBLIC) {
6237 addr_type = ADDR_LE_DEV_PUBLIC;
6238 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6239 addr_type = ADDR_LE_DEV_RANDOM;
6240 } else {
6241 BT_ERR("Ignoring invalid connection parameters");
6242 continue;
6243 }
6244
6245 min = le16_to_cpu(param->min_interval);
6246 max = le16_to_cpu(param->max_interval);
6247 latency = le16_to_cpu(param->latency);
6248 timeout = le16_to_cpu(param->timeout);
6249
6250 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6251 min, max, latency, timeout);
6252
6253 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6254 BT_ERR("Ignoring invalid connection parameters");
6255 continue;
6256 }
6257
6258 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6259 addr_type);
6260 if (!hci_param) {
6261 BT_ERR("Failed to add connection parameters");
6262 continue;
6263 }
6264
6265 hci_param->conn_min_interval = min;
6266 hci_param->conn_max_interval = max;
6267 hci_param->conn_latency = latency;
6268 hci_param->supervision_timeout = timeout;
6269 }
6270
6271 hci_dev_unlock(hdev);
6272
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006273 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6274 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006275}
6276
Marcel Holtmanndbece372014-07-04 18:11:55 +02006277static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6278 void *data, u16 len)
6279{
6280 struct mgmt_cp_set_external_config *cp = data;
6281 bool changed;
6282 int err;
6283
6284 BT_DBG("%s", hdev->name);
6285
6286 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006287 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6288 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006289
6290 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006291 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6292 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006293
6294 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006295 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6296 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006297
6298 hci_dev_lock(hdev);
6299
6300 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006301 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006302 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006303 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006304
6305 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6306 if (err < 0)
6307 goto unlock;
6308
6309 if (!changed)
6310 goto unlock;
6311
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006312 err = new_options(hdev, sk);
6313
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006314 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006315 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006316
Marcel Holtmann516018a2015-03-13 02:11:04 -07006317 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006318 hci_dev_set_flag(hdev, HCI_CONFIG);
6319 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006320
6321 queue_work(hdev->req_workqueue, &hdev->power_on);
6322 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006323 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006324 mgmt_index_added(hdev);
6325 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006326 }
6327
6328unlock:
6329 hci_dev_unlock(hdev);
6330 return err;
6331}
6332
Marcel Holtmann9713c172014-07-06 12:11:15 +02006333static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6334 void *data, u16 len)
6335{
6336 struct mgmt_cp_set_public_address *cp = data;
6337 bool changed;
6338 int err;
6339
6340 BT_DBG("%s", hdev->name);
6341
6342 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006343 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6344 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006345
6346 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006347 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6348 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006349
6350 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006351 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6352 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006353
6354 hci_dev_lock(hdev);
6355
6356 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6357 bacpy(&hdev->public_addr, &cp->bdaddr);
6358
6359 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6360 if (err < 0)
6361 goto unlock;
6362
6363 if (!changed)
6364 goto unlock;
6365
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006366 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006367 err = new_options(hdev, sk);
6368
6369 if (is_configured(hdev)) {
6370 mgmt_index_removed(hdev);
6371
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006372 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006373
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006374 hci_dev_set_flag(hdev, HCI_CONFIG);
6375 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006376
6377 queue_work(hdev->req_workqueue, &hdev->power_on);
6378 }
6379
6380unlock:
6381 hci_dev_unlock(hdev);
6382 return err;
6383}
6384
Marcel Holtmannbea41602015-03-14 22:43:17 -07006385static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6386 u8 data_len)
6387{
6388 eir[eir_len++] = sizeof(type) + data_len;
6389 eir[eir_len++] = type;
6390 memcpy(&eir[eir_len], data, data_len);
6391 eir_len += data_len;
6392
6393 return eir_len;
6394}
6395
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006396static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6397 void *data, u16 data_len)
6398{
6399 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6400 struct mgmt_rp_read_local_oob_ext_data *rp;
6401 size_t rp_len;
6402 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006403 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006404 int err;
6405
6406 BT_DBG("%s", hdev->name);
6407
6408 if (!hdev_is_powered(hdev))
6409 return mgmt_cmd_complete(sk, hdev->id,
6410 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6411 MGMT_STATUS_NOT_POWERED,
6412 &cp->type, sizeof(cp->type));
6413
6414 switch (cp->type) {
6415 case BIT(BDADDR_BREDR):
6416 status = mgmt_bredr_support(hdev);
6417 if (status)
6418 return mgmt_cmd_complete(sk, hdev->id,
6419 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6420 status, &cp->type,
6421 sizeof(cp->type));
6422 eir_len = 5;
6423 break;
6424 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6425 status = mgmt_le_support(hdev);
6426 if (status)
6427 return mgmt_cmd_complete(sk, hdev->id,
6428 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6429 status, &cp->type,
6430 sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006431 eir_len = 9 + 3 + 18 + 18 + 3;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006432 break;
6433 default:
6434 return mgmt_cmd_complete(sk, hdev->id,
6435 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6436 MGMT_STATUS_INVALID_PARAMS,
6437 &cp->type, sizeof(cp->type));
6438 }
6439
6440 hci_dev_lock(hdev);
6441
6442 rp_len = sizeof(*rp) + eir_len;
6443 rp = kmalloc(rp_len, GFP_ATOMIC);
6444 if (!rp) {
6445 hci_dev_unlock(hdev);
6446 return -ENOMEM;
6447 }
6448
6449 eir_len = 0;
6450 switch (cp->type) {
6451 case BIT(BDADDR_BREDR):
6452 eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
6453 hdev->dev_class, 3);
6454 break;
6455 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006456 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6457 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006458 hci_dev_unlock(hdev);
6459 err = mgmt_cmd_complete(sk, hdev->id,
Marcel Holtmann5082a592015-03-16 12:39:00 -07006460 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6461 MGMT_STATUS_FAILED,
6462 &cp->type, sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006463 goto done;
6464 }
6465
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006466 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
6467 memcpy(addr, &hdev->rpa, 6);
6468 addr[6] = 0x01;
6469 } else if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6470 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6471 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6472 bacmp(&hdev->static_addr, BDADDR_ANY))) {
6473 memcpy(addr, &hdev->static_addr, 6);
6474 addr[6] = 0x01;
6475 } else {
6476 memcpy(addr, &hdev->bdaddr, 6);
6477 addr[6] = 0x00;
6478 }
6479
6480 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6481 addr, sizeof(addr));
6482
6483 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6484 role = 0x02;
6485 else
6486 role = 0x01;
6487
6488 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6489 &role, sizeof(role));
6490
Marcel Holtmann5082a592015-03-16 12:39:00 -07006491 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6492 eir_len = eir_append_data(rp->eir, eir_len,
6493 EIR_LE_SC_CONFIRM,
6494 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006495
Marcel Holtmann5082a592015-03-16 12:39:00 -07006496 eir_len = eir_append_data(rp->eir, eir_len,
6497 EIR_LE_SC_RANDOM,
6498 rand, sizeof(rand));
6499 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006500
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006501 flags = get_adv_discov_flags(hdev);
6502
6503 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6504 flags |= LE_AD_NO_BREDR;
6505
6506 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6507 &flags, sizeof(flags));
6508 break;
6509 }
6510
6511 rp->type = cp->type;
6512 rp->eir_len = cpu_to_le16(eir_len);
6513
6514 hci_dev_unlock(hdev);
6515
Marcel Holtmann72000df2015-03-16 16:11:21 -07006516 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6517
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006518 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann5425f982015-03-16 16:05:44 -07006519 MGMT_STATUS_SUCCESS, rp, sizeof(*rp) + eir_len);
Marcel Holtmann72000df2015-03-16 16:11:21 -07006520 if (err < 0)
6521 goto done;
6522
6523 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6524 rp, sizeof(*rp) + eir_len,
6525 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006526
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006527done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006528 kfree(rp);
6529
6530 return err;
6531}
6532
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006533static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6534 void *data, u16 data_len)
6535{
6536 struct mgmt_rp_read_adv_features *rp;
6537 size_t rp_len;
6538 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006539 bool instance;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006540
6541 BT_DBG("%s", hdev->name);
6542
6543 hci_dev_lock(hdev);
6544
6545 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006546
6547 /* Currently only one instance is supported, so just add 1 to the
6548 * response length.
6549 */
6550 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6551 if (instance)
6552 rp_len++;
6553
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006554 rp = kmalloc(rp_len, GFP_ATOMIC);
6555 if (!rp) {
6556 hci_dev_unlock(hdev);
6557 return -ENOMEM;
6558 }
6559
6560 rp->supported_flags = cpu_to_le32(0);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006561 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6562 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006563 rp->max_instances = 1;
6564
6565 /* Currently only one instance is supported, so simply return the
6566 * current instance number.
6567 */
6568 if (instance) {
6569 rp->num_instances = 1;
6570 rp->instance[0] = 1;
6571 } else {
6572 rp->num_instances = 0;
6573 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006574
6575 hci_dev_unlock(hdev);
6576
6577 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6578 MGMT_STATUS_SUCCESS, rp, rp_len);
6579
6580 kfree(rp);
6581
6582 return err;
6583}
6584
Arman Uguray4117ed72015-03-23 15:57:14 -07006585static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006586 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006587{
Arman Uguray4117ed72015-03-23 15:57:14 -07006588 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006589 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006590 bool flags_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006591 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6592 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006593
Arman Uguray807ec772015-03-25 18:53:42 -07006594 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006595 flags_managed = true;
6596 max_len -= 3;
6597 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006598
Arman Uguray4117ed72015-03-23 15:57:14 -07006599 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006600 return false;
6601
Arman Uguray4117ed72015-03-23 15:57:14 -07006602 /* Make sure that the data is correctly formatted. */
6603 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6604 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006605
Arman Ugurayb44133f2015-03-25 18:53:41 -07006606 if (flags_managed && data[i + 1] == EIR_FLAGS)
6607 return false;
6608
Arman Uguray24b4f382015-03-23 15:57:12 -07006609 /* If the current field length would exceed the total data
6610 * length, then it's invalid.
6611 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006612 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006613 return false;
6614 }
6615
6616 return true;
6617}
6618
Arman Uguray24b4f382015-03-23 15:57:12 -07006619static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6620 u16 opcode)
6621{
6622 struct mgmt_pending_cmd *cmd;
6623 struct mgmt_rp_add_advertising rp;
6624
6625 BT_DBG("status %d", status);
6626
6627 hci_dev_lock(hdev);
6628
6629 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6630
6631 if (status) {
6632 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6633 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6634 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6635 }
6636
6637 if (!cmd)
6638 goto unlock;
6639
6640 rp.instance = 0x01;
6641
6642 if (status)
6643 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6644 mgmt_status(status));
6645 else
6646 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6647 mgmt_status(status), &rp, sizeof(rp));
6648
6649 mgmt_pending_remove(cmd);
6650
6651unlock:
6652 hci_dev_unlock(hdev);
6653}
6654
Arman Uguray912098a2015-03-23 15:57:15 -07006655static void adv_timeout_expired(struct work_struct *work)
6656{
6657 struct hci_dev *hdev = container_of(work, struct hci_dev,
6658 adv_instance.timeout_exp.work);
6659
6660 hdev->adv_instance.timeout = 0;
6661
6662 hci_dev_lock(hdev);
6663 clear_adv_instance(hdev);
6664 hci_dev_unlock(hdev);
6665}
6666
Arman Uguray24b4f382015-03-23 15:57:12 -07006667static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6668 void *data, u16 data_len)
6669{
6670 struct mgmt_cp_add_advertising *cp = data;
6671 struct mgmt_rp_add_advertising rp;
6672 u32 flags;
6673 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006674 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006675 int err;
6676 struct mgmt_pending_cmd *cmd;
6677 struct hci_request req;
6678
6679 BT_DBG("%s", hdev->name);
6680
6681 status = mgmt_le_support(hdev);
6682 if (status)
6683 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6684 status);
6685
6686 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006687 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006688
Arman Uguraye7a685d2015-03-25 18:53:40 -07006689 /* The current implementation only supports adding one instance */
6690 if (cp->instance != 0x01)
Arman Uguray24b4f382015-03-23 15:57:12 -07006691 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6692 MGMT_STATUS_INVALID_PARAMS);
6693
6694 hci_dev_lock(hdev);
6695
Arman Uguray912098a2015-03-23 15:57:15 -07006696 if (timeout && !hdev_is_powered(hdev)) {
6697 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6698 MGMT_STATUS_REJECTED);
6699 goto unlock;
6700 }
6701
Arman Uguray24b4f382015-03-23 15:57:12 -07006702 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006703 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006704 pending_find(MGMT_OP_SET_LE, hdev)) {
6705 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6706 MGMT_STATUS_BUSY);
6707 goto unlock;
6708 }
6709
Arman Ugurayb44133f2015-03-25 18:53:41 -07006710 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006711 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006712 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006713 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6714 MGMT_STATUS_INVALID_PARAMS);
6715 goto unlock;
6716 }
6717
Arman Uguray912098a2015-03-23 15:57:15 -07006718 INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
6719
Arman Uguray24b4f382015-03-23 15:57:12 -07006720 hdev->adv_instance.flags = flags;
6721 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6722 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6723
6724 if (cp->adv_data_len)
6725 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6726
6727 if (cp->scan_rsp_len)
6728 memcpy(hdev->adv_instance.scan_rsp_data,
6729 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6730
Arman Uguray912098a2015-03-23 15:57:15 -07006731 if (hdev->adv_instance.timeout)
6732 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6733
6734 hdev->adv_instance.timeout = timeout;
6735
6736 if (timeout)
6737 queue_delayed_work(hdev->workqueue,
6738 &hdev->adv_instance.timeout_exp,
6739 msecs_to_jiffies(timeout * 1000));
6740
Arman Uguray24b4f382015-03-23 15:57:12 -07006741 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6742 advertising_added(sk, hdev, 1);
6743
6744 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6745 * we have no HCI communication to make. Simply return.
6746 */
6747 if (!hdev_is_powered(hdev) ||
6748 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6749 rp.instance = 0x01;
6750 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6751 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6752 goto unlock;
6753 }
6754
6755 /* We're good to go, update advertising data, parameters, and start
6756 * advertising.
6757 */
6758 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6759 data_len);
6760 if (!cmd) {
6761 err = -ENOMEM;
6762 goto unlock;
6763 }
6764
6765 hci_req_init(&req, hdev);
6766
6767 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07006768 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07006769 enable_advertising(&req);
6770
6771 err = hci_req_run(&req, add_advertising_complete);
6772 if (err < 0)
6773 mgmt_pending_remove(cmd);
6774
6775unlock:
6776 hci_dev_unlock(hdev);
6777
6778 return err;
6779}
6780
Arman Ugurayda9293352015-03-23 15:57:13 -07006781static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6782 u16 opcode)
6783{
6784 struct mgmt_pending_cmd *cmd;
6785 struct mgmt_rp_remove_advertising rp;
6786
6787 BT_DBG("status %d", status);
6788
6789 hci_dev_lock(hdev);
6790
6791 /* A failure status here only means that we failed to disable
6792 * advertising. Otherwise, the advertising instance has been removed,
6793 * so report success.
6794 */
6795 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6796 if (!cmd)
6797 goto unlock;
6798
6799 rp.instance = 1;
6800
6801 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6802 &rp, sizeof(rp));
6803 mgmt_pending_remove(cmd);
6804
6805unlock:
6806 hci_dev_unlock(hdev);
6807}
6808
6809static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6810 void *data, u16 data_len)
6811{
6812 struct mgmt_cp_remove_advertising *cp = data;
6813 struct mgmt_rp_remove_advertising rp;
6814 int err;
6815 struct mgmt_pending_cmd *cmd;
6816 struct hci_request req;
6817
6818 BT_DBG("%s", hdev->name);
6819
6820 /* The current implementation only allows modifying instance no 1. A
6821 * value of 0 indicates that all instances should be cleared.
6822 */
6823 if (cp->instance > 1)
6824 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6825 MGMT_STATUS_INVALID_PARAMS);
6826
6827 hci_dev_lock(hdev);
6828
6829 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
6830 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
6831 pending_find(MGMT_OP_SET_LE, hdev)) {
6832 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6833 MGMT_STATUS_BUSY);
6834 goto unlock;
6835 }
6836
6837 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
6838 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6839 MGMT_STATUS_INVALID_PARAMS);
6840 goto unlock;
6841 }
6842
Arman Uguray912098a2015-03-23 15:57:15 -07006843 if (hdev->adv_instance.timeout)
6844 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6845
Arman Ugurayda9293352015-03-23 15:57:13 -07006846 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6847
6848 advertising_removed(sk, hdev, 1);
6849
6850 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6851
6852 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6853 * we have no HCI communication to make. Simply return.
6854 */
6855 if (!hdev_is_powered(hdev) ||
6856 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6857 rp.instance = 1;
6858 err = mgmt_cmd_complete(sk, hdev->id,
6859 MGMT_OP_REMOVE_ADVERTISING,
6860 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6861 goto unlock;
6862 }
6863
6864 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
6865 data_len);
6866 if (!cmd) {
6867 err = -ENOMEM;
6868 goto unlock;
6869 }
6870
6871 hci_req_init(&req, hdev);
6872 disable_advertising(&req);
6873
6874 err = hci_req_run(&req, remove_advertising_complete);
6875 if (err < 0)
6876 mgmt_pending_remove(cmd);
6877
6878unlock:
6879 hci_dev_unlock(hdev);
6880
6881 return err;
6882}
6883
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006884static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006885 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006886 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006887 HCI_MGMT_NO_HDEV |
6888 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006889 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006890 HCI_MGMT_NO_HDEV |
6891 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006892 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006893 HCI_MGMT_NO_HDEV |
6894 HCI_MGMT_UNTRUSTED },
6895 { read_controller_info, MGMT_READ_INFO_SIZE,
6896 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006897 { set_powered, MGMT_SETTING_SIZE },
6898 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
6899 { set_connectable, MGMT_SETTING_SIZE },
6900 { set_fast_connectable, MGMT_SETTING_SIZE },
6901 { set_bondable, MGMT_SETTING_SIZE },
6902 { set_link_security, MGMT_SETTING_SIZE },
6903 { set_ssp, MGMT_SETTING_SIZE },
6904 { set_hs, MGMT_SETTING_SIZE },
6905 { set_le, MGMT_SETTING_SIZE },
6906 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
6907 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
6908 { add_uuid, MGMT_ADD_UUID_SIZE },
6909 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006910 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6911 HCI_MGMT_VAR_LEN },
6912 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6913 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006914 { disconnect, MGMT_DISCONNECT_SIZE },
6915 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
6916 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
6917 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6918 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
6919 { pair_device, MGMT_PAIR_DEVICE_SIZE },
6920 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6921 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
6922 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
6923 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6924 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
6925 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006926 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6927 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6928 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006929 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6930 { start_discovery, MGMT_START_DISCOVERY_SIZE },
6931 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
6932 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
6933 { block_device, MGMT_BLOCK_DEVICE_SIZE },
6934 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
6935 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
6936 { set_advertising, MGMT_SETTING_SIZE },
6937 { set_bredr, MGMT_SETTING_SIZE },
6938 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
6939 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
6940 { set_secure_conn, MGMT_SETTING_SIZE },
6941 { set_debug_keys, MGMT_SETTING_SIZE },
6942 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006943 { load_irks, MGMT_LOAD_IRKS_SIZE,
6944 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006945 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
6946 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
6947 { add_device, MGMT_ADD_DEVICE_SIZE },
6948 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006949 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6950 HCI_MGMT_VAR_LEN },
6951 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006952 HCI_MGMT_NO_HDEV |
6953 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006954 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006955 HCI_MGMT_UNCONFIGURED |
6956 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006957 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6958 HCI_MGMT_UNCONFIGURED },
6959 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6960 HCI_MGMT_UNCONFIGURED },
6961 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6962 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006963 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07006964 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006965 HCI_MGMT_NO_HDEV |
6966 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006967 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07006968 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
6969 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07006970 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006971};
6972
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006973void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006974{
Marcel Holtmannced85542015-03-14 19:27:56 -07006975 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006976
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006977 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6978 return;
6979
Marcel Holtmannf9207332015-03-14 19:27:55 -07006980 switch (hdev->dev_type) {
6981 case HCI_BREDR:
6982 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6983 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
6984 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006985 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006986 } else {
6987 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
6988 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006989 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006990 }
6991 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006992 case HCI_AMP:
6993 ev.type = 0x02;
6994 break;
6995 default:
6996 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006997 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006998
6999 ev.bus = hdev->bus;
7000
7001 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7002 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007003}
7004
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007005void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007006{
Marcel Holtmannced85542015-03-14 19:27:56 -07007007 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007008 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007009
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007010 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7011 return;
7012
Marcel Holtmannf9207332015-03-14 19:27:55 -07007013 switch (hdev->dev_type) {
7014 case HCI_BREDR:
7015 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007016
Marcel Holtmannf9207332015-03-14 19:27:55 -07007017 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7018 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7019 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007020 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007021 } else {
7022 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7023 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007024 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007025 }
7026 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007027 case HCI_AMP:
7028 ev.type = 0x02;
7029 break;
7030 default:
7031 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007032 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007033
7034 ev.bus = hdev->bus;
7035
7036 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7037 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007038}
7039
Andre Guedes6046dc32014-02-26 20:21:51 -03007040/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007041static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007042{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007043 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007044 struct hci_conn_params *p;
7045
7046 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007047 /* Needed for AUTO_OFF case where might not "really"
7048 * have been powered off.
7049 */
7050 list_del_init(&p->action);
7051
7052 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007053 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007054 case HCI_AUTO_CONN_ALWAYS:
7055 list_add(&p->action, &hdev->pend_le_conns);
7056 break;
7057 case HCI_AUTO_CONN_REPORT:
7058 list_add(&p->action, &hdev->pend_le_reports);
7059 break;
7060 default:
7061 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007062 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007063 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007064
Johan Hedberg2cf22212014-12-19 22:26:00 +02007065 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007066}
7067
Marcel Holtmann1904a852015-01-11 13:50:44 -08007068static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007069{
7070 struct cmd_lookup match = { NULL, hdev };
7071
7072 BT_DBG("status 0x%02x", status);
7073
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007074 if (!status) {
7075 /* Register the available SMP channels (BR/EDR and LE) only
7076 * when successfully powering on the controller. This late
7077 * registration is required so that LE SMP can clearly
7078 * decide if the public address or static address is used.
7079 */
7080 smp_register(hdev);
7081 }
7082
Johan Hedberg229ab392013-03-15 17:06:53 -05007083 hci_dev_lock(hdev);
7084
7085 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7086
7087 new_settings(hdev, match.sk);
7088
7089 hci_dev_unlock(hdev);
7090
7091 if (match.sk)
7092 sock_put(match.sk);
7093}
7094
Johan Hedberg70da6242013-03-15 17:06:51 -05007095static int powered_update_hci(struct hci_dev *hdev)
7096{
Johan Hedberg890ea892013-03-15 17:06:52 -05007097 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007098 u8 link_sec;
7099
Johan Hedberg890ea892013-03-15 17:06:52 -05007100 hci_req_init(&req, hdev);
7101
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007102 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007103 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007104 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007105
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007106 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007107
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007108 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7109 u8 support = 0x01;
7110
7111 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7112 sizeof(support), &support);
7113 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007114 }
7115
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007116 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007117 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007118 struct hci_cp_write_le_host_supported cp;
7119
Marcel Holtmann32226e42014-07-24 20:04:16 +02007120 cp.le = 0x01;
7121 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007122
7123 /* Check first if we already have the right
7124 * host state (host features set)
7125 */
7126 if (cp.le != lmp_host_le_capable(hdev) ||
7127 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007128 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7129 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007130 }
7131
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007132 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007133 /* Make sure the controller has a good default for
7134 * advertising data. This also applies to the case
7135 * where BR/EDR was toggled during the AUTO_OFF phase.
7136 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007137 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007138 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007139 update_scan_rsp_data(&req);
7140 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007141
Arman Uguray24b4f382015-03-23 15:57:12 -07007142 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7143 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007144 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007145
7146 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007147 }
7148
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007149 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007150 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007151 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7152 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007153
7154 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007155 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007156 write_fast_connectable(&req, true);
7157 else
7158 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007159 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007160 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007161 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007162 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007163 }
7164
Johan Hedberg229ab392013-03-15 17:06:53 -05007165 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007166}
7167
Johan Hedberg744cf192011-11-08 20:40:14 +02007168int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007169{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007170 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007171 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007172 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007173
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007174 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007175 return 0;
7176
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007177 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007178 if (powered_update_hci(hdev) == 0)
7179 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007180
Johan Hedberg229ab392013-03-15 17:06:53 -05007181 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7182 &match);
7183 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007184 }
7185
Johan Hedberg229ab392013-03-15 17:06:53 -05007186 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007187
7188 /* If the power off is because of hdev unregistration let
7189 * use the appropriate INVALID_INDEX status. Otherwise use
7190 * NOT_POWERED. We cover both scenarios here since later in
7191 * mgmt_index_removed() any hci_conn callbacks will have already
7192 * been triggered, potentially causing misleading DISCONNECTED
7193 * status responses.
7194 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007195 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007196 status = MGMT_STATUS_INVALID_INDEX;
7197 else
7198 status = MGMT_STATUS_NOT_POWERED;
7199
7200 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007201
7202 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007203 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7204 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007205
7206new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007207 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007208
7209 if (match.sk)
7210 sock_put(match.sk);
7211
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007212 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007213}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007214
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007215void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007216{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007217 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007218 u8 status;
7219
Johan Hedberg333ae952015-03-17 13:48:47 +02007220 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007221 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007222 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007223
7224 if (err == -ERFKILL)
7225 status = MGMT_STATUS_RFKILLED;
7226 else
7227 status = MGMT_STATUS_FAILED;
7228
Johan Hedberga69e8372015-03-06 21:08:53 +02007229 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007230
7231 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007232}
7233
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007234void mgmt_discoverable_timeout(struct hci_dev *hdev)
7235{
7236 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007237
7238 hci_dev_lock(hdev);
7239
7240 /* When discoverable timeout triggers, then just make sure
7241 * the limited discoverable flag is cleared. Even in the case
7242 * of a timeout triggered from general discoverable, it is
7243 * safe to unconditionally clear the flag.
7244 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007245 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7246 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007247
7248 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007249 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007250 u8 scan = SCAN_PAGE;
7251 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7252 sizeof(scan), &scan);
7253 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007254 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007255
7256 /* Advertising instances don't use the global discoverable setting, so
7257 * only update AD if advertising was enabled using Set Advertising.
7258 */
7259 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7260 update_adv_data(&req);
7261
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007262 hci_req_run(&req, NULL);
7263
7264 hdev->discov_timeout = 0;
7265
Johan Hedberg9a43e252013-10-20 19:00:07 +03007266 new_settings(hdev, NULL);
7267
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007268 hci_dev_unlock(hdev);
7269}
7270
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007271void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7272 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007273{
Johan Hedberg86742e12011-11-07 23:13:38 +02007274 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007275
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007276 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007277
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007278 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007279 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007280 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007281 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007282 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007283 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007284
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007285 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007286}
Johan Hedbergf7520542011-01-20 12:34:39 +02007287
Johan Hedbergd7b25452014-05-23 13:19:53 +03007288static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7289{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007290 switch (ltk->type) {
7291 case SMP_LTK:
7292 case SMP_LTK_SLAVE:
7293 if (ltk->authenticated)
7294 return MGMT_LTK_AUTHENTICATED;
7295 return MGMT_LTK_UNAUTHENTICATED;
7296 case SMP_LTK_P256:
7297 if (ltk->authenticated)
7298 return MGMT_LTK_P256_AUTH;
7299 return MGMT_LTK_P256_UNAUTH;
7300 case SMP_LTK_P256_DEBUG:
7301 return MGMT_LTK_P256_DEBUG;
7302 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007303
7304 return MGMT_LTK_UNAUTHENTICATED;
7305}
7306
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007307void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007308{
7309 struct mgmt_ev_new_long_term_key ev;
7310
7311 memset(&ev, 0, sizeof(ev));
7312
Marcel Holtmann5192d302014-02-19 17:11:58 -08007313 /* Devices using resolvable or non-resolvable random addresses
7314 * without providing an indentity resolving key don't require
7315 * to store long term keys. Their addresses will change the
7316 * next time around.
7317 *
7318 * Only when a remote device provides an identity address
7319 * make sure the long term key is stored. If the remote
7320 * identity is known, the long term keys are internally
7321 * mapped to the identity address. So allow static random
7322 * and public addresses here.
7323 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007324 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7325 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7326 ev.store_hint = 0x00;
7327 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007328 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007329
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007330 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007331 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007332 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007333 ev.key.enc_size = key->enc_size;
7334 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007335 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007336
Johan Hedberg2ceba532014-06-16 19:25:16 +03007337 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007338 ev.key.master = 1;
7339
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007340 memcpy(ev.key.val, key->val, sizeof(key->val));
7341
Marcel Holtmann083368f2013-10-15 14:26:29 -07007342 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007343}
7344
Johan Hedberg95fbac82014-02-19 15:18:31 +02007345void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7346{
7347 struct mgmt_ev_new_irk ev;
7348
7349 memset(&ev, 0, sizeof(ev));
7350
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007351 /* For identity resolving keys from devices that are already
7352 * using a public address or static random address, do not
7353 * ask for storing this key. The identity resolving key really
7354 * is only mandatory for devices using resovlable random
7355 * addresses.
7356 *
7357 * Storing all identity resolving keys has the downside that
7358 * they will be also loaded on next boot of they system. More
7359 * identity resolving keys, means more time during scanning is
7360 * needed to actually resolve these addresses.
7361 */
7362 if (bacmp(&irk->rpa, BDADDR_ANY))
7363 ev.store_hint = 0x01;
7364 else
7365 ev.store_hint = 0x00;
7366
Johan Hedberg95fbac82014-02-19 15:18:31 +02007367 bacpy(&ev.rpa, &irk->rpa);
7368 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7369 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7370 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7371
7372 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7373}
7374
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007375void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7376 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007377{
7378 struct mgmt_ev_new_csrk ev;
7379
7380 memset(&ev, 0, sizeof(ev));
7381
7382 /* Devices using resolvable or non-resolvable random addresses
7383 * without providing an indentity resolving key don't require
7384 * to store signature resolving keys. Their addresses will change
7385 * the next time around.
7386 *
7387 * Only when a remote device provides an identity address
7388 * make sure the signature resolving key is stored. So allow
7389 * static random and public addresses here.
7390 */
7391 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7392 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7393 ev.store_hint = 0x00;
7394 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007395 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007396
7397 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7398 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007399 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007400 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7401
7402 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7403}
7404
Andre Guedesffb5a8272014-07-01 18:10:11 -03007405void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007406 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7407 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007408{
7409 struct mgmt_ev_new_conn_param ev;
7410
Johan Hedbergc103aea2014-07-02 17:37:34 +03007411 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7412 return;
7413
Andre Guedesffb5a8272014-07-01 18:10:11 -03007414 memset(&ev, 0, sizeof(ev));
7415 bacpy(&ev.addr.bdaddr, bdaddr);
7416 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007417 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007418 ev.min_interval = cpu_to_le16(min_interval);
7419 ev.max_interval = cpu_to_le16(max_interval);
7420 ev.latency = cpu_to_le16(latency);
7421 ev.timeout = cpu_to_le16(timeout);
7422
7423 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7424}
7425
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007426void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7427 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007428{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007429 char buf[512];
7430 struct mgmt_ev_device_connected *ev = (void *) buf;
7431 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007432
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007433 bacpy(&ev->addr.bdaddr, &conn->dst);
7434 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007435
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007436 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007437
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007438 /* We must ensure that the EIR Data fields are ordered and
7439 * unique. Keep it simple for now and avoid the problem by not
7440 * adding any BR/EDR data to the LE adv.
7441 */
7442 if (conn->le_adv_data_len > 0) {
7443 memcpy(&ev->eir[eir_len],
7444 conn->le_adv_data, conn->le_adv_data_len);
7445 eir_len = conn->le_adv_data_len;
7446 } else {
7447 if (name_len > 0)
7448 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7449 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007450
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007451 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007452 eir_len = eir_append_data(ev->eir, eir_len,
7453 EIR_CLASS_OF_DEV,
7454 conn->dev_class, 3);
7455 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007456
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007457 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007458
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007459 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7460 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007461}
7462
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007463static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007464{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007465 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007466
Johan Hedbergf5818c22014-12-05 13:36:02 +02007467 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007468
7469 *sk = cmd->sk;
7470 sock_hold(*sk);
7471
Johan Hedberga664b5b2011-02-19 12:06:02 -03007472 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007473}
7474
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007475static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007476{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007477 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007478 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007479
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007480 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7481
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007482 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007483 mgmt_pending_remove(cmd);
7484}
7485
Johan Hedberg84c61d92014-08-01 11:13:30 +03007486bool mgmt_powering_down(struct hci_dev *hdev)
7487{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007488 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007489 struct mgmt_mode *cp;
7490
Johan Hedberg333ae952015-03-17 13:48:47 +02007491 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007492 if (!cmd)
7493 return false;
7494
7495 cp = cmd->param;
7496 if (!cp->val)
7497 return true;
7498
7499 return false;
7500}
7501
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007502void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007503 u8 link_type, u8 addr_type, u8 reason,
7504 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007505{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007506 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007507 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007508
Johan Hedberg84c61d92014-08-01 11:13:30 +03007509 /* The connection is still in hci_conn_hash so test for 1
7510 * instead of 0 to know if this is the last one.
7511 */
7512 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7513 cancel_delayed_work(&hdev->power_off);
7514 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007515 }
7516
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007517 if (!mgmt_connected)
7518 return;
7519
Andre Guedes57eb7762013-10-30 19:01:41 -03007520 if (link_type != ACL_LINK && link_type != LE_LINK)
7521 return;
7522
Johan Hedberg744cf192011-11-08 20:40:14 +02007523 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007524
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007525 bacpy(&ev.addr.bdaddr, bdaddr);
7526 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7527 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007528
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007529 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007530
7531 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007532 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007533
Johan Hedberg124f6e32012-02-09 13:50:12 +02007534 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007535 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007536}
7537
Marcel Holtmann78929242013-10-06 23:55:47 -07007538void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7539 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007540{
Andre Guedes3655bba2013-10-30 19:01:40 -03007541 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7542 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007543 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007544
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007545 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7546 hdev);
7547
Johan Hedberg333ae952015-03-17 13:48:47 +02007548 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007549 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007550 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007551
Andre Guedes3655bba2013-10-30 19:01:40 -03007552 cp = cmd->param;
7553
7554 if (bacmp(bdaddr, &cp->addr.bdaddr))
7555 return;
7556
7557 if (cp->addr.type != bdaddr_type)
7558 return;
7559
Johan Hedbergf5818c22014-12-05 13:36:02 +02007560 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007561 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007562}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007563
Marcel Holtmann445608d2013-10-06 23:55:48 -07007564void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7565 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007566{
7567 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007568
Johan Hedberg84c61d92014-08-01 11:13:30 +03007569 /* The connection is still in hci_conn_hash so test for 1
7570 * instead of 0 to know if this is the last one.
7571 */
7572 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7573 cancel_delayed_work(&hdev->power_off);
7574 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007575 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007576
Johan Hedberg4c659c32011-11-07 23:13:39 +02007577 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007578 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007579 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007580
Marcel Holtmann445608d2013-10-06 23:55:48 -07007581 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007582}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007583
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007584void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007585{
7586 struct mgmt_ev_pin_code_request ev;
7587
Johan Hedbergd8457692012-02-17 14:24:57 +02007588 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007589 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007590 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007591
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007592 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007593}
7594
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007595void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7596 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007597{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007598 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007599
Johan Hedberg333ae952015-03-17 13:48:47 +02007600 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007601 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007602 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007603
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007604 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007605 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007606}
7607
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007608void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7609 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007610{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007611 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007612
Johan Hedberg333ae952015-03-17 13:48:47 +02007613 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007614 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007615 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007616
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007617 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007618 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007619}
Johan Hedberga5c29682011-02-19 12:05:57 -03007620
Johan Hedberg744cf192011-11-08 20:40:14 +02007621int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007622 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007623 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007624{
7625 struct mgmt_ev_user_confirm_request ev;
7626
Johan Hedberg744cf192011-11-08 20:40:14 +02007627 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007628
Johan Hedberg272d90d2012-02-09 15:26:12 +02007629 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007630 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007631 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007632 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007633
Johan Hedberg744cf192011-11-08 20:40:14 +02007634 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007635 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007636}
7637
Johan Hedberg272d90d2012-02-09 15:26:12 +02007638int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007639 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007640{
7641 struct mgmt_ev_user_passkey_request ev;
7642
7643 BT_DBG("%s", hdev->name);
7644
Johan Hedberg272d90d2012-02-09 15:26:12 +02007645 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007646 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007647
7648 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007649 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007650}
7651
Brian Gix0df4c182011-11-16 13:53:13 -08007652static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007653 u8 link_type, u8 addr_type, u8 status,
7654 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007655{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007656 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007657
Johan Hedberg333ae952015-03-17 13:48:47 +02007658 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007659 if (!cmd)
7660 return -ENOENT;
7661
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007662 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007663 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007664
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007665 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007666}
7667
Johan Hedberg744cf192011-11-08 20:40:14 +02007668int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007669 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007670{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007671 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007672 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007673}
7674
Johan Hedberg272d90d2012-02-09 15:26:12 +02007675int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007676 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007677{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007678 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007679 status,
7680 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007681}
Johan Hedberg2a611692011-02-19 12:06:00 -03007682
Brian Gix604086b2011-11-23 08:28:33 -08007683int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007684 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007685{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007686 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007687 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007688}
7689
Johan Hedberg272d90d2012-02-09 15:26:12 +02007690int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007691 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007692{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007693 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007694 status,
7695 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007696}
7697
Johan Hedberg92a25252012-09-06 18:39:26 +03007698int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7699 u8 link_type, u8 addr_type, u32 passkey,
7700 u8 entered)
7701{
7702 struct mgmt_ev_passkey_notify ev;
7703
7704 BT_DBG("%s", hdev->name);
7705
7706 bacpy(&ev.addr.bdaddr, bdaddr);
7707 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7708 ev.passkey = __cpu_to_le32(passkey);
7709 ev.entered = entered;
7710
7711 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7712}
7713
Johan Hedberge1e930f2014-09-08 17:09:49 -07007714void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007715{
7716 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007717 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007718 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007719
Johan Hedberge1e930f2014-09-08 17:09:49 -07007720 bacpy(&ev.addr.bdaddr, &conn->dst);
7721 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7722 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007723
Johan Hedberge1e930f2014-09-08 17:09:49 -07007724 cmd = find_pairing(conn);
7725
7726 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7727 cmd ? cmd->sk : NULL);
7728
Johan Hedberga511b352014-12-11 21:45:45 +02007729 if (cmd) {
7730 cmd->cmd_complete(cmd, status);
7731 mgmt_pending_remove(cmd);
7732 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007733}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007734
Marcel Holtmann464996a2013-10-15 14:26:24 -07007735void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007736{
7737 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007738 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007739
7740 if (status) {
7741 u8 mgmt_err = mgmt_status(status);
7742 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007743 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007744 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007745 }
7746
Marcel Holtmann464996a2013-10-15 14:26:24 -07007747 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007748 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007749 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007750 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007751
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007752 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007753 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007754
Johan Hedberg47990ea2012-02-22 11:58:37 +02007755 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007756 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007757
7758 if (match.sk)
7759 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007760}
7761
Johan Hedberg890ea892013-03-15 17:06:52 -05007762static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007763{
Johan Hedberg890ea892013-03-15 17:06:52 -05007764 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007765 struct hci_cp_write_eir cp;
7766
Johan Hedberg976eb202012-10-24 21:12:01 +03007767 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007768 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007769
Johan Hedbergc80da272012-02-22 15:38:48 +02007770 memset(hdev->eir, 0, sizeof(hdev->eir));
7771
Johan Hedbergcacaf522012-02-21 00:52:42 +02007772 memset(&cp, 0, sizeof(cp));
7773
Johan Hedberg890ea892013-03-15 17:06:52 -05007774 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007775}
7776
Marcel Holtmann3e248562013-10-15 14:26:25 -07007777void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007778{
7779 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007780 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007781 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007782
7783 if (status) {
7784 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007785
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007786 if (enable && hci_dev_test_and_clear_flag(hdev,
7787 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007788 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007789 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007790 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007791
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007792 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7793 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007794 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007795 }
7796
7797 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007798 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007799 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007800 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007801 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007802 changed = hci_dev_test_and_clear_flag(hdev,
7803 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007804 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007805 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007806 }
7807
7808 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7809
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007810 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007811 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007812
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007813 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007814 sock_put(match.sk);
7815
Johan Hedberg890ea892013-03-15 17:06:52 -05007816 hci_req_init(&req, hdev);
7817
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007818 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7819 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007820 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7821 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007822 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007823 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007824 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007825 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007826
7827 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007828}
7829
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007830static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007831{
7832 struct cmd_lookup *match = data;
7833
Johan Hedberg90e70452012-02-23 23:09:40 +02007834 if (match->sk == NULL) {
7835 match->sk = cmd->sk;
7836 sock_hold(match->sk);
7837 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007838}
7839
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007840void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7841 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007842{
Johan Hedberg90e70452012-02-23 23:09:40 +02007843 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007844
Johan Hedberg92da6092013-03-15 17:06:55 -05007845 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7846 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7847 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007848
7849 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007850 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7851 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007852
7853 if (match.sk)
7854 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007855}
7856
Marcel Holtmann7667da32013-10-15 14:26:27 -07007857void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007858{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007859 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007860 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007861
Johan Hedberg13928972013-03-15 17:07:00 -05007862 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007863 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007864
7865 memset(&ev, 0, sizeof(ev));
7866 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007867 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007868
Johan Hedberg333ae952015-03-17 13:48:47 +02007869 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007870 if (!cmd) {
7871 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007872
Johan Hedberg13928972013-03-15 17:07:00 -05007873 /* If this is a HCI command related to powering on the
7874 * HCI dev don't send any mgmt signals.
7875 */
Johan Hedberg333ae952015-03-17 13:48:47 +02007876 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007877 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007878 }
7879
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007880 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7881 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007882}
Szymon Jancc35938b2011-03-22 13:12:21 +01007883
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007884void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007885 u8 *rand192, u8 *hash256, u8 *rand256,
7886 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007887{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007888 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007889
Johan Hedberg744cf192011-11-08 20:40:14 +02007890 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007891
Johan Hedberg333ae952015-03-17 13:48:47 +02007892 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007893 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007894 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007895
7896 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007897 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7898 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007899 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007900 struct mgmt_rp_read_local_oob_data rp;
7901 size_t rp_size = sizeof(rp);
7902
7903 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7904 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7905
Johan Hedberg710f11c2014-05-26 11:21:22 +03007906 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007907 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007908 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007909 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007910 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007911 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007912
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007913 mgmt_cmd_complete(cmd->sk, hdev->id,
7914 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7915 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007916 }
7917
7918 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007919}
Johan Hedberge17acd42011-03-30 23:57:16 +03007920
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007921static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7922{
7923 int i;
7924
7925 for (i = 0; i < uuid_count; i++) {
7926 if (!memcmp(uuid, uuids[i], 16))
7927 return true;
7928 }
7929
7930 return false;
7931}
7932
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007933static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7934{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007935 u16 parsed = 0;
7936
7937 while (parsed < eir_len) {
7938 u8 field_len = eir[0];
7939 u8 uuid[16];
7940 int i;
7941
7942 if (field_len == 0)
7943 break;
7944
7945 if (eir_len - parsed < field_len + 1)
7946 break;
7947
7948 switch (eir[1]) {
7949 case EIR_UUID16_ALL:
7950 case EIR_UUID16_SOME:
7951 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007952 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007953 uuid[13] = eir[i + 3];
7954 uuid[12] = eir[i + 2];
7955 if (has_uuid(uuid, uuid_count, uuids))
7956 return true;
7957 }
7958 break;
7959 case EIR_UUID32_ALL:
7960 case EIR_UUID32_SOME:
7961 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007962 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007963 uuid[15] = eir[i + 5];
7964 uuid[14] = eir[i + 4];
7965 uuid[13] = eir[i + 3];
7966 uuid[12] = eir[i + 2];
7967 if (has_uuid(uuid, uuid_count, uuids))
7968 return true;
7969 }
7970 break;
7971 case EIR_UUID128_ALL:
7972 case EIR_UUID128_SOME:
7973 for (i = 0; i + 17 <= field_len; i += 16) {
7974 memcpy(uuid, eir + i + 2, 16);
7975 if (has_uuid(uuid, uuid_count, uuids))
7976 return true;
7977 }
7978 break;
7979 }
7980
7981 parsed += field_len + 1;
7982 eir += field_len + 1;
7983 }
7984
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007985 return false;
7986}
7987
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007988static void restart_le_scan(struct hci_dev *hdev)
7989{
7990 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007991 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007992 return;
7993
7994 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7995 hdev->discovery.scan_start +
7996 hdev->discovery.scan_duration))
7997 return;
7998
7999 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8000 DISCOV_LE_RESTART_DELAY);
8001}
8002
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008003static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8004 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8005{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008006 /* If a RSSI threshold has been specified, and
8007 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8008 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8009 * is set, let it through for further processing, as we might need to
8010 * restart the scan.
8011 *
8012 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8013 * the results are also dropped.
8014 */
8015 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8016 (rssi == HCI_RSSI_INVALID ||
8017 (rssi < hdev->discovery.rssi &&
8018 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8019 return false;
8020
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008021 if (hdev->discovery.uuid_count != 0) {
8022 /* If a list of UUIDs is provided in filter, results with no
8023 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008024 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008025 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8026 hdev->discovery.uuids) &&
8027 !eir_has_uuids(scan_rsp, scan_rsp_len,
8028 hdev->discovery.uuid_count,
8029 hdev->discovery.uuids))
8030 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008031 }
8032
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008033 /* If duplicate filtering does not report RSSI changes, then restart
8034 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008035 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008036 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8037 restart_le_scan(hdev);
8038
8039 /* Validate RSSI value against the RSSI threshold once more. */
8040 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8041 rssi < hdev->discovery.rssi)
8042 return false;
8043 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008044
8045 return true;
8046}
8047
Marcel Holtmann901801b2013-10-06 23:55:51 -07008048void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008049 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8050 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008051{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008052 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008053 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008054 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008055
Johan Hedberg75ce2082014-07-02 22:42:01 +03008056 /* Don't send events for a non-kernel initiated discovery. With
8057 * LE one exception is if we have pend_le_reports > 0 in which
8058 * case we're doing passive scanning and want these events.
8059 */
8060 if (!hci_discovery_active(hdev)) {
8061 if (link_type == ACL_LINK)
8062 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008063 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008064 return;
8065 }
Andre Guedes12602d02013-04-30 15:29:40 -03008066
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008067 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008068 /* We are using service discovery */
8069 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8070 scan_rsp_len))
8071 return;
8072 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008073
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008074 /* Make sure that the buffer is big enough. The 5 extra bytes
8075 * are for the potential CoD field.
8076 */
8077 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008078 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008079
Johan Hedberg1dc06092012-01-15 21:01:23 +02008080 memset(buf, 0, sizeof(buf));
8081
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008082 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8083 * RSSI value was reported as 0 when not available. This behavior
8084 * is kept when using device discovery. This is required for full
8085 * backwards compatibility with the API.
8086 *
8087 * However when using service discovery, the value 127 will be
8088 * returned when the RSSI is not available.
8089 */
Szymon Janc91200e92015-01-22 16:57:05 +01008090 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8091 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008092 rssi = 0;
8093
Johan Hedberg841c5642014-07-07 12:45:54 +03008094 bacpy(&ev->addr.bdaddr, bdaddr);
8095 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008096 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008097 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008098
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008099 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008100 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008101 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008102
Johan Hedberg1dc06092012-01-15 21:01:23 +02008103 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8104 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008105 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008106
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008107 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008108 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008109 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008110
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008111 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8112 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008113
Marcel Holtmann901801b2013-10-06 23:55:51 -07008114 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008115}
Johan Hedberga88a9652011-03-30 13:18:12 +03008116
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008117void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8118 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008119{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008120 struct mgmt_ev_device_found *ev;
8121 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8122 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008123
Johan Hedbergb644ba32012-01-17 21:48:47 +02008124 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008125
Johan Hedbergb644ba32012-01-17 21:48:47 +02008126 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008127
Johan Hedbergb644ba32012-01-17 21:48:47 +02008128 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008129 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008130 ev->rssi = rssi;
8131
8132 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008133 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008134
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008135 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008136
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008137 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008138}
Johan Hedberg314b2382011-04-27 10:29:57 -04008139
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008140void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008141{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008142 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008143
Andre Guedes343fb142011-11-22 17:14:19 -03008144 BT_DBG("%s discovering %u", hdev->name, discovering);
8145
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008146 memset(&ev, 0, sizeof(ev));
8147 ev.type = hdev->discovery.type;
8148 ev.discovering = discovering;
8149
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008150 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008151}
Antti Julku5e762442011-08-25 16:48:02 +03008152
Marcel Holtmann1904a852015-01-11 13:50:44 -08008153static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008154{
8155 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008156}
8157
8158void mgmt_reenable_advertising(struct hci_dev *hdev)
8159{
8160 struct hci_request req;
8161
Arman Uguray24b4f382015-03-23 15:57:12 -07008162 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8163 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008164 return;
8165
8166 hci_req_init(&req, hdev);
8167 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008168 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008169}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008170
8171static struct hci_mgmt_chan chan = {
8172 .channel = HCI_CHANNEL_CONTROL,
8173 .handler_count = ARRAY_SIZE(mgmt_handlers),
8174 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008175 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008176};
8177
8178int mgmt_init(void)
8179{
8180 return hci_mgmt_chan_register(&chan);
8181}
8182
8183void mgmt_exit(void)
8184{
8185 hci_mgmt_chan_unregister(&chan);
8186}