blob: 55765dd79070f09f5e38315dd7848a5c32604781 [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 Holtmannedd3896b2014-07-02 21:30:55 +0200135 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200136 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700137 MGMT_EV_EXT_INDEX_ADDED,
138 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700139 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Arman Uguray24b4f382015-03-23 15:57:12 -0700140 MGMT_EV_ADVERTISING_ADDED,
141 MGMT_EV_ADVERTISING_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200142};
143
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700144static const u16 mgmt_untrusted_commands[] = {
145 MGMT_OP_READ_INDEX_LIST,
146 MGMT_OP_READ_INFO,
147 MGMT_OP_READ_UNCONF_INDEX_LIST,
148 MGMT_OP_READ_CONFIG_INFO,
149 MGMT_OP_READ_EXT_INDEX_LIST,
150};
151
152static const u16 mgmt_untrusted_events[] = {
153 MGMT_EV_INDEX_ADDED,
154 MGMT_EV_INDEX_REMOVED,
155 MGMT_EV_NEW_SETTINGS,
156 MGMT_EV_CLASS_OF_DEV_CHANGED,
157 MGMT_EV_LOCAL_NAME_CHANGED,
158 MGMT_EV_UNCONF_INDEX_ADDED,
159 MGMT_EV_UNCONF_INDEX_REMOVED,
160 MGMT_EV_NEW_CONFIG_OPTIONS,
161 MGMT_EV_EXT_INDEX_ADDED,
162 MGMT_EV_EXT_INDEX_REMOVED,
163};
164
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800165#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200166
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200167#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
168 "\x00\x00\x00\x00\x00\x00\x00\x00"
169
Johan Hedbergca69b792011-11-11 18:10:00 +0200170/* HCI to MGMT error code conversion table */
171static u8 mgmt_status_table[] = {
172 MGMT_STATUS_SUCCESS,
173 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
174 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
175 MGMT_STATUS_FAILED, /* Hardware Failure */
176 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
177 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200178 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200179 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
180 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
181 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
182 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
183 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
184 MGMT_STATUS_BUSY, /* Command Disallowed */
185 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
186 MGMT_STATUS_REJECTED, /* Rejected Security */
187 MGMT_STATUS_REJECTED, /* Rejected Personal */
188 MGMT_STATUS_TIMEOUT, /* Host Timeout */
189 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
190 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
191 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
192 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
193 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
194 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
195 MGMT_STATUS_BUSY, /* Repeated Attempts */
196 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
197 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
198 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
199 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
200 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
201 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
202 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
203 MGMT_STATUS_FAILED, /* Unspecified Error */
204 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
205 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
206 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
207 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
208 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
209 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
210 MGMT_STATUS_FAILED, /* Unit Link Key Used */
211 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
212 MGMT_STATUS_TIMEOUT, /* Instant Passed */
213 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
214 MGMT_STATUS_FAILED, /* Transaction Collision */
215 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
216 MGMT_STATUS_REJECTED, /* QoS Rejected */
217 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
218 MGMT_STATUS_REJECTED, /* Insufficient Security */
219 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
220 MGMT_STATUS_BUSY, /* Role Switch Pending */
221 MGMT_STATUS_FAILED, /* Slot Violation */
222 MGMT_STATUS_FAILED, /* Role Switch Failed */
223 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
224 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
225 MGMT_STATUS_BUSY, /* Host Busy Pairing */
226 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
227 MGMT_STATUS_BUSY, /* Controller Busy */
228 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
229 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
230 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
231 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
232 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
233};
234
235static u8 mgmt_status(u8 hci_status)
236{
237 if (hci_status < ARRAY_SIZE(mgmt_status_table))
238 return mgmt_status_table[hci_status];
239
240 return MGMT_STATUS_FAILED;
241}
242
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700243static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
244 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700245{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700246 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
247 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700248}
249
Marcel Holtmann72000df2015-03-16 16:11:21 -0700250static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
251 u16 len, int flag, struct sock *skip_sk)
252{
253 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
254 flag, skip_sk);
255}
256
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700257static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
258 u16 len, struct sock *skip_sk)
259{
260 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
261 HCI_MGMT_GENERIC_EVENTS, skip_sk);
262}
263
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200264static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
265 struct sock *skip_sk)
266{
267 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700268 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200269}
270
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 Holtmann08dc0e982015-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
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200835static u8 get_current_adv_instance(struct hci_dev *hdev)
836{
837 /* The "Set Advertising" setting supersedes the "Add Advertising"
838 * setting. Here we set the advertising data based on which
839 * setting was set. When neither apply, default to the global settings,
840 * represented by instance "0".
841 */
842 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
843 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Florian Grandel3ff37e62015-06-18 03:16:39 +0200844 return hdev->cur_adv_instance;
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200845
846 return 0x00;
847}
848
Arman Uguray4117ed72015-03-23 15:57:14 -0700849static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700850{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700851 u8 ad_len = 0;
852 size_t name_len;
853
854 name_len = strlen(hdev->dev_name);
855 if (name_len > 0) {
856 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
857
858 if (name_len > max_len) {
859 name_len = max_len;
860 ptr[1] = EIR_NAME_SHORT;
861 } else
862 ptr[1] = EIR_NAME_COMPLETE;
863
864 ptr[0] = name_len + 1;
865
866 memcpy(ptr + 2, hdev->dev_name, name_len);
867
868 ad_len += (name_len + 2);
869 ptr += (name_len + 2);
870 }
871
872 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700873}
874
Florian Grandelca21fbe2015-06-18 03:16:43 +0200875static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
876 u8 *ptr)
Arman Uguray4117ed72015-03-23 15:57:14 -0700877{
Florian Grandelca21fbe2015-06-18 03:16:43 +0200878 struct adv_info *adv_instance;
879
880 adv_instance = hci_find_adv_instance(hdev, instance);
881 if (!adv_instance)
882 return 0;
883
Arman Uguray4117ed72015-03-23 15:57:14 -0700884 /* TODO: Set the appropriate entries based on advertising instance flags
885 * here once flags other than 0 are supported.
886 */
Florian Grandelca21fbe2015-06-18 03:16:43 +0200887 memcpy(ptr, adv_instance->scan_rsp_data,
888 adv_instance->scan_rsp_len);
Arman Uguray4117ed72015-03-23 15:57:14 -0700889
Florian Grandelca21fbe2015-06-18 03:16:43 +0200890 return adv_instance->scan_rsp_len;
Arman Uguray4117ed72015-03-23 15:57:14 -0700891}
892
Florian Grandelefae0022015-06-18 03:16:37 +0200893static void update_inst_scan_rsp_data(struct hci_request *req, u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700894{
895 struct hci_dev *hdev = req->hdev;
896 struct hci_cp_le_set_scan_rsp_data cp;
897 u8 len;
898
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700899 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700900 return;
901
902 memset(&cp, 0, sizeof(cp));
903
Arman Uguray4117ed72015-03-23 15:57:14 -0700904 if (instance)
Florian Grandelca21fbe2015-06-18 03:16:43 +0200905 len = create_instance_scan_rsp_data(hdev, instance, cp.data);
Arman Uguray4117ed72015-03-23 15:57:14 -0700906 else
907 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700908
Johan Hedbergeb438b52013-10-16 15:31:07 +0300909 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700910 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700911 return;
912
Johan Hedbergeb438b52013-10-16 15:31:07 +0300913 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
914 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700915
916 cp.length = len;
917
918 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
919}
920
Arman Uguray4117ed72015-03-23 15:57:14 -0700921static void update_scan_rsp_data(struct hci_request *req)
922{
Florian Grandelefae0022015-06-18 03:16:37 +0200923 update_inst_scan_rsp_data(req, get_current_adv_instance(req->hdev));
Arman Uguray4117ed72015-03-23 15:57:14 -0700924}
925
Johan Hedberg9a43e252013-10-20 19:00:07 +0300926static u8 get_adv_discov_flags(struct hci_dev *hdev)
927{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200928 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300929
930 /* If there's a pending mgmt command the flags will not yet have
931 * their final values, so check for this first.
932 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200933 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300934 if (cmd) {
935 struct mgmt_mode *cp = cmd->param;
936 if (cp->val == 0x01)
937 return LE_AD_GENERAL;
938 else if (cp->val == 0x02)
939 return LE_AD_LIMITED;
940 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700941 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300942 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700943 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300944 return LE_AD_GENERAL;
945 }
946
947 return 0;
948}
949
Arman Uguraye7a685d2015-03-25 18:53:40 -0700950static bool get_connectable(struct hci_dev *hdev)
951{
952 struct mgmt_pending_cmd *cmd;
953
954 /* If there's a pending mgmt command the flag will not yet have
955 * it's final value, so check for this first.
956 */
957 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
958 if (cmd) {
959 struct mgmt_mode *cp = cmd->param;
960
961 return cp->val;
962 }
963
964 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
965}
966
967static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
968{
969 u32 flags;
Florian Grandel411b4122015-06-18 03:16:40 +0200970 struct adv_info *adv_instance;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700971
Florian Grandelbea28e62015-06-18 03:16:41 +0200972 if (instance == 0x00) {
973 /* Instance 0 always manages the "Tx Power" and "Flags"
974 * fields
975 */
976 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700977
Florian Grandelbea28e62015-06-18 03:16:41 +0200978 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting
979 * corresponds to the "connectable" instance flag.
980 */
981 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
982 flags |= MGMT_ADV_FLAG_CONNECTABLE;
Florian Grandel411b4122015-06-18 03:16:40 +0200983
Florian Grandelbea28e62015-06-18 03:16:41 +0200984 return flags;
Florian Grandel411b4122015-06-18 03:16:40 +0200985 }
Arman Uguraye7a685d2015-03-25 18:53:40 -0700986
Florian Grandelbea28e62015-06-18 03:16:41 +0200987 adv_instance = hci_find_adv_instance(hdev, instance);
Arman Uguraye7a685d2015-03-25 18:53:40 -0700988
Florian Grandelbea28e62015-06-18 03:16:41 +0200989 /* Return 0 when we got an invalid instance identifier. */
990 if (!adv_instance)
991 return 0;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700992
Florian Grandelbea28e62015-06-18 03:16:41 +0200993 return adv_instance->flags;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700994}
995
Florian Grandel7b683b72015-06-18 03:16:42 +0200996static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
Arman Ugurayc7d48832015-03-28 12:38:59 -0700997{
Florian Grandel7b683b72015-06-18 03:16:42 +0200998 u8 instance = get_current_adv_instance(hdev);
999 struct adv_info *adv_instance;
1000
1001 /* Ignore instance 0 */
1002 if (instance == 0x00)
1003 return 0;
1004
1005 adv_instance = hci_find_adv_instance(hdev, instance);
1006 if (!adv_instance)
Arman Ugurayc7d48832015-03-28 12:38:59 -07001007 return 0;
1008
1009 /* TODO: Take into account the "appearance" and "local-name" flags here.
1010 * These are currently being ignored as they are not supported.
1011 */
Florian Grandel7b683b72015-06-18 03:16:42 +02001012 return adv_instance->scan_rsp_len;
Arman Ugurayc7d48832015-03-28 12:38:59 -07001013}
1014
Arman Ugurayfdf51782015-03-25 18:53:46 -07001015static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1016{
Florian Grandelf63ba242015-06-18 03:16:44 +02001017 struct adv_info *adv_instance = NULL;
Arman Ugurayfdf51782015-03-25 18:53:46 -07001018 u8 ad_len = 0, flags = 0;
Florian Grandelf63ba242015-06-18 03:16:44 +02001019 u32 instance_flags;
1020
1021 /* Return 0 when the current instance identifier is invalid. */
1022 if (instance) {
1023 adv_instance = hci_find_adv_instance(hdev, instance);
1024 if (!adv_instance)
1025 return 0;
1026 }
1027
1028 instance_flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfdf51782015-03-25 18:53:46 -07001029
1030 /* The Add Advertising command allows userspace to set both the general
1031 * and limited discoverable flags.
1032 */
1033 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1034 flags |= LE_AD_GENERAL;
1035
1036 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1037 flags |= LE_AD_LIMITED;
1038
1039 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1040 /* If a discovery flag wasn't provided, simply use the global
1041 * settings.
1042 */
1043 if (!flags)
1044 flags |= get_adv_discov_flags(hdev);
1045
1046 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1047 flags |= LE_AD_NO_BREDR;
1048
1049 /* If flags would still be empty, then there is no need to
1050 * include the "Flags" AD field".
1051 */
1052 if (flags) {
1053 ptr[0] = 0x02;
1054 ptr[1] = EIR_FLAGS;
1055 ptr[2] = flags;
1056
1057 ad_len += 3;
1058 ptr += 3;
1059 }
1060 }
1061
Florian Grandelf63ba242015-06-18 03:16:44 +02001062 if (adv_instance) {
1063 memcpy(ptr, adv_instance->adv_data,
1064 adv_instance->adv_data_len);
1065 ad_len += adv_instance->adv_data_len;
1066 ptr += adv_instance->adv_data_len;
Marcel Holtmann38c8af62015-04-03 13:23:12 -07001067 }
1068
Arman Ugurayfdf51782015-03-25 18:53:46 -07001069 /* Provide Tx Power only if we can provide a valid value for it */
1070 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1071 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1072 ptr[0] = 0x02;
1073 ptr[1] = EIR_TX_POWER;
1074 ptr[2] = (u8)hdev->adv_tx_power;
1075
1076 ad_len += 3;
1077 ptr += 3;
1078 }
1079
Arman Ugurayfdf51782015-03-25 18:53:46 -07001080 return ad_len;
1081}
1082
Florian Grandelefae0022015-06-18 03:16:37 +02001083static void update_inst_adv_data(struct hci_request *req, u8 instance)
Arman Ugurayfdf51782015-03-25 18:53:46 -07001084{
1085 struct hci_dev *hdev = req->hdev;
1086 struct hci_cp_le_set_adv_data cp;
1087 u8 len;
1088
1089 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1090 return;
1091
1092 memset(&cp, 0, sizeof(cp));
1093
1094 len = create_instance_adv_data(hdev, instance, cp.data);
1095
1096 /* There's nothing to do if the data hasn't changed */
1097 if (hdev->adv_data_len == len &&
1098 memcmp(cp.data, hdev->adv_data, len) == 0)
1099 return;
1100
1101 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1102 hdev->adv_data_len = len;
1103
1104 cp.length = len;
1105
1106 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1107}
1108
Arman Uguraye7a685d2015-03-25 18:53:40 -07001109static void update_adv_data(struct hci_request *req)
1110{
Florian Grandelefae0022015-06-18 03:16:37 +02001111 update_inst_adv_data(req, get_current_adv_instance(req->hdev));
Arman Uguray24b4f382015-03-23 15:57:12 -07001112}
1113
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001114int mgmt_update_adv_data(struct hci_dev *hdev)
1115{
1116 struct hci_request req;
1117
1118 hci_req_init(&req, hdev);
1119 update_adv_data(&req);
1120
1121 return hci_req_run(&req, NULL);
1122}
1123
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001124static void create_eir(struct hci_dev *hdev, u8 *data)
1125{
1126 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001127 size_t name_len;
1128
1129 name_len = strlen(hdev->dev_name);
1130
1131 if (name_len > 0) {
1132 /* EIR Data type */
1133 if (name_len > 48) {
1134 name_len = 48;
1135 ptr[1] = EIR_NAME_SHORT;
1136 } else
1137 ptr[1] = EIR_NAME_COMPLETE;
1138
1139 /* EIR Data length */
1140 ptr[0] = name_len + 1;
1141
1142 memcpy(ptr + 2, hdev->dev_name, name_len);
1143
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001144 ptr += (name_len + 2);
1145 }
1146
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001147 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001148 ptr[0] = 2;
1149 ptr[1] = EIR_TX_POWER;
1150 ptr[2] = (u8) hdev->inq_tx_power;
1151
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001152 ptr += 3;
1153 }
1154
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001155 if (hdev->devid_source > 0) {
1156 ptr[0] = 9;
1157 ptr[1] = EIR_DEVICE_ID;
1158
1159 put_unaligned_le16(hdev->devid_source, ptr + 2);
1160 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1161 put_unaligned_le16(hdev->devid_product, ptr + 6);
1162 put_unaligned_le16(hdev->devid_version, ptr + 8);
1163
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001164 ptr += 10;
1165 }
1166
Johan Hedberg213202e2013-01-27 00:31:33 +02001167 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001168 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001169 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001170}
1171
Johan Hedberg890ea892013-03-15 17:06:52 -05001172static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001173{
Johan Hedberg890ea892013-03-15 17:06:52 -05001174 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001175 struct hci_cp_write_eir cp;
1176
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001177 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001178 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001179
Johan Hedberg976eb202012-10-24 21:12:01 +03001180 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001181 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001182
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001183 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001184 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001185
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001186 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001187 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001188
1189 memset(&cp, 0, sizeof(cp));
1190
1191 create_eir(hdev, cp.data);
1192
1193 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001194 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001195
1196 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1197
Johan Hedberg890ea892013-03-15 17:06:52 -05001198 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001199}
1200
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001201static u8 get_service_classes(struct hci_dev *hdev)
1202{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001203 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001204 u8 val = 0;
1205
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001206 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001207 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001208
1209 return val;
1210}
1211
Johan Hedberg890ea892013-03-15 17:06:52 -05001212static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001213{
Johan Hedberg890ea892013-03-15 17:06:52 -05001214 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001215 u8 cod[3];
1216
1217 BT_DBG("%s", hdev->name);
1218
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001219 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001220 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001221
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001222 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001223 return;
1224
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001225 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001226 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001227
1228 cod[0] = hdev->minor_class;
1229 cod[1] = hdev->major_class;
1230 cod[2] = get_service_classes(hdev);
1231
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001232 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001233 cod[1] |= 0x20;
1234
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001235 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001236 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001237
Johan Hedberg890ea892013-03-15 17:06:52 -05001238 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001239}
1240
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001241static void disable_advertising(struct hci_request *req)
1242{
1243 u8 enable = 0x00;
1244
1245 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1246}
1247
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001248static void enable_advertising(struct hci_request *req)
1249{
1250 struct hci_dev *hdev = req->hdev;
1251 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001252 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001253 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001254 u8 instance;
1255 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001256
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001257 if (hci_conn_num(hdev, LE_LINK) > 0)
1258 return;
1259
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001260 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001261 disable_advertising(req);
1262
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001263 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001264 * hci_update_random_address knows that it's safe to go ahead
1265 * and write a new random address. The flag will be set back on
1266 * as soon as the SET_ADV_ENABLE HCI command completes.
1267 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001268 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001269
Arman Uguraye7a685d2015-03-25 18:53:40 -07001270 instance = get_current_adv_instance(hdev);
1271 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001272
1273 /* If the "connectable" instance flag was not set, then choose between
1274 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1275 */
1276 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1277 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001278
Johan Hedberga4858cb2014-02-25 19:56:31 +02001279 /* Set require_privacy to true only when non-connectable
1280 * advertising is used. In that case it is fine to use a
1281 * non-resolvable private address.
1282 */
1283 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001284 return;
1285
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001286 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001287 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1288 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001289
1290 if (connectable)
1291 cp.type = LE_ADV_IND;
Florian Grandel7b683b72015-06-18 03:16:42 +02001292 else if (get_cur_adv_instance_scan_rsp_len(hdev))
Arman Ugurayc7d48832015-03-28 12:38:59 -07001293 cp.type = LE_ADV_SCAN_IND;
1294 else
1295 cp.type = LE_ADV_NONCONN_IND;
1296
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001297 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001298 cp.channel_map = hdev->le_adv_channel_map;
1299
1300 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1301
1302 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1303}
1304
Johan Hedberg7d785252011-12-15 00:47:39 +02001305static void service_cache_off(struct work_struct *work)
1306{
1307 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001308 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001309 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001310
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001311 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001312 return;
1313
Johan Hedberg890ea892013-03-15 17:06:52 -05001314 hci_req_init(&req, hdev);
1315
Johan Hedberg7d785252011-12-15 00:47:39 +02001316 hci_dev_lock(hdev);
1317
Johan Hedberg890ea892013-03-15 17:06:52 -05001318 update_eir(&req);
1319 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001320
1321 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001322
1323 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001324}
1325
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001326static void rpa_expired(struct work_struct *work)
1327{
1328 struct hci_dev *hdev = container_of(work, struct hci_dev,
1329 rpa_expired.work);
1330 struct hci_request req;
1331
1332 BT_DBG("");
1333
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001334 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001335
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001336 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001337 return;
1338
1339 /* The generation of a new RPA and programming it into the
1340 * controller happens in the enable_advertising() function.
1341 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001342 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001343 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001344 hci_req_run(&req, NULL);
1345}
1346
Johan Hedberg6a919082012-02-28 06:17:26 +02001347static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001348{
Marcel Holtmann238be782015-03-13 02:11:06 -07001349 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001350 return;
1351
Johan Hedberg4f87da82012-03-02 19:55:56 +02001352 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001353 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001354
Johan Hedberg4f87da82012-03-02 19:55:56 +02001355 /* Non-mgmt controlled devices get this bit set
1356 * implicitly so that pairing works for them, however
1357 * for mgmt we require user-space to explicitly enable
1358 * it
1359 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001360 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001361}
1362
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001363static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001364 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001365{
1366 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001367
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001368 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001369
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001370 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedberg03811012010-12-08 00:21:06 +02001372 memset(&rp, 0, sizeof(rp));
1373
Johan Hedberg03811012010-12-08 00:21:06 +02001374 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001375
1376 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001377 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001378
1379 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1380 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1381
1382 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001383
1384 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001385 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001386
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001387 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001388
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001389 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1390 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001391}
1392
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001393static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001394{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001395 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001396
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001397 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1398 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001399}
1400
Marcel Holtmann1904a852015-01-11 13:50:44 -08001401static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001402{
1403 BT_DBG("%s status 0x%02x", hdev->name, status);
1404
Johan Hedberga3172b72014-02-28 09:33:44 +02001405 if (hci_conn_count(hdev) == 0) {
1406 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001407 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001408 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001409}
1410
Johan Hedberg23a48092014-07-08 16:05:06 +03001411static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001412{
1413 struct hci_dev *hdev = req->hdev;
1414 struct hci_cp_remote_name_req_cancel cp;
1415 struct inquiry_entry *e;
1416
1417 switch (hdev->discovery.state) {
1418 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001419 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001420 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001421
1422 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001423 cancel_delayed_work(&hdev->le_scan_disable);
1424 hci_req_add_le_scan_disable(req);
1425 }
1426
Johan Hedberg23a48092014-07-08 16:05:06 +03001427 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001428
1429 case DISCOVERY_RESOLVING:
1430 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1431 NAME_PENDING);
1432 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001433 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001434
1435 bacpy(&cp.bdaddr, &e->data.bdaddr);
1436 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1437 &cp);
1438
Johan Hedberg23a48092014-07-08 16:05:06 +03001439 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001440
1441 default:
1442 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001443 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001444 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001445 return true;
1446 }
1447
Johan Hedberg21a60d32014-06-10 14:05:58 +03001448 break;
1449 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001450
1451 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001452}
1453
Arman Uguray912098a2015-03-23 15:57:15 -07001454static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1455 u8 instance)
1456{
1457 struct mgmt_ev_advertising_added ev;
1458
1459 ev.instance = instance;
1460
1461 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1462}
1463
1464static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1465 u8 instance)
1466{
1467 struct mgmt_ev_advertising_removed ev;
1468
1469 ev.instance = instance;
1470
1471 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1472}
1473
Florian Grandel7816b822015-06-18 03:16:45 +02001474static int schedule_adv_instance(struct hci_request *req, u8 instance,
1475 bool force) {
1476 struct hci_dev *hdev = req->hdev;
1477 struct adv_info *adv_instance = NULL;
1478 u16 timeout;
1479
1480 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
1481 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1482 return -EPERM;
1483
1484 if (hdev->adv_instance_timeout)
1485 return -EBUSY;
1486
1487 adv_instance = hci_find_adv_instance(hdev, instance);
1488 if (!adv_instance)
1489 return -ENOENT;
1490
1491 /* A zero timeout means unlimited advertising. As long as there is
1492 * only one instance, duration should be ignored. We still set a timeout
1493 * in case further instances are being added later on.
1494 *
1495 * If the remaining lifetime of the instance is more than the duration
1496 * then the timeout corresponds to the duration, otherwise it will be
1497 * reduced to the remaining instance lifetime.
1498 */
1499 if (adv_instance->timeout == 0 ||
1500 adv_instance->duration <= adv_instance->remaining_time)
1501 timeout = adv_instance->duration;
1502 else
1503 timeout = adv_instance->remaining_time;
1504
1505 /* The remaining time is being reduced unless the instance is being
1506 * advertised without time limit.
1507 */
1508 if (adv_instance->timeout)
1509 adv_instance->remaining_time =
1510 adv_instance->remaining_time - timeout;
1511
1512 hdev->adv_instance_timeout = timeout;
1513 queue_delayed_work(hdev->workqueue,
1514 &hdev->adv_instance_expire,
1515 msecs_to_jiffies(timeout * 1000));
1516
1517 /* If we're just re-scheduling the same instance again then do not
1518 * execute any HCI commands. This happens when a single instance is
1519 * being advertised.
1520 */
1521 if (!force && hdev->cur_adv_instance == instance &&
1522 hci_dev_test_flag(hdev, HCI_LE_ADV))
1523 return 0;
1524
1525 hdev->cur_adv_instance = instance;
1526 update_adv_data(req);
1527 update_scan_rsp_data(req);
1528 enable_advertising(req);
1529
1530 return 0;
1531}
1532
1533static void cancel_adv_timeout(struct hci_dev *hdev)
1534{
1535 if (hdev->adv_instance_timeout) {
1536 hdev->adv_instance_timeout = 0;
1537 cancel_delayed_work(&hdev->adv_instance_expire);
1538 }
1539}
1540
Arman Uguray912098a2015-03-23 15:57:15 -07001541static void clear_adv_instance(struct hci_dev *hdev)
1542{
1543 struct hci_request req;
1544
1545 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1546 return;
1547
Florian Grandel5d900e42015-06-18 03:16:35 +02001548 if (hdev->adv_instance_timeout)
1549 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07001550
1551 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1552 advertising_removed(NULL, hdev, 1);
1553 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1554
1555 if (!hdev_is_powered(hdev) ||
1556 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1557 return;
1558
1559 hci_req_init(&req, hdev);
1560 disable_advertising(&req);
1561 hci_req_run(&req, NULL);
1562}
1563
Johan Hedberg8b064a32014-02-24 14:52:22 +02001564static int clean_up_hci_state(struct hci_dev *hdev)
1565{
1566 struct hci_request req;
1567 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001568 bool discov_stopped;
1569 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001570
1571 hci_req_init(&req, hdev);
1572
1573 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1574 test_bit(HCI_PSCAN, &hdev->flags)) {
1575 u8 scan = 0x00;
1576 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1577 }
1578
Florian Grandel5d900e42015-06-18 03:16:35 +02001579 if (hdev->adv_instance_timeout)
Arman Uguray912098a2015-03-23 15:57:15 -07001580 clear_adv_instance(hdev);
1581
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001582 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001583 disable_advertising(&req);
1584
Johan Hedberg23a48092014-07-08 16:05:06 +03001585 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001586
1587 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1588 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001589 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590
Johan Hedbergc9910d02014-02-27 14:35:12 +02001591 switch (conn->state) {
1592 case BT_CONNECTED:
1593 case BT_CONFIG:
1594 dc.handle = cpu_to_le16(conn->handle);
1595 dc.reason = 0x15; /* Terminated due to Power Off */
1596 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1597 break;
1598 case BT_CONNECT:
1599 if (conn->type == LE_LINK)
1600 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1601 0, NULL);
1602 else if (conn->type == ACL_LINK)
1603 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1604 6, &conn->dst);
1605 break;
1606 case BT_CONNECT2:
1607 bacpy(&rej.bdaddr, &conn->dst);
1608 rej.reason = 0x15; /* Terminated due to Power Off */
1609 if (conn->type == ACL_LINK)
1610 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1611 sizeof(rej), &rej);
1612 else if (conn->type == SCO_LINK)
1613 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1614 sizeof(rej), &rej);
1615 break;
1616 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001617 }
1618
Johan Hedberg23a48092014-07-08 16:05:06 +03001619 err = hci_req_run(&req, clean_up_hci_complete);
1620 if (!err && discov_stopped)
1621 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1622
1623 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001624}
1625
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001626static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001627 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001628{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001629 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001630 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001631 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001632
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001633 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001634
Johan Hedberga7e80f22013-01-09 16:05:19 +02001635 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001636 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1637 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001638
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001639 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001640
Johan Hedberg333ae952015-03-17 13:48:47 +02001641 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001642 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1643 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001644 goto failed;
1645 }
1646
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001647 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001648 cancel_delayed_work(&hdev->power_off);
1649
1650 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001651 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1652 data, len);
1653 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001654 goto failed;
1655 }
1656 }
1657
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001658 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001659 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001660 goto failed;
1661 }
1662
Johan Hedberg03811012010-12-08 00:21:06 +02001663 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1664 if (!cmd) {
1665 err = -ENOMEM;
1666 goto failed;
1667 }
1668
Johan Hedberg8b064a32014-02-24 14:52:22 +02001669 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001670 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001671 err = 0;
1672 } else {
1673 /* Disconnect connections, stop scans, etc */
1674 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001675 if (!err)
1676 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1677 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001678
Johan Hedberg8b064a32014-02-24 14:52:22 +02001679 /* ENODATA means there were no HCI commands queued */
1680 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001681 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001682 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1683 err = 0;
1684 }
1685 }
Johan Hedberg03811012010-12-08 00:21:06 +02001686
1687failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001688 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001689 return err;
1690}
1691
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001692static int new_settings(struct hci_dev *hdev, struct sock *skip)
1693{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001694 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001695
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001696 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1697 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001698}
1699
Johan Hedberg91a668b2014-07-09 13:28:26 +03001700int mgmt_new_settings(struct hci_dev *hdev)
1701{
1702 return new_settings(hdev, NULL);
1703}
1704
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001705struct cmd_lookup {
1706 struct sock *sk;
1707 struct hci_dev *hdev;
1708 u8 mgmt_status;
1709};
1710
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001711static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001712{
1713 struct cmd_lookup *match = data;
1714
1715 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1716
1717 list_del(&cmd->list);
1718
1719 if (match->sk == NULL) {
1720 match->sk = cmd->sk;
1721 sock_hold(match->sk);
1722 }
1723
1724 mgmt_pending_free(cmd);
1725}
1726
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001727static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001728{
1729 u8 *status = data;
1730
Johan Hedberga69e8372015-03-06 21:08:53 +02001731 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001732 mgmt_pending_remove(cmd);
1733}
1734
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001735static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001736{
1737 if (cmd->cmd_complete) {
1738 u8 *status = data;
1739
1740 cmd->cmd_complete(cmd, *status);
1741 mgmt_pending_remove(cmd);
1742
1743 return;
1744 }
1745
1746 cmd_status_rsp(cmd, data);
1747}
1748
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001749static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001750{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001751 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1752 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001753}
1754
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001755static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001756{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001757 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1758 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001759}
1760
Johan Hedberge6fe7982013-10-02 15:45:22 +03001761static u8 mgmt_bredr_support(struct hci_dev *hdev)
1762{
1763 if (!lmp_bredr_capable(hdev))
1764 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001765 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001766 return MGMT_STATUS_REJECTED;
1767 else
1768 return MGMT_STATUS_SUCCESS;
1769}
1770
1771static u8 mgmt_le_support(struct hci_dev *hdev)
1772{
1773 if (!lmp_le_capable(hdev))
1774 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001775 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001776 return MGMT_STATUS_REJECTED;
1777 else
1778 return MGMT_STATUS_SUCCESS;
1779}
1780
Marcel Holtmann1904a852015-01-11 13:50:44 -08001781static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1782 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001783{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001784 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001785 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001786 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001787 bool changed;
1788
1789 BT_DBG("status 0x%02x", status);
1790
1791 hci_dev_lock(hdev);
1792
Johan Hedberg333ae952015-03-17 13:48:47 +02001793 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001794 if (!cmd)
1795 goto unlock;
1796
1797 if (status) {
1798 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001799 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001800 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001801 goto remove_cmd;
1802 }
1803
1804 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001805 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001806 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001807
1808 if (hdev->discov_timeout > 0) {
1809 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1810 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1811 to);
1812 }
1813 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001814 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001815 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001816
1817 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1818
1819 if (changed)
1820 new_settings(hdev, cmd->sk);
1821
Marcel Holtmann970ba522013-10-15 06:33:57 -07001822 /* When the discoverable mode gets changed, make sure
1823 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001824 * bit correctly set. Also update page scan based on whitelist
1825 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001826 */
1827 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001828 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001829 update_class(&req);
1830 hci_req_run(&req, NULL);
1831
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001832remove_cmd:
1833 mgmt_pending_remove(cmd);
1834
1835unlock:
1836 hci_dev_unlock(hdev);
1837}
1838
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001839static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001840 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001841{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001842 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001843 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001844 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001845 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001846 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001847 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001848
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001849 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001850
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001851 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1852 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001853 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1854 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001855
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001856 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001857 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1858 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001859
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001860 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001861
1862 /* Disabling discoverable requires that no timeout is set,
1863 * and enabling limited discoverable requires a timeout.
1864 */
1865 if ((cp->val == 0x00 && timeout > 0) ||
1866 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001867 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1868 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001869
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001870 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001871
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001872 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001873 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1874 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001875 goto failed;
1876 }
1877
Johan Hedberg333ae952015-03-17 13:48:47 +02001878 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1879 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001880 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1881 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001882 goto failed;
1883 }
1884
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001885 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001886 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1887 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001888 goto failed;
1889 }
1890
1891 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001892 bool changed = false;
1893
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001894 /* Setting limited discoverable when powered off is
1895 * not a valid operation since it requires a timeout
1896 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1897 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001898 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001899 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001900 changed = true;
1901 }
1902
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001903 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001904 if (err < 0)
1905 goto failed;
1906
1907 if (changed)
1908 err = new_settings(hdev, sk);
1909
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001910 goto failed;
1911 }
1912
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001913 /* If the current mode is the same, then just update the timeout
1914 * value with the new value. And if only the timeout gets updated,
1915 * then no need for any HCI transactions.
1916 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001917 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1918 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1919 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001920 cancel_delayed_work(&hdev->discov_off);
1921 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001922
Marcel Holtmann36261542013-10-15 08:28:51 -07001923 if (cp->val && hdev->discov_timeout > 0) {
1924 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001925 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001926 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001927 }
1928
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001929 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001930 goto failed;
1931 }
1932
1933 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1934 if (!cmd) {
1935 err = -ENOMEM;
1936 goto failed;
1937 }
1938
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001939 /* Cancel any potential discoverable timeout that might be
1940 * still active and store new timeout value. The arming of
1941 * the timeout happens in the complete handler.
1942 */
1943 cancel_delayed_work(&hdev->discov_off);
1944 hdev->discov_timeout = timeout;
1945
Johan Hedbergb456f872013-10-19 23:38:22 +03001946 /* Limited discoverable mode */
1947 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001948 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001949 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001950 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001951
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001952 hci_req_init(&req, hdev);
1953
Johan Hedberg9a43e252013-10-20 19:00:07 +03001954 /* The procedure for LE-only controllers is much simpler - just
1955 * update the advertising data.
1956 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001957 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001958 goto update_ad;
1959
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001960 scan = SCAN_PAGE;
1961
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001962 if (cp->val) {
1963 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001964
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001965 if (cp->val == 0x02) {
1966 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001967 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001968 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1969 hci_cp.iac_lap[1] = 0x8b;
1970 hci_cp.iac_lap[2] = 0x9e;
1971 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1972 hci_cp.iac_lap[4] = 0x8b;
1973 hci_cp.iac_lap[5] = 0x9e;
1974 } else {
1975 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001976 hci_cp.num_iac = 1;
1977 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1978 hci_cp.iac_lap[1] = 0x8b;
1979 hci_cp.iac_lap[2] = 0x9e;
1980 }
1981
1982 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1983 (hci_cp.num_iac * 3) + 1, &hci_cp);
1984
1985 scan |= SCAN_INQUIRY;
1986 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001987 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001988 }
1989
1990 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001991
Johan Hedberg9a43e252013-10-20 19:00:07 +03001992update_ad:
1993 update_adv_data(&req);
1994
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001995 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001996 if (err < 0)
1997 mgmt_pending_remove(cmd);
1998
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001999failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002000 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002001 return err;
2002}
2003
Johan Hedberg406d7802013-03-15 17:07:09 -05002004static void write_fast_connectable(struct hci_request *req, bool enable)
2005{
Johan Hedbergbd98b992013-03-15 17:07:13 -05002006 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05002007 struct hci_cp_write_page_scan_activity acp;
2008 u8 type;
2009
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002010 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03002011 return;
2012
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05002013 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
2014 return;
2015
Johan Hedberg406d7802013-03-15 17:07:09 -05002016 if (enable) {
2017 type = PAGE_SCAN_TYPE_INTERLACED;
2018
2019 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002020 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05002021 } else {
2022 type = PAGE_SCAN_TYPE_STANDARD; /* default */
2023
2024 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002025 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05002026 }
2027
Joe Perchesdcf4adb2014-03-12 10:52:35 -07002028 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05002029
Johan Hedbergbd98b992013-03-15 17:07:13 -05002030 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
2031 __cpu_to_le16(hdev->page_scan_window) != acp.window)
2032 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
2033 sizeof(acp), &acp);
2034
2035 if (hdev->page_scan_type != type)
2036 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05002037}
2038
Marcel Holtmann1904a852015-01-11 13:50:44 -08002039static void set_connectable_complete(struct hci_dev *hdev, u8 status,
2040 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05002041{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002042 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002043 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002044 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002045
2046 BT_DBG("status 0x%02x", status);
2047
2048 hci_dev_lock(hdev);
2049
Johan Hedberg333ae952015-03-17 13:48:47 +02002050 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05002051 if (!cmd)
2052 goto unlock;
2053
Johan Hedberg37438c12013-10-14 16:20:05 +03002054 if (status) {
2055 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02002056 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03002057 goto remove_cmd;
2058 }
2059
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002060 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002061 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002062 conn_changed = !hci_dev_test_and_set_flag(hdev,
2063 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002064 discov_changed = false;
2065 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002066 conn_changed = hci_dev_test_and_clear_flag(hdev,
2067 HCI_CONNECTABLE);
2068 discov_changed = hci_dev_test_and_clear_flag(hdev,
2069 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002070 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002071
Johan Hedberg2b76f452013-03-15 17:07:04 -05002072 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
2073
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002074 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002075 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002076 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03002077 if (discov_changed)
2078 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03002079 hci_update_background_scan(hdev);
2080 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002081
Johan Hedberg37438c12013-10-14 16:20:05 +03002082remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002083 mgmt_pending_remove(cmd);
2084
2085unlock:
2086 hci_dev_unlock(hdev);
2087}
2088
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002089static int set_connectable_update_settings(struct hci_dev *hdev,
2090 struct sock *sk, u8 val)
2091{
2092 bool changed = false;
2093 int err;
2094
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002095 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002096 changed = true;
2097
2098 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002099 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002100 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002101 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2102 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002103 }
2104
2105 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2106 if (err < 0)
2107 return err;
2108
Johan Hedberg562064e2014-07-08 16:35:34 +03002109 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002110 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002111 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002112 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002113 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002114
2115 return 0;
2116}
2117
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002118static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002119 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002120{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002121 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002122 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002123 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002124 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002125 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002126
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002127 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002128
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002129 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2130 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002131 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2132 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002133
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_CONNECTABLE,
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
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002140 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002141 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002142 goto failed;
2143 }
2144
Johan Hedberg333ae952015-03-17 13:48:47 +02002145 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2146 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002147 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2148 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002149 goto failed;
2150 }
2151
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002152 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2153 if (!cmd) {
2154 err = -ENOMEM;
2155 goto failed;
2156 }
2157
Johan Hedberg2b76f452013-03-15 17:07:04 -05002158 hci_req_init(&req, hdev);
2159
Johan Hedberg9a43e252013-10-20 19:00:07 +03002160 /* If BR/EDR is not enabled and we disable advertising as a
2161 * by-product of disabling connectable, we need to update the
2162 * advertising flags.
2163 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002164 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002165 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002166 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2167 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002168 }
2169 update_adv_data(&req);
2170 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002171 if (cp->val) {
2172 scan = SCAN_PAGE;
2173 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002174 /* If we don't have any whitelist entries just
2175 * disable all scanning. If there are entries
2176 * and we had both page and inquiry scanning
2177 * enabled then fall back to only page scanning.
2178 * Otherwise no changes are needed.
2179 */
2180 if (list_empty(&hdev->whitelist))
2181 scan = SCAN_DISABLED;
2182 else if (test_bit(HCI_ISCAN, &hdev->flags))
2183 scan = SCAN_PAGE;
2184 else
2185 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002186
2187 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002188 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002189 cancel_delayed_work(&hdev->discov_off);
2190 }
2191
2192 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2193 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002194
Johan Hedberg3bd27242014-07-28 20:53:58 +03002195no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002196 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002197 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2198 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002199 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002200
Johan Hedberg2b76f452013-03-15 17:07:04 -05002201 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002202 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002203 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002204 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002205 err = set_connectable_update_settings(hdev, sk,
2206 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002207 goto failed;
2208 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002209
2210failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002211 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002212 return err;
2213}
2214
Johan Hedbergb2939472014-07-30 09:22:23 +03002215static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002216 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002217{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002218 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002219 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002220 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002221
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002222 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002223
Johan Hedberga7e80f22013-01-09 16:05:19 +02002224 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002225 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2226 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002227
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002228 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002229
2230 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002231 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002232 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002233 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002234
Johan Hedbergb2939472014-07-30 09:22:23 +03002235 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002236 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002237 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002238
Marcel Holtmann55594352013-10-06 16:11:57 -07002239 if (changed)
2240 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002241
Marcel Holtmann55594352013-10-06 16:11:57 -07002242unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002243 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002244 return err;
2245}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002246
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002247static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2248 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002249{
2250 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002251 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002252 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002253 int err;
2254
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002255 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002256
Johan Hedberge6fe7982013-10-02 15:45:22 +03002257 status = mgmt_bredr_support(hdev);
2258 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002259 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2260 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002261
Johan Hedberga7e80f22013-01-09 16:05:19 +02002262 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002263 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2264 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002265
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002266 hci_dev_lock(hdev);
2267
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002268 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002269 bool changed = false;
2270
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002271 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002272 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002273 changed = true;
2274 }
2275
2276 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2277 if (err < 0)
2278 goto failed;
2279
2280 if (changed)
2281 err = new_settings(hdev, sk);
2282
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002283 goto failed;
2284 }
2285
Johan Hedberg333ae952015-03-17 13:48:47 +02002286 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002287 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2288 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002289 goto failed;
2290 }
2291
2292 val = !!cp->val;
2293
2294 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2295 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2296 goto failed;
2297 }
2298
2299 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2300 if (!cmd) {
2301 err = -ENOMEM;
2302 goto failed;
2303 }
2304
2305 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2306 if (err < 0) {
2307 mgmt_pending_remove(cmd);
2308 goto failed;
2309 }
2310
2311failed:
2312 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002313 return err;
2314}
2315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002316static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002317{
2318 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002319 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002320 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002321 int err;
2322
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002323 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002324
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002325 status = mgmt_bredr_support(hdev);
2326 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002327 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002328
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002329 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002330 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2331 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002332
Johan Hedberga7e80f22013-01-09 16:05:19 +02002333 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002334 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2335 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002336
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002337 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002338
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002339 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002340 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002341
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002342 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002343 changed = !hci_dev_test_and_set_flag(hdev,
2344 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002345 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002346 changed = hci_dev_test_and_clear_flag(hdev,
2347 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002348 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002349 changed = hci_dev_test_and_clear_flag(hdev,
2350 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002351 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002352 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002353 }
2354
2355 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2356 if (err < 0)
2357 goto failed;
2358
2359 if (changed)
2360 err = new_settings(hdev, sk);
2361
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002362 goto failed;
2363 }
2364
Johan Hedberg333ae952015-03-17 13:48:47 +02002365 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002366 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2367 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002368 goto failed;
2369 }
2370
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002371 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002372 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2373 goto failed;
2374 }
2375
2376 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2377 if (!cmd) {
2378 err = -ENOMEM;
2379 goto failed;
2380 }
2381
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002382 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002383 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2384 sizeof(cp->val), &cp->val);
2385
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002386 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002387 if (err < 0) {
2388 mgmt_pending_remove(cmd);
2389 goto failed;
2390 }
2391
2392failed:
2393 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002394 return err;
2395}
2396
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002397static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002398{
2399 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002400 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002401 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002402 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002404 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002405
Johan Hedberge6fe7982013-10-02 15:45:22 +03002406 status = mgmt_bredr_support(hdev);
2407 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002408 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002409
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002410 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002411 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2412 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002413
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002414 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002415 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2416 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002417
Johan Hedberga7e80f22013-01-09 16:05:19 +02002418 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002419 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2420 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002421
Marcel Holtmannee392692013-10-01 22:59:23 -07002422 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002423
Johan Hedberg333ae952015-03-17 13:48:47 +02002424 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002425 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2426 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002427 goto unlock;
2428 }
2429
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002430 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002431 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002432 } else {
2433 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002434 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2435 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002436 goto unlock;
2437 }
2438
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002439 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002440 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002441
2442 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2443 if (err < 0)
2444 goto unlock;
2445
2446 if (changed)
2447 err = new_settings(hdev, sk);
2448
2449unlock:
2450 hci_dev_unlock(hdev);
2451 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002452}
2453
Marcel Holtmann1904a852015-01-11 13:50:44 -08002454static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002455{
2456 struct cmd_lookup match = { NULL, hdev };
2457
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302458 hci_dev_lock(hdev);
2459
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002460 if (status) {
2461 u8 mgmt_err = mgmt_status(status);
2462
2463 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2464 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302465 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002466 }
2467
2468 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2469
2470 new_settings(hdev, match.sk);
2471
2472 if (match.sk)
2473 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002474
2475 /* Make sure the controller has a good default for
2476 * advertising data. Restrict the update to when LE
2477 * has actually been enabled. During power on, the
2478 * update in powered_update_hci will take care of it.
2479 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002480 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002481 struct hci_request req;
2482
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002483 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002484 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002485 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002486 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002487 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002488 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302489
2490unlock:
2491 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002492}
2493
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002494static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002495{
2496 struct mgmt_mode *cp = data;
2497 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002498 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002499 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002500 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002501 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002502
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002503 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002504
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002505 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002506 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2507 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002508
Johan Hedberga7e80f22013-01-09 16:05:19 +02002509 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002510 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2511 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002512
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002513 /* Bluetooth single mode LE only controllers or dual-mode
2514 * controllers configured as LE only devices, do not allow
2515 * switching LE off. These have either LE enabled explicitly
2516 * or BR/EDR has been previously switched off.
2517 *
2518 * When trying to enable an already enabled LE, then gracefully
2519 * send a positive response. Trying to disable it however will
2520 * result into rejection.
2521 */
2522 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2523 if (cp->val == 0x01)
2524 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2525
Johan Hedberga69e8372015-03-06 21:08:53 +02002526 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2527 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002528 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002529
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002530 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002531
2532 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002533 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002534
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002535 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002536 bool changed = false;
2537
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002538 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002539 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002540 changed = true;
2541 }
2542
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002543 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002544 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002545 changed = true;
2546 }
2547
Johan Hedberg06199cf2012-02-22 16:37:11 +02002548 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2549 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002550 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002551
2552 if (changed)
2553 err = new_settings(hdev, sk);
2554
Johan Hedberg1de028c2012-02-29 19:55:35 -08002555 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002556 }
2557
Johan Hedberg333ae952015-03-17 13:48:47 +02002558 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2559 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002560 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2561 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002562 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002563 }
2564
2565 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2566 if (!cmd) {
2567 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002568 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002569 }
2570
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002571 hci_req_init(&req, hdev);
2572
Johan Hedberg06199cf2012-02-22 16:37:11 +02002573 memset(&hci_cp, 0, sizeof(hci_cp));
2574
2575 if (val) {
2576 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002577 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002578 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002579 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002580 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002581 }
2582
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002583 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2584 &hci_cp);
2585
2586 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302587 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002588 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002589
Johan Hedberg1de028c2012-02-29 19:55:35 -08002590unlock:
2591 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002592 return err;
2593}
2594
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002595/* This is a helper function to test for pending mgmt commands that can
2596 * cause CoD or EIR HCI commands. We can only allow one such pending
2597 * mgmt command at a time since otherwise we cannot easily track what
2598 * the current values are, will be, and based on that calculate if a new
2599 * HCI command needs to be sent and if yes with what value.
2600 */
2601static bool pending_eir_or_class(struct hci_dev *hdev)
2602{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002603 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002604
2605 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2606 switch (cmd->opcode) {
2607 case MGMT_OP_ADD_UUID:
2608 case MGMT_OP_REMOVE_UUID:
2609 case MGMT_OP_SET_DEV_CLASS:
2610 case MGMT_OP_SET_POWERED:
2611 return true;
2612 }
2613 }
2614
2615 return false;
2616}
2617
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002618static const u8 bluetooth_base_uuid[] = {
2619 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2620 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2621};
2622
2623static u8 get_uuid_size(const u8 *uuid)
2624{
2625 u32 val;
2626
2627 if (memcmp(uuid, bluetooth_base_uuid, 12))
2628 return 128;
2629
2630 val = get_unaligned_le32(&uuid[12]);
2631 if (val > 0xffff)
2632 return 32;
2633
2634 return 16;
2635}
2636
Johan Hedberg92da6092013-03-15 17:06:55 -05002637static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2638{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002639 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002640
2641 hci_dev_lock(hdev);
2642
Johan Hedberg333ae952015-03-17 13:48:47 +02002643 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002644 if (!cmd)
2645 goto unlock;
2646
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002647 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2648 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002649
2650 mgmt_pending_remove(cmd);
2651
2652unlock:
2653 hci_dev_unlock(hdev);
2654}
2655
Marcel Holtmann1904a852015-01-11 13:50:44 -08002656static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002657{
2658 BT_DBG("status 0x%02x", status);
2659
2660 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2661}
2662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002663static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002664{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002665 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002666 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002667 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002668 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002669 int err;
2670
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002671 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002673 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002674
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002675 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002676 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2677 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002678 goto failed;
2679 }
2680
Andre Guedes92c4c202012-06-07 19:05:44 -03002681 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002682 if (!uuid) {
2683 err = -ENOMEM;
2684 goto failed;
2685 }
2686
2687 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002688 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002689 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002690
Johan Hedbergde66aa62013-01-27 00:31:27 +02002691 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002692
Johan Hedberg890ea892013-03-15 17:06:52 -05002693 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002694
Johan Hedberg890ea892013-03-15 17:06:52 -05002695 update_class(&req);
2696 update_eir(&req);
2697
Johan Hedberg92da6092013-03-15 17:06:55 -05002698 err = hci_req_run(&req, add_uuid_complete);
2699 if (err < 0) {
2700 if (err != -ENODATA)
2701 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002702
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002703 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2704 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002705 goto failed;
2706 }
2707
2708 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002709 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002710 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002711 goto failed;
2712 }
2713
2714 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002715
2716failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002717 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002718 return err;
2719}
2720
Johan Hedberg24b78d02012-02-23 23:24:30 +02002721static bool enable_service_cache(struct hci_dev *hdev)
2722{
2723 if (!hdev_is_powered(hdev))
2724 return false;
2725
Marcel Holtmann238be782015-03-13 02:11:06 -07002726 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002727 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2728 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002729 return true;
2730 }
2731
2732 return false;
2733}
2734
Marcel Holtmann1904a852015-01-11 13:50:44 -08002735static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002736{
2737 BT_DBG("status 0x%02x", status);
2738
2739 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2740}
2741
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002742static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002743 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002744{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002745 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002746 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002747 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002748 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 -05002749 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002750 int err, found;
2751
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002752 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002753
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002754 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002755
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002756 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002757 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2758 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002759 goto unlock;
2760 }
2761
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002762 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002763 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002764
Johan Hedberg24b78d02012-02-23 23:24:30 +02002765 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002766 err = mgmt_cmd_complete(sk, hdev->id,
2767 MGMT_OP_REMOVE_UUID,
2768 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002769 goto unlock;
2770 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002771
Johan Hedberg9246a862012-02-23 21:33:16 +02002772 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002773 }
2774
2775 found = 0;
2776
Johan Hedberg056341c2013-01-27 00:31:30 +02002777 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002778 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2779 continue;
2780
2781 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002782 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002783 found++;
2784 }
2785
2786 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002787 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2788 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002789 goto unlock;
2790 }
2791
Johan Hedberg9246a862012-02-23 21:33:16 +02002792update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002793 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002794
Johan Hedberg890ea892013-03-15 17:06:52 -05002795 update_class(&req);
2796 update_eir(&req);
2797
Johan Hedberg92da6092013-03-15 17:06:55 -05002798 err = hci_req_run(&req, remove_uuid_complete);
2799 if (err < 0) {
2800 if (err != -ENODATA)
2801 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002802
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002803 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2804 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002805 goto unlock;
2806 }
2807
2808 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002809 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002810 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002811 goto unlock;
2812 }
2813
2814 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002815
2816unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002817 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002818 return err;
2819}
2820
Marcel Holtmann1904a852015-01-11 13:50:44 -08002821static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002822{
2823 BT_DBG("status 0x%02x", status);
2824
2825 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2826}
2827
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002828static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002829 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002830{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002831 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002832 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002833 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002834 int err;
2835
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002836 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002837
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002838 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002839 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2840 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002841
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002842 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002843
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002844 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002845 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2846 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002847 goto unlock;
2848 }
2849
2850 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002851 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2852 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002853 goto unlock;
2854 }
2855
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002856 hdev->major_class = cp->major;
2857 hdev->minor_class = cp->minor;
2858
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002859 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002860 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2861 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002862 goto unlock;
2863 }
2864
Johan Hedberg890ea892013-03-15 17:06:52 -05002865 hci_req_init(&req, hdev);
2866
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002867 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002868 hci_dev_unlock(hdev);
2869 cancel_delayed_work_sync(&hdev->service_cache);
2870 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002871 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002872 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002873
Johan Hedberg890ea892013-03-15 17:06:52 -05002874 update_class(&req);
2875
Johan Hedberg92da6092013-03-15 17:06:55 -05002876 err = hci_req_run(&req, set_class_complete);
2877 if (err < 0) {
2878 if (err != -ENODATA)
2879 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002880
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002881 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2882 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002883 goto unlock;
2884 }
2885
2886 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002887 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002888 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002889 goto unlock;
2890 }
2891
2892 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002893
Johan Hedbergb5235a62012-02-21 14:32:24 +02002894unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002895 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002896 return err;
2897}
2898
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002899static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002900 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002901{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002902 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002903 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2904 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002905 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002906 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002907 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002908
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002909 BT_DBG("request for %s", hdev->name);
2910
2911 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002912 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2913 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002914
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002915 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002916 if (key_count > max_key_count) {
2917 BT_ERR("load_link_keys: too big key_count value %u",
2918 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002919 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2920 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002921 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002922
Johan Hedberg86742e12011-11-07 23:13:38 +02002923 expected_len = sizeof(*cp) + key_count *
2924 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002925 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002926 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002927 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002928 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2929 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002930 }
2931
Johan Hedberg4ae143012013-01-20 14:27:13 +02002932 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002933 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2934 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae143012013-01-20 14:27:13 +02002935
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002936 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002937 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002938
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002939 for (i = 0; i < key_count; i++) {
2940 struct mgmt_link_key_info *key = &cp->keys[i];
2941
Marcel Holtmann8e991132014-01-10 02:07:25 -08002942 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002943 return mgmt_cmd_status(sk, hdev->id,
2944 MGMT_OP_LOAD_LINK_KEYS,
2945 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002946 }
2947
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002948 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002949
2950 hci_link_keys_clear(hdev);
2951
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002952 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002953 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002954 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002955 changed = hci_dev_test_and_clear_flag(hdev,
2956 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002957
2958 if (changed)
2959 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002960
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002961 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002962 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002963
Johan Hedberg58e92932014-06-24 14:00:26 +03002964 /* Always ignore debug keys and require a new pairing if
2965 * the user wants to use them.
2966 */
2967 if (key->type == HCI_LK_DEBUG_COMBINATION)
2968 continue;
2969
Johan Hedberg7652ff62014-06-24 13:15:49 +03002970 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2971 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002972 }
2973
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002974 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002976 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002977
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002978 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002979}
2980
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002981static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002983{
2984 struct mgmt_ev_device_unpaired ev;
2985
2986 bacpy(&ev.addr.bdaddr, bdaddr);
2987 ev.addr.type = addr_type;
2988
2989 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002990 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002991}
2992
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002993static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002994 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002995{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002996 struct mgmt_cp_unpair_device *cp = data;
2997 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002998 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002999 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003000 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003001 int err;
3002
Johan Hedberga8a1d192011-11-10 15:54:38 +02003003 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02003004 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3005 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02003006
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003007 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003008 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3009 MGMT_STATUS_INVALID_PARAMS,
3010 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003011
Johan Hedberg118da702013-01-20 14:27:20 +02003012 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003013 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3014 MGMT_STATUS_INVALID_PARAMS,
3015 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02003016
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003017 hci_dev_lock(hdev);
3018
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02003019 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003020 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3021 MGMT_STATUS_NOT_POWERED, &rp,
3022 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02003023 goto unlock;
3024 }
3025
Johan Hedberge0b2b272014-02-18 17:14:31 +02003026 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003027 /* If disconnection is requested, then look up the
3028 * connection. If the remote device is connected, it
3029 * will be later used to terminate the link.
3030 *
3031 * Setting it to NULL explicitly will cause no
3032 * termination of the link.
3033 */
3034 if (cp->disconnect)
3035 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3036 &cp->addr.bdaddr);
3037 else
3038 conn = NULL;
3039
Johan Hedberg124f6e32012-02-09 13:50:12 +02003040 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02003041 } else {
3042 u8 addr_type;
3043
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003044 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
3045 &cp->addr.bdaddr);
3046 if (conn) {
3047 /* Defer clearing up the connection parameters
3048 * until closing to give a chance of keeping
3049 * them if a repairing happens.
3050 */
3051 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
3052
3053 /* If disconnection is not requested, then
3054 * clear the connection variable so that the
3055 * link is not terminated.
3056 */
3057 if (!cp->disconnect)
3058 conn = NULL;
3059 }
3060
Johan Hedberge0b2b272014-02-18 17:14:31 +02003061 if (cp->addr.type == BDADDR_LE_PUBLIC)
3062 addr_type = ADDR_LE_DEV_PUBLIC;
3063 else
3064 addr_type = ADDR_LE_DEV_RANDOM;
3065
Johan Hedberga7ec7332014-02-18 17:14:35 +02003066 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
3067
Johan Hedberge0b2b272014-02-18 17:14:31 +02003068 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
3069 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03003070
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003071 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003072 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
3073 MGMT_STATUS_NOT_PAIRED, &rp,
3074 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003075 goto unlock;
3076 }
3077
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003078 /* If the connection variable is set, then termination of the
3079 * link is requested.
3080 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02003081 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003082 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3083 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003084 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003085 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003086 }
3087
Johan Hedberg124f6e32012-02-09 13:50:12 +02003088 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003089 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003090 if (!cmd) {
3091 err = -ENOMEM;
3092 goto unlock;
3093 }
3094
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003095 cmd->cmd_complete = addr_cmd_complete;
3096
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003097 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003098 dc.reason = 0x13; /* Remote User Terminated Connection */
3099 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3100 if (err < 0)
3101 mgmt_pending_remove(cmd);
3102
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003103unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003104 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003105 return err;
3106}
3107
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003108static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003109 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003110{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003111 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003112 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003113 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003114 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003115 int err;
3116
3117 BT_DBG("");
3118
Johan Hedberg06a63b12013-01-20 14:27:21 +02003119 memset(&rp, 0, sizeof(rp));
3120 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3121 rp.addr.type = cp->addr.type;
3122
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003123 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003124 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3125 MGMT_STATUS_INVALID_PARAMS,
3126 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003127
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003128 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003129
3130 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003131 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3132 MGMT_STATUS_NOT_POWERED, &rp,
3133 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003134 goto failed;
3135 }
3136
Johan Hedberg333ae952015-03-17 13:48:47 +02003137 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003138 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3139 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003140 goto failed;
3141 }
3142
Andre Guedes591f47f2012-04-24 21:02:49 -03003143 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003144 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3145 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003146 else
3147 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003148
Vishal Agarwalf9607272012-06-13 05:32:43 +05303149 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003150 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3151 MGMT_STATUS_NOT_CONNECTED, &rp,
3152 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003153 goto failed;
3154 }
3155
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003156 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003157 if (!cmd) {
3158 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003159 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003160 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003161
Johan Hedbergf5818c22014-12-05 13:36:02 +02003162 cmd->cmd_complete = generic_cmd_complete;
3163
Johan Hedberge3f2f922014-08-18 20:33:33 +03003164 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003165 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003166 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003167
3168failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003169 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003170 return err;
3171}
3172
Andre Guedes57c14772012-04-24 21:02:50 -03003173static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003174{
3175 switch (link_type) {
3176 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003177 switch (addr_type) {
3178 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003179 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003180
Johan Hedberg48264f02011-11-09 13:58:58 +02003181 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003182 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003183 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003184 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003185
Johan Hedberg4c659c32011-11-07 23:13:39 +02003186 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003187 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003188 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003189 }
3190}
3191
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003192static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3193 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003194{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003195 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003196 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003197 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003198 int err;
3199 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003200
3201 BT_DBG("");
3202
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003203 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003204
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003205 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003206 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3207 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003208 goto unlock;
3209 }
3210
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003211 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003212 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3213 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003214 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003215 }
3216
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003217 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003218 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003219 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003220 err = -ENOMEM;
3221 goto unlock;
3222 }
3223
Johan Hedberg2784eb42011-01-21 13:56:35 +02003224 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003225 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003226 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3227 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003228 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003229 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003230 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003231 continue;
3232 i++;
3233 }
3234
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003235 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003236
Johan Hedberg4c659c32011-11-07 23:13:39 +02003237 /* Recalculate length in case of filtered SCO connections, etc */
3238 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003239
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003240 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3241 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003242
Johan Hedberga38528f2011-01-22 06:46:43 +02003243 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003244
3245unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003246 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003247 return err;
3248}
3249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003250static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003251 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003252{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003253 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003254 int err;
3255
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003256 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003257 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003258 if (!cmd)
3259 return -ENOMEM;
3260
Johan Hedbergd8457692012-02-17 14:24:57 +02003261 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003262 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003263 if (err < 0)
3264 mgmt_pending_remove(cmd);
3265
3266 return err;
3267}
3268
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003269static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003270 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003271{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003272 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003273 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003274 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003275 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003276 int err;
3277
3278 BT_DBG("");
3279
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003280 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003281
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003282 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003283 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3284 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003285 goto failed;
3286 }
3287
Johan Hedbergd8457692012-02-17 14:24:57 +02003288 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003289 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003290 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3291 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003292 goto failed;
3293 }
3294
3295 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003296 struct mgmt_cp_pin_code_neg_reply ncp;
3297
3298 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003299
3300 BT_ERR("PIN code is not 16 bytes long");
3301
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003302 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003303 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003304 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3305 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003306
3307 goto failed;
3308 }
3309
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003310 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003311 if (!cmd) {
3312 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003313 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003314 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003315
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003316 cmd->cmd_complete = addr_cmd_complete;
3317
Johan Hedbergd8457692012-02-17 14:24:57 +02003318 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003319 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003320 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003321
3322 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3323 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003324 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003325
3326failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003327 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003328 return err;
3329}
3330
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003331static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3332 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003333{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003334 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003335
3336 BT_DBG("");
3337
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003338 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003339 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3340 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003341
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003342 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003343
3344 hdev->io_capability = cp->io_capability;
3345
3346 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003347 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003348
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003349 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003350
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003351 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3352 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003353}
3354
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003355static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003356{
3357 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003358 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003359
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003360 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003361 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3362 continue;
3363
Johan Hedberge9a416b2011-02-19 12:05:56 -03003364 if (cmd->user_data != conn)
3365 continue;
3366
3367 return cmd;
3368 }
3369
3370 return NULL;
3371}
3372
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003373static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003374{
3375 struct mgmt_rp_pair_device rp;
3376 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003377 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003378
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003379 bacpy(&rp.addr.bdaddr, &conn->dst);
3380 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003381
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003382 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3383 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003384
3385 /* So we don't get further callbacks for this connection */
3386 conn->connect_cfm_cb = NULL;
3387 conn->security_cfm_cb = NULL;
3388 conn->disconn_cfm_cb = NULL;
3389
David Herrmann76a68ba2013-04-06 20:28:37 +02003390 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003391
3392 /* The device is paired so there is no need to remove
3393 * its connection parameters anymore.
3394 */
3395 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003396
3397 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003398
3399 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003400}
3401
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003402void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3403{
3404 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003405 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003406
3407 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003408 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003409 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003410 mgmt_pending_remove(cmd);
3411 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003412}
3413
Johan Hedberge9a416b2011-02-19 12:05:56 -03003414static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3415{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003416 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003417
3418 BT_DBG("status %u", status);
3419
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003420 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003421 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003422 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003423 return;
3424 }
3425
3426 cmd->cmd_complete(cmd, mgmt_status(status));
3427 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003428}
3429
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003430static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303431{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003432 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303433
3434 BT_DBG("status %u", status);
3435
3436 if (!status)
3437 return;
3438
3439 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003440 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303441 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003442 return;
3443 }
3444
3445 cmd->cmd_complete(cmd, mgmt_status(status));
3446 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303447}
3448
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003449static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003450 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003451{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003452 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003453 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003454 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003455 u8 sec_level, auth_type;
3456 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003457 int err;
3458
3459 BT_DBG("");
3460
Szymon Jancf950a30e2013-01-18 12:48:07 +01003461 memset(&rp, 0, sizeof(rp));
3462 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3463 rp.addr.type = cp->addr.type;
3464
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003465 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003466 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3467 MGMT_STATUS_INVALID_PARAMS,
3468 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003469
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003470 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003471 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3472 MGMT_STATUS_INVALID_PARAMS,
3473 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003474
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003475 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003476
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003477 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003478 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3479 MGMT_STATUS_NOT_POWERED, &rp,
3480 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003481 goto unlock;
3482 }
3483
Johan Hedberg55e76b32015-03-10 22:34:40 +02003484 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3485 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3486 MGMT_STATUS_ALREADY_PAIRED, &rp,
3487 sizeof(rp));
3488 goto unlock;
3489 }
3490
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003491 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003492 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003493
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003494 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003495 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3496 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003497 } else {
3498 u8 addr_type;
3499
3500 /* Convert from L2CAP channel address type to HCI address type
3501 */
3502 if (cp->addr.type == BDADDR_LE_PUBLIC)
3503 addr_type = ADDR_LE_DEV_PUBLIC;
3504 else
3505 addr_type = ADDR_LE_DEV_RANDOM;
3506
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003507 /* When pairing a new device, it is expected to remember
3508 * this device for future connections. Adding the connection
3509 * parameter information ahead of time allows tracking
3510 * of the slave preferred values and will speed up any
3511 * further connection establishment.
3512 *
3513 * If connection parameters already exist, then they
3514 * will be kept and this function does nothing.
3515 */
3516 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3517
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003518 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003519 sec_level, HCI_LE_CONN_TIMEOUT,
3520 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003521 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003522
Ville Tervo30e76272011-02-22 16:10:53 -03003523 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003524 int status;
3525
3526 if (PTR_ERR(conn) == -EBUSY)
3527 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003528 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3529 status = MGMT_STATUS_NOT_SUPPORTED;
3530 else if (PTR_ERR(conn) == -ECONNREFUSED)
3531 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003532 else
3533 status = MGMT_STATUS_CONNECT_FAILED;
3534
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003535 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3536 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003537 goto unlock;
3538 }
3539
3540 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003541 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003542 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3543 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003544 goto unlock;
3545 }
3546
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003547 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003548 if (!cmd) {
3549 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003550 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003551 goto unlock;
3552 }
3553
Johan Hedberg04ab2742014-12-05 13:36:04 +02003554 cmd->cmd_complete = pairing_complete;
3555
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003556 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003557 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003558 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003559 conn->security_cfm_cb = pairing_complete_cb;
3560 conn->disconn_cfm_cb = pairing_complete_cb;
3561 } else {
3562 conn->connect_cfm_cb = le_pairing_complete_cb;
3563 conn->security_cfm_cb = le_pairing_complete_cb;
3564 conn->disconn_cfm_cb = le_pairing_complete_cb;
3565 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003566
Johan Hedberge9a416b2011-02-19 12:05:56 -03003567 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003568 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003569
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003570 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003571 hci_conn_security(conn, sec_level, auth_type, true)) {
3572 cmd->cmd_complete(cmd, 0);
3573 mgmt_pending_remove(cmd);
3574 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003575
3576 err = 0;
3577
3578unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003579 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003580 return err;
3581}
3582
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003583static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3584 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003585{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003586 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003587 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003588 struct hci_conn *conn;
3589 int err;
3590
3591 BT_DBG("");
3592
Johan Hedberg28424702012-02-02 04:02:29 +02003593 hci_dev_lock(hdev);
3594
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003595 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003596 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3597 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003598 goto unlock;
3599 }
3600
Johan Hedberg333ae952015-03-17 13:48:47 +02003601 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003602 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003603 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3604 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003605 goto unlock;
3606 }
3607
3608 conn = cmd->user_data;
3609
3610 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003611 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3612 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003613 goto unlock;
3614 }
3615
Johan Hedberga511b352014-12-11 21:45:45 +02003616 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3617 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003618
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003619 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3620 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003621unlock:
3622 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003623 return err;
3624}
3625
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003626static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003627 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003628 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003629{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003630 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003631 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003632 int err;
3633
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003634 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003635
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003636 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003637 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3638 MGMT_STATUS_NOT_POWERED, addr,
3639 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003640 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003641 }
3642
Johan Hedberg1707c602013-03-15 17:07:15 -05003643 if (addr->type == BDADDR_BREDR)
3644 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003645 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003646 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003647
Johan Hedberg272d90d2012-02-09 15:26:12 +02003648 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003649 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3650 MGMT_STATUS_NOT_CONNECTED, addr,
3651 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003652 goto done;
3653 }
3654
Johan Hedberg1707c602013-03-15 17:07:15 -05003655 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003656 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003657 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003658 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3659 MGMT_STATUS_SUCCESS, addr,
3660 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003661 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003662 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3663 MGMT_STATUS_FAILED, addr,
3664 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003665
Brian Gix47c15e22011-11-16 13:53:14 -08003666 goto done;
3667 }
3668
Johan Hedberg1707c602013-03-15 17:07:15 -05003669 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003670 if (!cmd) {
3671 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003672 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003673 }
3674
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003675 cmd->cmd_complete = addr_cmd_complete;
3676
Brian Gix0df4c182011-11-16 13:53:13 -08003677 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003678 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3679 struct hci_cp_user_passkey_reply cp;
3680
Johan Hedberg1707c602013-03-15 17:07:15 -05003681 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003682 cp.passkey = passkey;
3683 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3684 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003685 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3686 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003687
Johan Hedberga664b5b2011-02-19 12:06:02 -03003688 if (err < 0)
3689 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003690
Brian Gix0df4c182011-11-16 13:53:13 -08003691done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003692 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003693 return err;
3694}
3695
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303696static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3697 void *data, u16 len)
3698{
3699 struct mgmt_cp_pin_code_neg_reply *cp = data;
3700
3701 BT_DBG("");
3702
Johan Hedberg1707c602013-03-15 17:07:15 -05003703 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303704 MGMT_OP_PIN_CODE_NEG_REPLY,
3705 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3706}
3707
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003708static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3709 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003710{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003711 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003712
3713 BT_DBG("");
3714
3715 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003716 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3717 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003718
Johan Hedberg1707c602013-03-15 17:07:15 -05003719 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003720 MGMT_OP_USER_CONFIRM_REPLY,
3721 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003722}
3723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003724static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003725 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003726{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003727 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003728
3729 BT_DBG("");
3730
Johan Hedberg1707c602013-03-15 17:07:15 -05003731 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003732 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3733 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003734}
3735
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003736static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3737 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003738{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003739 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003740
3741 BT_DBG("");
3742
Johan Hedberg1707c602013-03-15 17:07:15 -05003743 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003744 MGMT_OP_USER_PASSKEY_REPLY,
3745 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003746}
3747
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003748static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003749 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003750{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003751 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003752
3753 BT_DBG("");
3754
Johan Hedberg1707c602013-03-15 17:07:15 -05003755 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003756 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3757 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003758}
3759
Johan Hedberg13928972013-03-15 17:07:00 -05003760static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003761{
Johan Hedberg13928972013-03-15 17:07:00 -05003762 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003763 struct hci_cp_write_local_name cp;
3764
Johan Hedberg13928972013-03-15 17:07:00 -05003765 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003766
Johan Hedberg890ea892013-03-15 17:06:52 -05003767 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003768}
3769
Marcel Holtmann1904a852015-01-11 13:50:44 -08003770static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003771{
3772 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003773 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003774
3775 BT_DBG("status 0x%02x", status);
3776
3777 hci_dev_lock(hdev);
3778
Johan Hedberg333ae952015-03-17 13:48:47 +02003779 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003780 if (!cmd)
3781 goto unlock;
3782
3783 cp = cmd->param;
3784
3785 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003786 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3787 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003788 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003789 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3790 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003791
3792 mgmt_pending_remove(cmd);
3793
3794unlock:
3795 hci_dev_unlock(hdev);
3796}
3797
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003798static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003799 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003800{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003801 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003802 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003803 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003804 int err;
3805
3806 BT_DBG("");
3807
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003808 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003809
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003810 /* If the old values are the same as the new ones just return a
3811 * direct command complete event.
3812 */
3813 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3814 !memcmp(hdev->short_name, cp->short_name,
3815 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003816 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3817 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003818 goto failed;
3819 }
3820
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003821 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003822
Johan Hedbergb5235a62012-02-21 14:32:24 +02003823 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003824 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003825
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003826 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3827 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003828 if (err < 0)
3829 goto failed;
3830
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003831 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3832 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003833
Johan Hedbergb5235a62012-02-21 14:32:24 +02003834 goto failed;
3835 }
3836
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003837 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003838 if (!cmd) {
3839 err = -ENOMEM;
3840 goto failed;
3841 }
3842
Johan Hedberg13928972013-03-15 17:07:00 -05003843 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3844
Johan Hedberg890ea892013-03-15 17:06:52 -05003845 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003846
3847 if (lmp_bredr_capable(hdev)) {
3848 update_name(&req);
3849 update_eir(&req);
3850 }
3851
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003852 /* The name is stored in the scan response data and so
3853 * no need to udpate the advertising data here.
3854 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003855 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003856 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003857
Johan Hedberg13928972013-03-15 17:07:00 -05003858 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003859 if (err < 0)
3860 mgmt_pending_remove(cmd);
3861
3862failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003863 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003864 return err;
3865}
3866
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003867static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3868 u16 opcode, struct sk_buff *skb)
3869{
3870 struct mgmt_rp_read_local_oob_data mgmt_rp;
3871 size_t rp_size = sizeof(mgmt_rp);
3872 struct mgmt_pending_cmd *cmd;
3873
3874 BT_DBG("%s status %u", hdev->name, status);
3875
3876 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3877 if (!cmd)
3878 return;
3879
3880 if (status || !skb) {
3881 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3882 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3883 goto remove;
3884 }
3885
3886 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3887
3888 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3889 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3890
3891 if (skb->len < sizeof(*rp)) {
3892 mgmt_cmd_status(cmd->sk, hdev->id,
3893 MGMT_OP_READ_LOCAL_OOB_DATA,
3894 MGMT_STATUS_FAILED);
3895 goto remove;
3896 }
3897
3898 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3899 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3900
3901 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3902 } else {
3903 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3904
3905 if (skb->len < sizeof(*rp)) {
3906 mgmt_cmd_status(cmd->sk, hdev->id,
3907 MGMT_OP_READ_LOCAL_OOB_DATA,
3908 MGMT_STATUS_FAILED);
3909 goto remove;
3910 }
3911
3912 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3913 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3914
3915 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3916 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3917 }
3918
3919 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3920 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3921
3922remove:
3923 mgmt_pending_remove(cmd);
3924}
3925
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003926static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003927 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003928{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003929 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003930 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003931 int err;
3932
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003933 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003934
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003935 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003936
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003937 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003938 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3939 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003940 goto unlock;
3941 }
3942
Andre Guedes9a1a1992012-07-24 15:03:48 -03003943 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003944 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3945 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003946 goto unlock;
3947 }
3948
Johan Hedberg333ae952015-03-17 13:48:47 +02003949 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003950 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3951 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003952 goto unlock;
3953 }
3954
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003955 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003956 if (!cmd) {
3957 err = -ENOMEM;
3958 goto unlock;
3959 }
3960
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003961 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003962
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003963 if (bredr_sc_enabled(hdev))
3964 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3965 else
3966 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3967
3968 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003969 if (err < 0)
3970 mgmt_pending_remove(cmd);
3971
3972unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003973 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003974 return err;
3975}
3976
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003977static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003978 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003979{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003980 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003981 int err;
3982
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003983 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003984
Johan Hedberg5d57e792015-01-23 10:10:38 +02003985 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003986 return mgmt_cmd_complete(sk, hdev->id,
3987 MGMT_OP_ADD_REMOTE_OOB_DATA,
3988 MGMT_STATUS_INVALID_PARAMS,
3989 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003990
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003991 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003992
Marcel Holtmannec109112014-01-10 02:07:30 -08003993 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3994 struct mgmt_cp_add_remote_oob_data *cp = data;
3995 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003996
Johan Hedbergc19a4952014-11-17 20:52:19 +02003997 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003998 err = mgmt_cmd_complete(sk, hdev->id,
3999 MGMT_OP_ADD_REMOTE_OOB_DATA,
4000 MGMT_STATUS_INVALID_PARAMS,
4001 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004002 goto unlock;
4003 }
4004
Marcel Holtmannec109112014-01-10 02:07:30 -08004005 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01004006 cp->addr.type, cp->hash,
4007 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08004008 if (err < 0)
4009 status = MGMT_STATUS_FAILED;
4010 else
4011 status = MGMT_STATUS_SUCCESS;
4012
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004013 err = mgmt_cmd_complete(sk, hdev->id,
4014 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
4015 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08004016 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
4017 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004018 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08004019 u8 status;
4020
Johan Hedberg86df9202014-10-26 20:52:27 +01004021 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02004022 /* Enforce zero-valued 192-bit parameters as
4023 * long as legacy SMP OOB isn't implemented.
4024 */
4025 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
4026 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004027 err = mgmt_cmd_complete(sk, hdev->id,
4028 MGMT_OP_ADD_REMOTE_OOB_DATA,
4029 MGMT_STATUS_INVALID_PARAMS,
4030 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02004031 goto unlock;
4032 }
4033
Johan Hedberg86df9202014-10-26 20:52:27 +01004034 rand192 = NULL;
4035 hash192 = NULL;
4036 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004037 /* In case one of the P-192 values is set to zero,
4038 * then just disable OOB data for P-192.
4039 */
4040 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
4041 !memcmp(cp->hash192, ZERO_KEY, 16)) {
4042 rand192 = NULL;
4043 hash192 = NULL;
4044 } else {
4045 rand192 = cp->rand192;
4046 hash192 = cp->hash192;
4047 }
4048 }
4049
4050 /* In case one of the P-256 values is set to zero, then just
4051 * disable OOB data for P-256.
4052 */
4053 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
4054 !memcmp(cp->hash256, ZERO_KEY, 16)) {
4055 rand256 = NULL;
4056 hash256 = NULL;
4057 } else {
4058 rand256 = cp->rand256;
4059 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01004060 }
4061
Johan Hedberg81328d5c2014-10-26 20:33:47 +01004062 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01004063 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08004064 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08004065 if (err < 0)
4066 status = MGMT_STATUS_FAILED;
4067 else
4068 status = MGMT_STATUS_SUCCESS;
4069
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004070 err = mgmt_cmd_complete(sk, hdev->id,
4071 MGMT_OP_ADD_REMOTE_OOB_DATA,
4072 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08004073 } else {
4074 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02004075 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
4076 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08004077 }
Szymon Janc2763eda2011-03-22 13:12:22 +01004078
Johan Hedbergc19a4952014-11-17 20:52:19 +02004079unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004080 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004081 return err;
4082}
4083
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004084static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004085 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01004086{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004087 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004088 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01004089 int err;
4090
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004091 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01004092
Johan Hedbergc19a4952014-11-17 20:52:19 +02004093 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004094 return mgmt_cmd_complete(sk, hdev->id,
4095 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4096 MGMT_STATUS_INVALID_PARAMS,
4097 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004098
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004099 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004100
Johan Hedbergeedbd582014-11-15 09:34:23 +02004101 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4102 hci_remote_oob_data_clear(hdev);
4103 status = MGMT_STATUS_SUCCESS;
4104 goto done;
4105 }
4106
Johan Hedberg6928a922014-10-26 20:46:09 +01004107 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004108 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004109 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004110 else
Szymon Janca6785be2012-12-13 15:11:21 +01004111 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004112
Johan Hedbergeedbd582014-11-15 09:34:23 +02004113done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004114 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4115 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004116
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004117 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004118 return err;
4119}
4120
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004121static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
4122{
4123 struct hci_dev *hdev = req->hdev;
4124 struct hci_cp_inquiry cp;
4125 /* General inquiry access code (GIAC) */
4126 u8 lap[3] = { 0x33, 0x8b, 0x9e };
4127
4128 *status = mgmt_bredr_support(hdev);
4129 if (*status)
4130 return false;
4131
4132 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
4133 *status = MGMT_STATUS_BUSY;
4134 return false;
4135 }
4136
4137 hci_inquiry_cache_flush(hdev);
4138
4139 memset(&cp, 0, sizeof(cp));
4140 memcpy(&cp.lap, lap, sizeof(cp.lap));
4141 cp.length = DISCOV_BREDR_INQUIRY_LEN;
4142
4143 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4144
4145 return true;
4146}
4147
4148static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004149{
Marcel Holtmann80190442014-12-04 11:36:36 +01004150 struct hci_dev *hdev = req->hdev;
4151 struct hci_cp_le_set_scan_param param_cp;
4152 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004153 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004154 int err;
4155
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004156 *status = mgmt_le_support(hdev);
4157 if (*status)
4158 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004159
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004160 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4161 /* Don't let discovery abort an outgoing connection attempt
4162 * that's using directed advertising.
4163 */
4164 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4165 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004166 return false;
4167 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004168
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004169 disable_advertising(req);
4170 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004171
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004172 /* If controller is scanning, it means the background scanning is
4173 * running. Thus, we should temporarily stop it in order to set the
4174 * discovery scanning parameters.
4175 */
4176 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4177 hci_req_add_le_scan_disable(req);
4178
4179 /* All active scans will be done with either a resolvable private
4180 * address (when privacy feature has been enabled) or non-resolvable
4181 * private address.
4182 */
4183 err = hci_update_random_address(req, true, &own_addr_type);
4184 if (err < 0) {
4185 *status = MGMT_STATUS_FAILED;
4186 return false;
4187 }
4188
4189 memset(&param_cp, 0, sizeof(param_cp));
4190 param_cp.type = LE_SCAN_ACTIVE;
4191 param_cp.interval = cpu_to_le16(interval);
4192 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4193 param_cp.own_address_type = own_addr_type;
4194
4195 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4196 &param_cp);
4197
4198 memset(&enable_cp, 0, sizeof(enable_cp));
4199 enable_cp.enable = LE_SCAN_ENABLE;
4200 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4201
4202 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4203 &enable_cp);
4204
4205 return true;
4206}
4207
4208static bool trigger_discovery(struct hci_request *req, u8 *status)
4209{
4210 struct hci_dev *hdev = req->hdev;
4211
4212 switch (hdev->discovery.type) {
4213 case DISCOV_TYPE_BREDR:
4214 if (!trigger_bredr_inquiry(req, status))
4215 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004216 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004217
Marcel Holtmann80190442014-12-04 11:36:36 +01004218 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004219 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4220 &hdev->quirks)) {
4221 /* During simultaneous discovery, we double LE scan
4222 * interval. We must leave some time for the controller
4223 * to do BR/EDR inquiry.
4224 */
4225 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4226 status))
4227 return false;
4228
4229 if (!trigger_bredr_inquiry(req, status))
4230 return false;
4231
4232 return true;
4233 }
4234
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004235 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004236 *status = MGMT_STATUS_NOT_SUPPORTED;
4237 return false;
4238 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004239 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004240
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004241 case DISCOV_TYPE_LE:
4242 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004243 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004244 break;
4245
4246 default:
4247 *status = MGMT_STATUS_INVALID_PARAMS;
4248 return false;
4249 }
4250
4251 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004252}
4253
Marcel Holtmann1904a852015-01-11 13:50:44 -08004254static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4255 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004256{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004257 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004258 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004259
Andre Guedes7c307722013-04-30 15:29:28 -03004260 BT_DBG("status %d", status);
4261
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004262 hci_dev_lock(hdev);
4263
Johan Hedberg333ae952015-03-17 13:48:47 +02004264 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004265 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004266 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004267
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004268 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004269 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004270 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004271 }
4272
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004273 if (status) {
4274 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4275 goto unlock;
4276 }
4277
Andre Guedes7c307722013-04-30 15:29:28 -03004278 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004279
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004280 /* If the scan involves LE scan, pick proper timeout to schedule
4281 * hdev->le_scan_disable that will stop it.
4282 */
Andre Guedes7c307722013-04-30 15:29:28 -03004283 switch (hdev->discovery.type) {
4284 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004285 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004286 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004287 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004288 /* When running simultaneous discovery, the LE scanning time
4289 * should occupy the whole discovery time sine BR/EDR inquiry
4290 * and LE scanning are scheduled by the controller.
4291 *
4292 * For interleaving discovery in comparison, BR/EDR inquiry
4293 * and LE scanning are done sequentially with separate
4294 * timeouts.
4295 */
4296 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4297 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4298 else
4299 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004300 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004301 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004302 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004303 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004304 default:
4305 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004306 timeout = 0;
4307 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004308 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004309
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004310 if (timeout) {
4311 /* When service discovery is used and the controller has
4312 * a strict duplicate filter, it is important to remember
4313 * the start and duration of the scan. This is required
4314 * for restarting scanning during the discovery phase.
4315 */
4316 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4317 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004318 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004319 hdev->discovery.scan_start = jiffies;
4320 hdev->discovery.scan_duration = timeout;
4321 }
4322
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004323 queue_delayed_work(hdev->workqueue,
4324 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004325 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004326
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004327unlock:
4328 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004329}
4330
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004331static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004332 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004333{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004334 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004335 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004336 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004337 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004338 int err;
4339
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004340 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004341
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004342 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004343
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004344 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004345 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4346 MGMT_STATUS_NOT_POWERED,
4347 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004348 goto failed;
4349 }
4350
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004351 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004352 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004353 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4354 MGMT_STATUS_BUSY, &cp->type,
4355 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004356 goto failed;
4357 }
4358
Johan Hedberg2922a942014-12-05 13:36:06 +02004359 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004360 if (!cmd) {
4361 err = -ENOMEM;
4362 goto failed;
4363 }
4364
Johan Hedberg2922a942014-12-05 13:36:06 +02004365 cmd->cmd_complete = generic_cmd_complete;
4366
Marcel Holtmann22078802014-12-05 11:45:22 +01004367 /* Clear the discovery filter first to free any previously
4368 * allocated memory for the UUID list.
4369 */
4370 hci_discovery_filter_clear(hdev);
4371
Andre Guedes4aab14e2012-02-17 20:39:36 -03004372 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004373 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004374
Andre Guedes7c307722013-04-30 15:29:28 -03004375 hci_req_init(&req, hdev);
4376
Marcel Holtmann80190442014-12-04 11:36:36 +01004377 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004378 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4379 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004380 mgmt_pending_remove(cmd);
4381 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004382 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004383
Andre Guedes7c307722013-04-30 15:29:28 -03004384 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004385 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004386 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004387 goto failed;
4388 }
4389
4390 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004391
4392failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004393 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004394 return err;
4395}
4396
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004397static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4398 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004399{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004400 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4401 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004402}
4403
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004404static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4405 void *data, u16 len)
4406{
4407 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004408 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004409 struct hci_request req;
4410 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4411 u16 uuid_count, expected_len;
4412 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004413 int err;
4414
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004415 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004416
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004417 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004418
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004419 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004420 err = mgmt_cmd_complete(sk, hdev->id,
4421 MGMT_OP_START_SERVICE_DISCOVERY,
4422 MGMT_STATUS_NOT_POWERED,
4423 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004424 goto failed;
4425 }
4426
4427 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004428 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004429 err = mgmt_cmd_complete(sk, hdev->id,
4430 MGMT_OP_START_SERVICE_DISCOVERY,
4431 MGMT_STATUS_BUSY, &cp->type,
4432 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004433 goto failed;
4434 }
4435
4436 uuid_count = __le16_to_cpu(cp->uuid_count);
4437 if (uuid_count > max_uuid_count) {
4438 BT_ERR("service_discovery: too big uuid_count value %u",
4439 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004440 err = mgmt_cmd_complete(sk, hdev->id,
4441 MGMT_OP_START_SERVICE_DISCOVERY,
4442 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4443 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004444 goto failed;
4445 }
4446
4447 expected_len = sizeof(*cp) + uuid_count * 16;
4448 if (expected_len != len) {
4449 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4450 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004451 err = mgmt_cmd_complete(sk, hdev->id,
4452 MGMT_OP_START_SERVICE_DISCOVERY,
4453 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4454 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004455 goto failed;
4456 }
4457
4458 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004459 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004460 if (!cmd) {
4461 err = -ENOMEM;
4462 goto failed;
4463 }
4464
Johan Hedberg2922a942014-12-05 13:36:06 +02004465 cmd->cmd_complete = service_discovery_cmd_complete;
4466
Marcel Holtmann22078802014-12-05 11:45:22 +01004467 /* Clear the discovery filter first to free any previously
4468 * allocated memory for the UUID list.
4469 */
4470 hci_discovery_filter_clear(hdev);
4471
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004472 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004473 hdev->discovery.type = cp->type;
4474 hdev->discovery.rssi = cp->rssi;
4475 hdev->discovery.uuid_count = uuid_count;
4476
4477 if (uuid_count > 0) {
4478 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4479 GFP_KERNEL);
4480 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004481 err = mgmt_cmd_complete(sk, hdev->id,
4482 MGMT_OP_START_SERVICE_DISCOVERY,
4483 MGMT_STATUS_FAILED,
4484 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004485 mgmt_pending_remove(cmd);
4486 goto failed;
4487 }
4488 }
4489
4490 hci_req_init(&req, hdev);
4491
4492 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004493 err = mgmt_cmd_complete(sk, hdev->id,
4494 MGMT_OP_START_SERVICE_DISCOVERY,
4495 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004496 mgmt_pending_remove(cmd);
4497 goto failed;
4498 }
4499
4500 err = hci_req_run(&req, start_discovery_complete);
4501 if (err < 0) {
4502 mgmt_pending_remove(cmd);
4503 goto failed;
4504 }
4505
4506 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4507
4508failed:
4509 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004510 return err;
4511}
4512
Marcel Holtmann1904a852015-01-11 13:50:44 -08004513static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004514{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004515 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004516
Andre Guedes0e05bba2013-04-30 15:29:33 -03004517 BT_DBG("status %d", status);
4518
4519 hci_dev_lock(hdev);
4520
Johan Hedberg333ae952015-03-17 13:48:47 +02004521 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004522 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004523 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004524 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004525 }
4526
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004527 if (!status)
4528 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004529
Andre Guedes0e05bba2013-04-30 15:29:33 -03004530 hci_dev_unlock(hdev);
4531}
4532
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004533static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004534 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004535{
Johan Hedbergd9306502012-02-20 23:25:18 +02004536 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004537 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004538 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004539 int err;
4540
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004541 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004542
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004543 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004544
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004545 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004546 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4547 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4548 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004549 goto unlock;
4550 }
4551
4552 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004553 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4554 MGMT_STATUS_INVALID_PARAMS,
4555 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004556 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004557 }
4558
Johan Hedberg2922a942014-12-05 13:36:06 +02004559 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004560 if (!cmd) {
4561 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004562 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004563 }
4564
Johan Hedberg2922a942014-12-05 13:36:06 +02004565 cmd->cmd_complete = generic_cmd_complete;
4566
Andre Guedes0e05bba2013-04-30 15:29:33 -03004567 hci_req_init(&req, hdev);
4568
Johan Hedberg21a60d32014-06-10 14:05:58 +03004569 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004570
Johan Hedberg21a60d32014-06-10 14:05:58 +03004571 err = hci_req_run(&req, stop_discovery_complete);
4572 if (!err) {
4573 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004574 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004575 }
4576
Johan Hedberg21a60d32014-06-10 14:05:58 +03004577 mgmt_pending_remove(cmd);
4578
4579 /* If no HCI commands were sent we're done */
4580 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004581 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4582 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004583 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4584 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004585
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004586unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004587 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004588 return err;
4589}
4590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004591static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004592 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004593{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004594 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004595 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004596 int err;
4597
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004598 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004599
Johan Hedberg561aafb2012-01-04 13:31:59 +02004600 hci_dev_lock(hdev);
4601
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004602 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004603 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4604 MGMT_STATUS_FAILED, &cp->addr,
4605 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004606 goto failed;
4607 }
4608
Johan Hedberga198e7b2012-02-17 14:27:06 +02004609 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004610 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004611 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4612 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4613 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004614 goto failed;
4615 }
4616
4617 if (cp->name_known) {
4618 e->name_state = NAME_KNOWN;
4619 list_del(&e->list);
4620 } else {
4621 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004622 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004623 }
4624
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004625 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4626 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004627
4628failed:
4629 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004630 return err;
4631}
4632
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004633static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004634 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004635{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004636 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004637 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004638 int err;
4639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004640 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004641
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004642 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004643 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4644 MGMT_STATUS_INVALID_PARAMS,
4645 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004646
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004647 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004648
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004649 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4650 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004651 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004652 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004653 goto done;
4654 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004655
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004656 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4657 sk);
4658 status = MGMT_STATUS_SUCCESS;
4659
4660done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004661 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4662 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004663
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004664 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004665
4666 return err;
4667}
4668
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004669static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004670 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004671{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004672 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004673 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004674 int err;
4675
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004676 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004677
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004678 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004679 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4680 MGMT_STATUS_INVALID_PARAMS,
4681 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004682
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004683 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004684
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004685 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4686 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004687 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004688 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004689 goto done;
4690 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004691
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004692 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4693 sk);
4694 status = MGMT_STATUS_SUCCESS;
4695
4696done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004697 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4698 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004699
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004700 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004701
4702 return err;
4703}
4704
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004705static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4706 u16 len)
4707{
4708 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004709 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004710 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004711 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004712
4713 BT_DBG("%s", hdev->name);
4714
Szymon Jancc72d4b82012-03-16 16:02:57 +01004715 source = __le16_to_cpu(cp->source);
4716
4717 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004718 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4719 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004720
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004721 hci_dev_lock(hdev);
4722
Szymon Jancc72d4b82012-03-16 16:02:57 +01004723 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004724 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4725 hdev->devid_product = __le16_to_cpu(cp->product);
4726 hdev->devid_version = __le16_to_cpu(cp->version);
4727
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004728 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4729 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004730
Johan Hedberg890ea892013-03-15 17:06:52 -05004731 hci_req_init(&req, hdev);
4732 update_eir(&req);
4733 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004734
4735 hci_dev_unlock(hdev);
4736
4737 return err;
4738}
4739
Arman Uguray24b4f382015-03-23 15:57:12 -07004740static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4741 u16 opcode)
4742{
4743 BT_DBG("status %d", status);
4744}
4745
Marcel Holtmann1904a852015-01-11 13:50:44 -08004746static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4747 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004748{
4749 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004750 struct hci_request req;
Florian Grandel7816b822015-06-18 03:16:45 +02004751 u8 instance;
4752 struct adv_info *adv_instance;
4753 int err;
Johan Hedberg4375f102013-09-25 13:26:10 +03004754
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304755 hci_dev_lock(hdev);
4756
Johan Hedberg4375f102013-09-25 13:26:10 +03004757 if (status) {
4758 u8 mgmt_err = mgmt_status(status);
4759
4760 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4761 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304762 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004763 }
4764
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004765 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004766 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004767 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004768 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004769
Johan Hedberg4375f102013-09-25 13:26:10 +03004770 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4771 &match);
4772
4773 new_settings(hdev, match.sk);
4774
4775 if (match.sk)
4776 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304777
Arman Uguray24b4f382015-03-23 15:57:12 -07004778 /* If "Set Advertising" was just disabled and instance advertising was
Florian Grandel7816b822015-06-18 03:16:45 +02004779 * set up earlier, then re-enable multi-instance advertising.
Arman Uguray24b4f382015-03-23 15:57:12 -07004780 */
4781 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
Florian Grandel7816b822015-06-18 03:16:45 +02004782 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) ||
4783 list_empty(&hdev->adv_instances))
Arman Uguray24b4f382015-03-23 15:57:12 -07004784 goto unlock;
4785
Florian Grandel7816b822015-06-18 03:16:45 +02004786 instance = hdev->cur_adv_instance;
4787 if (!instance) {
4788 adv_instance = list_first_entry_or_null(&hdev->adv_instances,
4789 struct adv_info, list);
4790 if (!adv_instance)
4791 goto unlock;
4792
4793 instance = adv_instance->instance;
4794 }
4795
Arman Uguray24b4f382015-03-23 15:57:12 -07004796 hci_req_init(&req, hdev);
4797
Florian Grandel7816b822015-06-18 03:16:45 +02004798 err = schedule_adv_instance(&req, instance, true);
Arman Uguray24b4f382015-03-23 15:57:12 -07004799
Florian Grandel7816b822015-06-18 03:16:45 +02004800 if (!err)
4801 err = hci_req_run(&req, enable_advertising_instance);
4802
4803 if (err)
Arman Uguray24b4f382015-03-23 15:57:12 -07004804 BT_ERR("Failed to re-configure advertising");
4805
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304806unlock:
4807 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004808}
4809
Marcel Holtmann21b51872013-10-10 09:47:53 -07004810static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4811 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004812{
4813 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004814 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004815 struct hci_request req;
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004816 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004817 int err;
4818
4819 BT_DBG("request for %s", hdev->name);
4820
Johan Hedberge6fe7982013-10-02 15:45:22 +03004821 status = mgmt_le_support(hdev);
4822 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004823 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4824 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004825
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004826 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004827 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4828 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004829
4830 hci_dev_lock(hdev);
4831
4832 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004833
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004834 /* The following conditions are ones which mean that we should
4835 * not do any HCI communication but directly send a mgmt
4836 * response to user space (after toggling the flag if
4837 * necessary).
4838 */
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004839 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004840 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4841 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004842 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004843 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004844 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004845 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004846
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004847 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004848 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004849 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004850 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004851 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004852 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004853 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004854 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004855 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004856 }
4857
4858 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4859 if (err < 0)
4860 goto unlock;
4861
4862 if (changed)
4863 err = new_settings(hdev, sk);
4864
4865 goto unlock;
4866 }
4867
Johan Hedberg333ae952015-03-17 13:48:47 +02004868 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4869 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004870 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4871 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004872 goto unlock;
4873 }
4874
4875 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4876 if (!cmd) {
4877 err = -ENOMEM;
4878 goto unlock;
4879 }
4880
4881 hci_req_init(&req, hdev);
4882
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004883 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004884 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004885 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004886 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb042015-03-12 22:30:58 -07004887
Florian Grandel7816b822015-06-18 03:16:45 +02004888 cancel_adv_timeout(hdev);
4889
Arman Uguray24b4f382015-03-23 15:57:12 -07004890 if (val) {
Florian Grandel7816b822015-06-18 03:16:45 +02004891 /* Switch to instance "0" for the Set Advertising setting.
4892 * We cannot use update_[adv|scan_rsp]_data() here as the
4893 * HCI_ADVERTISING flag is not yet set.
4894 */
Florian Grandelefae0022015-06-18 03:16:37 +02004895 update_inst_adv_data(&req, 0x00);
4896 update_inst_scan_rsp_data(&req, 0x00);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004897 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004898 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004899 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004900 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004901
4902 err = hci_req_run(&req, set_advertising_complete);
4903 if (err < 0)
4904 mgmt_pending_remove(cmd);
4905
4906unlock:
4907 hci_dev_unlock(hdev);
4908 return err;
4909}
4910
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004911static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4912 void *data, u16 len)
4913{
4914 struct mgmt_cp_set_static_address *cp = data;
4915 int err;
4916
4917 BT_DBG("%s", hdev->name);
4918
Marcel Holtmann62af4442013-10-02 22:10:32 -07004919 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004920 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4921 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004922
4923 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004924 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4925 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004926
4927 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4928 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004929 return mgmt_cmd_status(sk, hdev->id,
4930 MGMT_OP_SET_STATIC_ADDRESS,
4931 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004932
4933 /* Two most significant bits shall be set */
4934 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004935 return mgmt_cmd_status(sk, hdev->id,
4936 MGMT_OP_SET_STATIC_ADDRESS,
4937 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004938 }
4939
4940 hci_dev_lock(hdev);
4941
4942 bacpy(&hdev->static_addr, &cp->bdaddr);
4943
Marcel Holtmann93690c22015-03-06 10:11:21 -08004944 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4945 if (err < 0)
4946 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004947
Marcel Holtmann93690c22015-03-06 10:11:21 -08004948 err = new_settings(hdev, sk);
4949
4950unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004951 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004952 return err;
4953}
4954
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004955static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4956 void *data, u16 len)
4957{
4958 struct mgmt_cp_set_scan_params *cp = data;
4959 __u16 interval, window;
4960 int err;
4961
4962 BT_DBG("%s", hdev->name);
4963
4964 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004965 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4966 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004967
4968 interval = __le16_to_cpu(cp->interval);
4969
4970 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004971 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4972 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004973
4974 window = __le16_to_cpu(cp->window);
4975
4976 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004977 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4978 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004979
Marcel Holtmann899e1072013-10-14 09:55:32 -07004980 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004981 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4982 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004983
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004984 hci_dev_lock(hdev);
4985
4986 hdev->le_scan_interval = interval;
4987 hdev->le_scan_window = window;
4988
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004989 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4990 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004991
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004992 /* If background scan is running, restart it so new parameters are
4993 * loaded.
4994 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004995 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004996 hdev->discovery.state == DISCOVERY_STOPPED) {
4997 struct hci_request req;
4998
4999 hci_req_init(&req, hdev);
5000
5001 hci_req_add_le_scan_disable(&req);
5002 hci_req_add_le_passive_scan(&req);
5003
5004 hci_req_run(&req, NULL);
5005 }
5006
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005007 hci_dev_unlock(hdev);
5008
5009 return err;
5010}
5011
Marcel Holtmann1904a852015-01-11 13:50:44 -08005012static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
5013 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05005014{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005015 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05005016
5017 BT_DBG("status 0x%02x", status);
5018
5019 hci_dev_lock(hdev);
5020
Johan Hedberg333ae952015-03-17 13:48:47 +02005021 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005022 if (!cmd)
5023 goto unlock;
5024
5025 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005026 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5027 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05005028 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05005029 struct mgmt_mode *cp = cmd->param;
5030
5031 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005032 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05005033 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005034 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05005035
Johan Hedberg33e38b32013-03-15 17:07:05 -05005036 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
5037 new_settings(hdev, cmd->sk);
5038 }
5039
5040 mgmt_pending_remove(cmd);
5041
5042unlock:
5043 hci_dev_unlock(hdev);
5044}
5045
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005046static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005047 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03005048{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005049 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005050 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05005051 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03005052 int err;
5053
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005054 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03005055
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005056 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03005057 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02005058 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5059 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03005060
Johan Hedberga7e80f22013-01-09 16:05:19 +02005061 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005062 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5063 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02005064
Antti Julkuf6422ec2011-06-22 13:11:56 +03005065 hci_dev_lock(hdev);
5066
Johan Hedberg333ae952015-03-17 13:48:47 +02005067 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005068 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5069 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05005070 goto unlock;
5071 }
5072
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005073 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05005074 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
5075 hdev);
5076 goto unlock;
5077 }
5078
Johan Hedberg406ef2a2015-03-10 20:14:27 +02005079 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07005080 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02005081 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
5082 hdev);
5083 new_settings(hdev, sk);
5084 goto unlock;
5085 }
5086
Johan Hedberg33e38b32013-03-15 17:07:05 -05005087 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
5088 data, len);
5089 if (!cmd) {
5090 err = -ENOMEM;
5091 goto unlock;
5092 }
5093
5094 hci_req_init(&req, hdev);
5095
Johan Hedberg406d7802013-03-15 17:07:09 -05005096 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005097
5098 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03005099 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005100 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5101 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005102 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03005103 }
5104
Johan Hedberg33e38b32013-03-15 17:07:05 -05005105unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03005106 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005107
Antti Julkuf6422ec2011-06-22 13:11:56 +03005108 return err;
5109}
5110
Marcel Holtmann1904a852015-01-11 13:50:44 -08005111static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03005112{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005113 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005114
5115 BT_DBG("status 0x%02x", status);
5116
5117 hci_dev_lock(hdev);
5118
Johan Hedberg333ae952015-03-17 13:48:47 +02005119 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005120 if (!cmd)
5121 goto unlock;
5122
5123 if (status) {
5124 u8 mgmt_err = mgmt_status(status);
5125
5126 /* We need to restore the flag if related HCI commands
5127 * failed.
5128 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005129 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005130
Johan Hedberga69e8372015-03-06 21:08:53 +02005131 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005132 } else {
5133 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
5134 new_settings(hdev, cmd->sk);
5135 }
5136
5137 mgmt_pending_remove(cmd);
5138
5139unlock:
5140 hci_dev_unlock(hdev);
5141}
5142
5143static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
5144{
5145 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005146 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005147 struct hci_request req;
5148 int err;
5149
5150 BT_DBG("request for %s", hdev->name);
5151
5152 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005153 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5154 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005155
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005156 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005157 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5158 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005159
5160 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005161 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5162 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005163
5164 hci_dev_lock(hdev);
5165
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005166 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005167 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5168 goto unlock;
5169 }
5170
5171 if (!hdev_is_powered(hdev)) {
5172 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005173 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5174 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5175 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5176 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5177 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005178 }
5179
Marcel Holtmannce05d602015-03-13 02:11:03 -07005180 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005181
5182 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5183 if (err < 0)
5184 goto unlock;
5185
5186 err = new_settings(hdev, sk);
5187 goto unlock;
5188 }
5189
5190 /* Reject disabling when powered on */
5191 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005192 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5193 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005194 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005195 } else {
5196 /* When configuring a dual-mode controller to operate
5197 * with LE only and using a static address, then switching
5198 * BR/EDR back on is not allowed.
5199 *
5200 * Dual-mode controllers shall operate with the public
5201 * address as its identity address for BR/EDR and LE. So
5202 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005203 *
5204 * The same restrictions applies when secure connections
5205 * has been enabled. For BR/EDR this is a controller feature
5206 * while for LE it is a host stack feature. This means that
5207 * switching BR/EDR back on when secure connections has been
5208 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005209 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005210 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005211 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005212 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005213 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5214 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005215 goto unlock;
5216 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005217 }
5218
Johan Hedberg333ae952015-03-17 13:48:47 +02005219 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005220 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5221 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005222 goto unlock;
5223 }
5224
5225 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5226 if (!cmd) {
5227 err = -ENOMEM;
5228 goto unlock;
5229 }
5230
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005231 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005232 * generates the correct flags.
5233 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005234 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005235
5236 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005237
Johan Hedberg432df052014-08-01 11:13:31 +03005238 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005239 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005240
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005241 /* Since only the advertising data flags will change, there
5242 * is no need to update the scan response data.
5243 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005244 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005245
Johan Hedberg0663ca22013-10-02 13:43:14 +03005246 err = hci_req_run(&req, set_bredr_complete);
5247 if (err < 0)
5248 mgmt_pending_remove(cmd);
5249
5250unlock:
5251 hci_dev_unlock(hdev);
5252 return err;
5253}
5254
Johan Hedberga1443f52015-01-23 15:42:46 +02005255static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5256{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005257 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005258 struct mgmt_mode *cp;
5259
5260 BT_DBG("%s status %u", hdev->name, status);
5261
5262 hci_dev_lock(hdev);
5263
Johan Hedberg333ae952015-03-17 13:48:47 +02005264 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005265 if (!cmd)
5266 goto unlock;
5267
5268 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005269 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5270 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005271 goto remove;
5272 }
5273
5274 cp = cmd->param;
5275
5276 switch (cp->val) {
5277 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005278 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5279 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005280 break;
5281 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005282 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005283 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005284 break;
5285 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005286 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5287 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005288 break;
5289 }
5290
5291 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5292 new_settings(hdev, cmd->sk);
5293
5294remove:
5295 mgmt_pending_remove(cmd);
5296unlock:
5297 hci_dev_unlock(hdev);
5298}
5299
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005300static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5301 void *data, u16 len)
5302{
5303 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005304 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005305 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005306 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005307 int err;
5308
5309 BT_DBG("request for %s", hdev->name);
5310
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005311 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005312 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005313 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5314 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005315
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005316 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005317 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005318 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005319 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5320 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005321
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005322 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005323 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005324 MGMT_STATUS_INVALID_PARAMS);
5325
5326 hci_dev_lock(hdev);
5327
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005328 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005329 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005330 bool changed;
5331
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005332 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005333 changed = !hci_dev_test_and_set_flag(hdev,
5334 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005335 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005336 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005337 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005338 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005339 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005340 changed = hci_dev_test_and_clear_flag(hdev,
5341 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005342 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005343 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005344
5345 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5346 if (err < 0)
5347 goto failed;
5348
5349 if (changed)
5350 err = new_settings(hdev, sk);
5351
5352 goto failed;
5353 }
5354
Johan Hedberg333ae952015-03-17 13:48:47 +02005355 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005356 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5357 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005358 goto failed;
5359 }
5360
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005361 val = !!cp->val;
5362
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005363 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5364 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005365 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5366 goto failed;
5367 }
5368
5369 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5370 if (!cmd) {
5371 err = -ENOMEM;
5372 goto failed;
5373 }
5374
Johan Hedberga1443f52015-01-23 15:42:46 +02005375 hci_req_init(&req, hdev);
5376 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5377 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005378 if (err < 0) {
5379 mgmt_pending_remove(cmd);
5380 goto failed;
5381 }
5382
5383failed:
5384 hci_dev_unlock(hdev);
5385 return err;
5386}
5387
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005388static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5389 void *data, u16 len)
5390{
5391 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005392 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005393 int err;
5394
5395 BT_DBG("request for %s", hdev->name);
5396
Johan Hedbergb97109792014-06-24 14:00:28 +03005397 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005398 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5399 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005400
5401 hci_dev_lock(hdev);
5402
5403 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005404 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005405 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005406 changed = hci_dev_test_and_clear_flag(hdev,
5407 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005408
Johan Hedbergb97109792014-06-24 14:00:28 +03005409 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005410 use_changed = !hci_dev_test_and_set_flag(hdev,
5411 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005412 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005413 use_changed = hci_dev_test_and_clear_flag(hdev,
5414 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005415
5416 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005417 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005418 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5419 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5420 sizeof(mode), &mode);
5421 }
5422
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005423 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5424 if (err < 0)
5425 goto unlock;
5426
5427 if (changed)
5428 err = new_settings(hdev, sk);
5429
5430unlock:
5431 hci_dev_unlock(hdev);
5432 return err;
5433}
5434
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005435static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5436 u16 len)
5437{
5438 struct mgmt_cp_set_privacy *cp = cp_data;
5439 bool changed;
5440 int err;
5441
5442 BT_DBG("request for %s", hdev->name);
5443
5444 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005445 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5446 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005447
5448 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005449 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5450 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005451
5452 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005453 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5454 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005455
5456 hci_dev_lock(hdev);
5457
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005458 /* If user space supports this command it is also expected to
5459 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5460 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005461 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005462
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005463 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005464 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005465 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005466 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005467 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005468 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005469 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005470 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005471 }
5472
5473 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5474 if (err < 0)
5475 goto unlock;
5476
5477 if (changed)
5478 err = new_settings(hdev, sk);
5479
5480unlock:
5481 hci_dev_unlock(hdev);
5482 return err;
5483}
5484
Johan Hedberg41edf162014-02-18 10:19:35 +02005485static bool irk_is_valid(struct mgmt_irk_info *irk)
5486{
5487 switch (irk->addr.type) {
5488 case BDADDR_LE_PUBLIC:
5489 return true;
5490
5491 case BDADDR_LE_RANDOM:
5492 /* Two most significant bits shall be set */
5493 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5494 return false;
5495 return true;
5496 }
5497
5498 return false;
5499}
5500
5501static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5502 u16 len)
5503{
5504 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005505 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5506 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005507 u16 irk_count, expected_len;
5508 int i, err;
5509
5510 BT_DBG("request for %s", hdev->name);
5511
5512 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005513 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5514 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005515
5516 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005517 if (irk_count > max_irk_count) {
5518 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005519 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5520 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005521 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005522
5523 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5524 if (expected_len != len) {
5525 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005526 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005527 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5528 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005529 }
5530
5531 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5532
5533 for (i = 0; i < irk_count; i++) {
5534 struct mgmt_irk_info *key = &cp->irks[i];
5535
5536 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005537 return mgmt_cmd_status(sk, hdev->id,
5538 MGMT_OP_LOAD_IRKS,
5539 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005540 }
5541
5542 hci_dev_lock(hdev);
5543
5544 hci_smp_irks_clear(hdev);
5545
5546 for (i = 0; i < irk_count; i++) {
5547 struct mgmt_irk_info *irk = &cp->irks[i];
5548 u8 addr_type;
5549
5550 if (irk->addr.type == BDADDR_LE_PUBLIC)
5551 addr_type = ADDR_LE_DEV_PUBLIC;
5552 else
5553 addr_type = ADDR_LE_DEV_RANDOM;
5554
5555 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5556 BDADDR_ANY);
5557 }
5558
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005559 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005560
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005561 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005562
5563 hci_dev_unlock(hdev);
5564
5565 return err;
5566}
5567
Johan Hedberg3f706b72013-01-20 14:27:16 +02005568static bool ltk_is_valid(struct mgmt_ltk_info *key)
5569{
5570 if (key->master != 0x00 && key->master != 0x01)
5571 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005572
5573 switch (key->addr.type) {
5574 case BDADDR_LE_PUBLIC:
5575 return true;
5576
5577 case BDADDR_LE_RANDOM:
5578 /* Two most significant bits shall be set */
5579 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5580 return false;
5581 return true;
5582 }
5583
5584 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005585}
5586
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005587static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005588 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005589{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005590 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005591 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5592 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005593 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005594 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005595
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005596 BT_DBG("request for %s", hdev->name);
5597
5598 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005599 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5600 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005601
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005602 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005603 if (key_count > max_key_count) {
5604 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005605 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5606 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005607 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005608
5609 expected_len = sizeof(*cp) + key_count *
5610 sizeof(struct mgmt_ltk_info);
5611 if (expected_len != len) {
5612 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005613 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005614 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5615 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005616 }
5617
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005618 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005619
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005620 for (i = 0; i < key_count; i++) {
5621 struct mgmt_ltk_info *key = &cp->keys[i];
5622
Johan Hedberg3f706b72013-01-20 14:27:16 +02005623 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005624 return mgmt_cmd_status(sk, hdev->id,
5625 MGMT_OP_LOAD_LONG_TERM_KEYS,
5626 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005627 }
5628
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005629 hci_dev_lock(hdev);
5630
5631 hci_smp_ltks_clear(hdev);
5632
5633 for (i = 0; i < key_count; i++) {
5634 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005635 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005636
5637 if (key->addr.type == BDADDR_LE_PUBLIC)
5638 addr_type = ADDR_LE_DEV_PUBLIC;
5639 else
5640 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005641
Johan Hedberg61b43352014-05-29 19:36:53 +03005642 switch (key->type) {
5643 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005644 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005645 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005646 break;
5647 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005648 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005649 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005650 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005651 case MGMT_LTK_P256_UNAUTH:
5652 authenticated = 0x00;
5653 type = SMP_LTK_P256;
5654 break;
5655 case MGMT_LTK_P256_AUTH:
5656 authenticated = 0x01;
5657 type = SMP_LTK_P256;
5658 break;
5659 case MGMT_LTK_P256_DEBUG:
5660 authenticated = 0x00;
5661 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005662 default:
5663 continue;
5664 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005665
Johan Hedberg35d70272014-02-19 14:57:47 +02005666 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005667 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005668 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005669 }
5670
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005671 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005672 NULL, 0);
5673
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005674 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005675
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005676 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005677}
5678
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005679static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005680{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005681 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005682 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005683 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005684
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005685 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005686
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005687 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005688 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005689 rp.tx_power = conn->tx_power;
5690 rp.max_tx_power = conn->max_tx_power;
5691 } else {
5692 rp.rssi = HCI_RSSI_INVALID;
5693 rp.tx_power = HCI_TX_POWER_INVALID;
5694 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005695 }
5696
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005697 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5698 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005699
5700 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005701 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005702
5703 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005704}
5705
Marcel Holtmann1904a852015-01-11 13:50:44 -08005706static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5707 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005708{
5709 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005710 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005711 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005712 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005713 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005714
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005715 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005716
5717 hci_dev_lock(hdev);
5718
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005719 /* Commands sent in request are either Read RSSI or Read Transmit Power
5720 * Level so we check which one was last sent to retrieve connection
5721 * handle. Both commands have handle as first parameter so it's safe to
5722 * cast data on the same command struct.
5723 *
5724 * First command sent is always Read RSSI and we fail only if it fails.
5725 * In other case we simply override error to indicate success as we
5726 * already remembered if TX power value is actually valid.
5727 */
5728 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5729 if (!cp) {
5730 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005731 status = MGMT_STATUS_SUCCESS;
5732 } else {
5733 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005734 }
5735
5736 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005737 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005738 goto unlock;
5739 }
5740
5741 handle = __le16_to_cpu(cp->handle);
5742 conn = hci_conn_hash_lookup_handle(hdev, handle);
5743 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005744 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005745 goto unlock;
5746 }
5747
Johan Hedberg333ae952015-03-17 13:48:47 +02005748 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005749 if (!cmd)
5750 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005751
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005752 cmd->cmd_complete(cmd, status);
5753 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005754
5755unlock:
5756 hci_dev_unlock(hdev);
5757}
5758
5759static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5760 u16 len)
5761{
5762 struct mgmt_cp_get_conn_info *cp = data;
5763 struct mgmt_rp_get_conn_info rp;
5764 struct hci_conn *conn;
5765 unsigned long conn_info_age;
5766 int err = 0;
5767
5768 BT_DBG("%s", hdev->name);
5769
5770 memset(&rp, 0, sizeof(rp));
5771 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5772 rp.addr.type = cp->addr.type;
5773
5774 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005775 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5776 MGMT_STATUS_INVALID_PARAMS,
5777 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005778
5779 hci_dev_lock(hdev);
5780
5781 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005782 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5783 MGMT_STATUS_NOT_POWERED, &rp,
5784 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005785 goto unlock;
5786 }
5787
5788 if (cp->addr.type == BDADDR_BREDR)
5789 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5790 &cp->addr.bdaddr);
5791 else
5792 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5793
5794 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005795 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5796 MGMT_STATUS_NOT_CONNECTED, &rp,
5797 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005798 goto unlock;
5799 }
5800
Johan Hedberg333ae952015-03-17 13:48:47 +02005801 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005802 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5803 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005804 goto unlock;
5805 }
5806
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005807 /* To avoid client trying to guess when to poll again for information we
5808 * calculate conn info age as random value between min/max set in hdev.
5809 */
5810 conn_info_age = hdev->conn_info_min_age +
5811 prandom_u32_max(hdev->conn_info_max_age -
5812 hdev->conn_info_min_age);
5813
5814 /* Query controller to refresh cached values if they are too old or were
5815 * never read.
5816 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005817 if (time_after(jiffies, conn->conn_info_timestamp +
5818 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005819 !conn->conn_info_timestamp) {
5820 struct hci_request req;
5821 struct hci_cp_read_tx_power req_txp_cp;
5822 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005823 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005824
5825 hci_req_init(&req, hdev);
5826 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5827 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5828 &req_rssi_cp);
5829
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005830 /* For LE links TX power does not change thus we don't need to
5831 * query for it once value is known.
5832 */
5833 if (!bdaddr_type_is_le(cp->addr.type) ||
5834 conn->tx_power == HCI_TX_POWER_INVALID) {
5835 req_txp_cp.handle = cpu_to_le16(conn->handle);
5836 req_txp_cp.type = 0x00;
5837 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5838 sizeof(req_txp_cp), &req_txp_cp);
5839 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005840
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005841 /* Max TX power needs to be read only once per connection */
5842 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5843 req_txp_cp.handle = cpu_to_le16(conn->handle);
5844 req_txp_cp.type = 0x01;
5845 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5846 sizeof(req_txp_cp), &req_txp_cp);
5847 }
5848
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005849 err = hci_req_run(&req, conn_info_refresh_complete);
5850 if (err < 0)
5851 goto unlock;
5852
5853 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5854 data, len);
5855 if (!cmd) {
5856 err = -ENOMEM;
5857 goto unlock;
5858 }
5859
5860 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005861 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005862 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005863
5864 conn->conn_info_timestamp = jiffies;
5865 } else {
5866 /* Cache is valid, just reply with values cached in hci_conn */
5867 rp.rssi = conn->rssi;
5868 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005869 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005870
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005871 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5872 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005873 }
5874
5875unlock:
5876 hci_dev_unlock(hdev);
5877 return err;
5878}
5879
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005880static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005881{
5882 struct hci_conn *conn = cmd->user_data;
5883 struct mgmt_rp_get_clock_info rp;
5884 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005885 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005886
5887 memset(&rp, 0, sizeof(rp));
5888 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5889
5890 if (status)
5891 goto complete;
5892
5893 hdev = hci_dev_get(cmd->index);
5894 if (hdev) {
5895 rp.local_clock = cpu_to_le32(hdev->clock);
5896 hci_dev_put(hdev);
5897 }
5898
5899 if (conn) {
5900 rp.piconet_clock = cpu_to_le32(conn->clock);
5901 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5902 }
5903
5904complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005905 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5906 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005907
5908 if (conn) {
5909 hci_conn_drop(conn);
5910 hci_conn_put(conn);
5911 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005912
5913 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005914}
5915
Marcel Holtmann1904a852015-01-11 13:50:44 -08005916static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005917{
Johan Hedberg95868422014-06-28 17:54:07 +03005918 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005919 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005920 struct hci_conn *conn;
5921
5922 BT_DBG("%s status %u", hdev->name, status);
5923
5924 hci_dev_lock(hdev);
5925
5926 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5927 if (!hci_cp)
5928 goto unlock;
5929
5930 if (hci_cp->which) {
5931 u16 handle = __le16_to_cpu(hci_cp->handle);
5932 conn = hci_conn_hash_lookup_handle(hdev, handle);
5933 } else {
5934 conn = NULL;
5935 }
5936
Johan Hedberg333ae952015-03-17 13:48:47 +02005937 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005938 if (!cmd)
5939 goto unlock;
5940
Johan Hedberg69487372014-12-05 13:36:07 +02005941 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005942 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005943
5944unlock:
5945 hci_dev_unlock(hdev);
5946}
5947
5948static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5949 u16 len)
5950{
5951 struct mgmt_cp_get_clock_info *cp = data;
5952 struct mgmt_rp_get_clock_info rp;
5953 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005954 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005955 struct hci_request req;
5956 struct hci_conn *conn;
5957 int err;
5958
5959 BT_DBG("%s", hdev->name);
5960
5961 memset(&rp, 0, sizeof(rp));
5962 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5963 rp.addr.type = cp->addr.type;
5964
5965 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005966 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5967 MGMT_STATUS_INVALID_PARAMS,
5968 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005969
5970 hci_dev_lock(hdev);
5971
5972 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005973 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5974 MGMT_STATUS_NOT_POWERED, &rp,
5975 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005976 goto unlock;
5977 }
5978
5979 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5980 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5981 &cp->addr.bdaddr);
5982 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005983 err = mgmt_cmd_complete(sk, hdev->id,
5984 MGMT_OP_GET_CLOCK_INFO,
5985 MGMT_STATUS_NOT_CONNECTED,
5986 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005987 goto unlock;
5988 }
5989 } else {
5990 conn = NULL;
5991 }
5992
5993 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5994 if (!cmd) {
5995 err = -ENOMEM;
5996 goto unlock;
5997 }
5998
Johan Hedberg69487372014-12-05 13:36:07 +02005999 cmd->cmd_complete = clock_info_cmd_complete;
6000
Johan Hedberg95868422014-06-28 17:54:07 +03006001 hci_req_init(&req, hdev);
6002
6003 memset(&hci_cp, 0, sizeof(hci_cp));
6004 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
6005
6006 if (conn) {
6007 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03006008 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03006009
6010 hci_cp.handle = cpu_to_le16(conn->handle);
6011 hci_cp.which = 0x01; /* Piconet clock */
6012 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
6013 }
6014
6015 err = hci_req_run(&req, get_clock_info_complete);
6016 if (err < 0)
6017 mgmt_pending_remove(cmd);
6018
6019unlock:
6020 hci_dev_unlock(hdev);
6021 return err;
6022}
6023
Johan Hedberg5a154e62014-12-19 22:26:02 +02006024static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
6025{
6026 struct hci_conn *conn;
6027
6028 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
6029 if (!conn)
6030 return false;
6031
6032 if (conn->dst_type != type)
6033 return false;
6034
6035 if (conn->state != BT_CONNECTED)
6036 return false;
6037
6038 return true;
6039}
6040
6041/* This function requires the caller holds hdev->lock */
6042static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
6043 u8 addr_type, u8 auto_connect)
6044{
6045 struct hci_dev *hdev = req->hdev;
6046 struct hci_conn_params *params;
6047
6048 params = hci_conn_params_add(hdev, addr, addr_type);
6049 if (!params)
6050 return -EIO;
6051
6052 if (params->auto_connect == auto_connect)
6053 return 0;
6054
6055 list_del_init(&params->action);
6056
6057 switch (auto_connect) {
6058 case HCI_AUTO_CONN_DISABLED:
6059 case HCI_AUTO_CONN_LINK_LOSS:
6060 __hci_update_background_scan(req);
6061 break;
6062 case HCI_AUTO_CONN_REPORT:
6063 list_add(&params->action, &hdev->pend_le_reports);
6064 __hci_update_background_scan(req);
6065 break;
6066 case HCI_AUTO_CONN_DIRECT:
6067 case HCI_AUTO_CONN_ALWAYS:
6068 if (!is_connected(hdev, addr, addr_type)) {
6069 list_add(&params->action, &hdev->pend_le_conns);
6070 __hci_update_background_scan(req);
6071 }
6072 break;
6073 }
6074
6075 params->auto_connect = auto_connect;
6076
6077 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
6078 auto_connect);
6079
6080 return 0;
6081}
6082
Marcel Holtmann8afef092014-06-29 22:28:34 +02006083static void device_added(struct sock *sk, struct hci_dev *hdev,
6084 bdaddr_t *bdaddr, u8 type, u8 action)
6085{
6086 struct mgmt_ev_device_added ev;
6087
6088 bacpy(&ev.addr.bdaddr, bdaddr);
6089 ev.addr.type = type;
6090 ev.action = action;
6091
6092 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
6093}
6094
Marcel Holtmann1904a852015-01-11 13:50:44 -08006095static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02006096{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006097 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006098
6099 BT_DBG("status 0x%02x", status);
6100
6101 hci_dev_lock(hdev);
6102
Johan Hedberg333ae952015-03-17 13:48:47 +02006103 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006104 if (!cmd)
6105 goto unlock;
6106
6107 cmd->cmd_complete(cmd, mgmt_status(status));
6108 mgmt_pending_remove(cmd);
6109
6110unlock:
6111 hci_dev_unlock(hdev);
6112}
6113
Marcel Holtmann2faade52014-06-29 19:44:03 +02006114static int add_device(struct sock *sk, struct hci_dev *hdev,
6115 void *data, u16 len)
6116{
6117 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006118 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006119 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006120 u8 auto_conn, addr_type;
6121 int err;
6122
6123 BT_DBG("%s", hdev->name);
6124
Johan Hedberg66593582014-07-09 12:59:14 +03006125 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02006126 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006127 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6128 MGMT_STATUS_INVALID_PARAMS,
6129 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006130
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006131 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006132 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6133 MGMT_STATUS_INVALID_PARAMS,
6134 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006135
Johan Hedberg5a154e62014-12-19 22:26:02 +02006136 hci_req_init(&req, hdev);
6137
Marcel Holtmann2faade52014-06-29 19:44:03 +02006138 hci_dev_lock(hdev);
6139
Johan Hedberg5a154e62014-12-19 22:26:02 +02006140 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
6141 if (!cmd) {
6142 err = -ENOMEM;
6143 goto unlock;
6144 }
6145
6146 cmd->cmd_complete = addr_cmd_complete;
6147
Johan Hedberg66593582014-07-09 12:59:14 +03006148 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006149 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03006150 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006151 err = cmd->cmd_complete(cmd,
6152 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006153 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006154 goto unlock;
6155 }
6156
6157 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
6158 cp->addr.type);
6159 if (err)
6160 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03006161
Johan Hedberg5a154e62014-12-19 22:26:02 +02006162 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006163
Johan Hedberg66593582014-07-09 12:59:14 +03006164 goto added;
6165 }
6166
Marcel Holtmann2faade52014-06-29 19:44:03 +02006167 if (cp->addr.type == BDADDR_LE_PUBLIC)
6168 addr_type = ADDR_LE_DEV_PUBLIC;
6169 else
6170 addr_type = ADDR_LE_DEV_RANDOM;
6171
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006172 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006173 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006174 else if (cp->action == 0x01)
6175 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006176 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006177 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006178
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006179 /* If the connection parameters don't exist for this device,
6180 * they will be created and configured with defaults.
6181 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006182 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006183 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006184 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006185 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006186 goto unlock;
6187 }
6188
Johan Hedberg66593582014-07-09 12:59:14 +03006189added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006190 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6191
Johan Hedberg5a154e62014-12-19 22:26:02 +02006192 err = hci_req_run(&req, add_device_complete);
6193 if (err < 0) {
6194 /* ENODATA means no HCI commands were needed (e.g. if
6195 * the adapter is powered off).
6196 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006197 if (err == -ENODATA)
6198 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006199 mgmt_pending_remove(cmd);
6200 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006201
6202unlock:
6203 hci_dev_unlock(hdev);
6204 return err;
6205}
6206
Marcel Holtmann8afef092014-06-29 22:28:34 +02006207static void device_removed(struct sock *sk, struct hci_dev *hdev,
6208 bdaddr_t *bdaddr, u8 type)
6209{
6210 struct mgmt_ev_device_removed ev;
6211
6212 bacpy(&ev.addr.bdaddr, bdaddr);
6213 ev.addr.type = type;
6214
6215 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6216}
6217
Marcel Holtmann1904a852015-01-11 13:50:44 -08006218static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006219{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006220 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006221
6222 BT_DBG("status 0x%02x", status);
6223
6224 hci_dev_lock(hdev);
6225
Johan Hedberg333ae952015-03-17 13:48:47 +02006226 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006227 if (!cmd)
6228 goto unlock;
6229
6230 cmd->cmd_complete(cmd, mgmt_status(status));
6231 mgmt_pending_remove(cmd);
6232
6233unlock:
6234 hci_dev_unlock(hdev);
6235}
6236
Marcel Holtmann2faade52014-06-29 19:44:03 +02006237static int remove_device(struct sock *sk, struct hci_dev *hdev,
6238 void *data, u16 len)
6239{
6240 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006241 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006242 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006243 int err;
6244
6245 BT_DBG("%s", hdev->name);
6246
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006247 hci_req_init(&req, hdev);
6248
Marcel Holtmann2faade52014-06-29 19:44:03 +02006249 hci_dev_lock(hdev);
6250
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006251 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6252 if (!cmd) {
6253 err = -ENOMEM;
6254 goto unlock;
6255 }
6256
6257 cmd->cmd_complete = addr_cmd_complete;
6258
Marcel Holtmann2faade52014-06-29 19:44:03 +02006259 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006260 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006261 u8 addr_type;
6262
Johan Hedberg66593582014-07-09 12:59:14 +03006263 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006264 err = cmd->cmd_complete(cmd,
6265 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006266 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006267 goto unlock;
6268 }
6269
Johan Hedberg66593582014-07-09 12:59:14 +03006270 if (cp->addr.type == BDADDR_BREDR) {
6271 err = hci_bdaddr_list_del(&hdev->whitelist,
6272 &cp->addr.bdaddr,
6273 cp->addr.type);
6274 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006275 err = cmd->cmd_complete(cmd,
6276 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006277 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006278 goto unlock;
6279 }
6280
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006281 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006282
Johan Hedberg66593582014-07-09 12:59:14 +03006283 device_removed(sk, hdev, &cp->addr.bdaddr,
6284 cp->addr.type);
6285 goto complete;
6286 }
6287
Marcel Holtmann2faade52014-06-29 19:44:03 +02006288 if (cp->addr.type == BDADDR_LE_PUBLIC)
6289 addr_type = ADDR_LE_DEV_PUBLIC;
6290 else
6291 addr_type = ADDR_LE_DEV_RANDOM;
6292
Johan Hedbergc71593d2014-07-02 17:37:28 +03006293 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6294 addr_type);
6295 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006296 err = cmd->cmd_complete(cmd,
6297 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006298 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006299 goto unlock;
6300 }
6301
6302 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006303 err = cmd->cmd_complete(cmd,
6304 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006305 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006306 goto unlock;
6307 }
6308
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006309 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006310 list_del(&params->list);
6311 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006312 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006313
6314 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006315 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006316 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006317 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006318
Marcel Holtmann2faade52014-06-29 19:44:03 +02006319 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006320 err = cmd->cmd_complete(cmd,
6321 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006322 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006323 goto unlock;
6324 }
6325
Johan Hedberg66593582014-07-09 12:59:14 +03006326 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6327 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6328 list_del(&b->list);
6329 kfree(b);
6330 }
6331
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006332 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006333
Johan Hedberg19de0822014-07-06 13:06:51 +03006334 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6335 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6336 continue;
6337 device_removed(sk, hdev, &p->addr, p->addr_type);
6338 list_del(&p->action);
6339 list_del(&p->list);
6340 kfree(p);
6341 }
6342
6343 BT_DBG("All LE connection parameters were removed");
6344
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006345 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006346 }
6347
Johan Hedberg66593582014-07-09 12:59:14 +03006348complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006349 err = hci_req_run(&req, remove_device_complete);
6350 if (err < 0) {
6351 /* ENODATA means no HCI commands were needed (e.g. if
6352 * the adapter is powered off).
6353 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006354 if (err == -ENODATA)
6355 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006356 mgmt_pending_remove(cmd);
6357 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006358
6359unlock:
6360 hci_dev_unlock(hdev);
6361 return err;
6362}
6363
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006364static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6365 u16 len)
6366{
6367 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006368 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6369 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006370 u16 param_count, expected_len;
6371 int i;
6372
6373 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006374 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6375 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006376
6377 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006378 if (param_count > max_param_count) {
6379 BT_ERR("load_conn_param: too big param_count value %u",
6380 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006381 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6382 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006383 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006384
6385 expected_len = sizeof(*cp) + param_count *
6386 sizeof(struct mgmt_conn_param);
6387 if (expected_len != len) {
6388 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6389 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006390 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6391 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006392 }
6393
6394 BT_DBG("%s param_count %u", hdev->name, param_count);
6395
6396 hci_dev_lock(hdev);
6397
6398 hci_conn_params_clear_disabled(hdev);
6399
6400 for (i = 0; i < param_count; i++) {
6401 struct mgmt_conn_param *param = &cp->params[i];
6402 struct hci_conn_params *hci_param;
6403 u16 min, max, latency, timeout;
6404 u8 addr_type;
6405
6406 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6407 param->addr.type);
6408
6409 if (param->addr.type == BDADDR_LE_PUBLIC) {
6410 addr_type = ADDR_LE_DEV_PUBLIC;
6411 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6412 addr_type = ADDR_LE_DEV_RANDOM;
6413 } else {
6414 BT_ERR("Ignoring invalid connection parameters");
6415 continue;
6416 }
6417
6418 min = le16_to_cpu(param->min_interval);
6419 max = le16_to_cpu(param->max_interval);
6420 latency = le16_to_cpu(param->latency);
6421 timeout = le16_to_cpu(param->timeout);
6422
6423 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6424 min, max, latency, timeout);
6425
6426 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6427 BT_ERR("Ignoring invalid connection parameters");
6428 continue;
6429 }
6430
6431 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6432 addr_type);
6433 if (!hci_param) {
6434 BT_ERR("Failed to add connection parameters");
6435 continue;
6436 }
6437
6438 hci_param->conn_min_interval = min;
6439 hci_param->conn_max_interval = max;
6440 hci_param->conn_latency = latency;
6441 hci_param->supervision_timeout = timeout;
6442 }
6443
6444 hci_dev_unlock(hdev);
6445
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006446 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6447 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006448}
6449
Marcel Holtmanndbece372014-07-04 18:11:55 +02006450static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6451 void *data, u16 len)
6452{
6453 struct mgmt_cp_set_external_config *cp = data;
6454 bool changed;
6455 int err;
6456
6457 BT_DBG("%s", hdev->name);
6458
6459 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006460 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6461 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006462
6463 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006464 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6465 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006466
6467 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006468 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6469 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006470
6471 hci_dev_lock(hdev);
6472
6473 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006474 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006475 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006476 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006477
6478 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6479 if (err < 0)
6480 goto unlock;
6481
6482 if (!changed)
6483 goto unlock;
6484
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006485 err = new_options(hdev, sk);
6486
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006487 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006488 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006489
Marcel Holtmann516018a2015-03-13 02:11:04 -07006490 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006491 hci_dev_set_flag(hdev, HCI_CONFIG);
6492 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006493
6494 queue_work(hdev->req_workqueue, &hdev->power_on);
6495 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006496 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006497 mgmt_index_added(hdev);
6498 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006499 }
6500
6501unlock:
6502 hci_dev_unlock(hdev);
6503 return err;
6504}
6505
Marcel Holtmann9713c172014-07-06 12:11:15 +02006506static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6507 void *data, u16 len)
6508{
6509 struct mgmt_cp_set_public_address *cp = data;
6510 bool changed;
6511 int err;
6512
6513 BT_DBG("%s", hdev->name);
6514
6515 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006516 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6517 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006518
6519 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006520 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6521 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006522
6523 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006524 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6525 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006526
6527 hci_dev_lock(hdev);
6528
6529 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6530 bacpy(&hdev->public_addr, &cp->bdaddr);
6531
6532 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6533 if (err < 0)
6534 goto unlock;
6535
6536 if (!changed)
6537 goto unlock;
6538
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006539 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006540 err = new_options(hdev, sk);
6541
6542 if (is_configured(hdev)) {
6543 mgmt_index_removed(hdev);
6544
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006545 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006546
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006547 hci_dev_set_flag(hdev, HCI_CONFIG);
6548 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006549
6550 queue_work(hdev->req_workqueue, &hdev->power_on);
6551 }
6552
6553unlock:
6554 hci_dev_unlock(hdev);
6555 return err;
6556}
6557
Marcel Holtmannbea41602015-03-14 22:43:17 -07006558static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6559 u8 data_len)
6560{
6561 eir[eir_len++] = sizeof(type) + data_len;
6562 eir[eir_len++] = type;
6563 memcpy(&eir[eir_len], data, data_len);
6564 eir_len += data_len;
6565
6566 return eir_len;
6567}
6568
Johan Hedberg40f66c02015-04-07 21:52:22 +03006569static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
6570 u16 opcode, struct sk_buff *skb)
6571{
6572 const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
6573 struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
6574 u8 *h192, *r192, *h256, *r256;
6575 struct mgmt_pending_cmd *cmd;
6576 u16 eir_len;
6577 int err;
6578
6579 BT_DBG("%s status %u", hdev->name, status);
6580
6581 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
6582 if (!cmd)
6583 return;
6584
6585 mgmt_cp = cmd->param;
6586
6587 if (status) {
6588 status = mgmt_status(status);
6589 eir_len = 0;
6590
6591 h192 = NULL;
6592 r192 = NULL;
6593 h256 = NULL;
6594 r256 = NULL;
6595 } else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
6596 struct hci_rp_read_local_oob_data *rp;
6597
6598 if (skb->len != sizeof(*rp)) {
6599 status = MGMT_STATUS_FAILED;
6600 eir_len = 0;
6601 } else {
6602 status = MGMT_STATUS_SUCCESS;
6603 rp = (void *)skb->data;
6604
6605 eir_len = 5 + 18 + 18;
6606 h192 = rp->hash;
6607 r192 = rp->rand;
6608 h256 = NULL;
6609 r256 = NULL;
6610 }
6611 } else {
6612 struct hci_rp_read_local_oob_ext_data *rp;
6613
6614 if (skb->len != sizeof(*rp)) {
6615 status = MGMT_STATUS_FAILED;
6616 eir_len = 0;
6617 } else {
6618 status = MGMT_STATUS_SUCCESS;
6619 rp = (void *)skb->data;
6620
6621 if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
6622 eir_len = 5 + 18 + 18;
6623 h192 = NULL;
6624 r192 = NULL;
6625 } else {
6626 eir_len = 5 + 18 + 18 + 18 + 18;
6627 h192 = rp->hash192;
6628 r192 = rp->rand192;
6629 }
6630
6631 h256 = rp->hash256;
6632 r256 = rp->rand256;
6633 }
6634 }
6635
6636 mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
6637 if (!mgmt_rp)
6638 goto done;
6639
6640 if (status)
6641 goto send_rsp;
6642
6643 eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
6644 hdev->dev_class, 3);
6645
6646 if (h192 && r192) {
6647 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6648 EIR_SSP_HASH_C192, h192, 16);
6649 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6650 EIR_SSP_RAND_R192, r192, 16);
6651 }
6652
6653 if (h256 && r256) {
6654 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6655 EIR_SSP_HASH_C256, h256, 16);
6656 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6657 EIR_SSP_RAND_R256, r256, 16);
6658 }
6659
6660send_rsp:
6661 mgmt_rp->type = mgmt_cp->type;
6662 mgmt_rp->eir_len = cpu_to_le16(eir_len);
6663
6664 err = mgmt_cmd_complete(cmd->sk, hdev->id,
6665 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
6666 mgmt_rp, sizeof(*mgmt_rp) + eir_len);
6667 if (err < 0 || status)
6668 goto done;
6669
6670 hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
6671
6672 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6673 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
6674 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
6675done:
6676 kfree(mgmt_rp);
6677 mgmt_pending_remove(cmd);
6678}
6679
6680static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
6681 struct mgmt_cp_read_local_oob_ext_data *cp)
6682{
6683 struct mgmt_pending_cmd *cmd;
6684 struct hci_request req;
6685 int err;
6686
6687 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
6688 cp, sizeof(*cp));
6689 if (!cmd)
6690 return -ENOMEM;
6691
6692 hci_req_init(&req, hdev);
6693
6694 if (bredr_sc_enabled(hdev))
6695 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
6696 else
6697 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
6698
6699 err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
6700 if (err < 0) {
6701 mgmt_pending_remove(cmd);
6702 return err;
6703 }
6704
6705 return 0;
6706}
6707
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006708static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6709 void *data, u16 data_len)
6710{
6711 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6712 struct mgmt_rp_read_local_oob_ext_data *rp;
6713 size_t rp_len;
6714 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006715 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006716 int err;
6717
6718 BT_DBG("%s", hdev->name);
6719
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006720 if (hdev_is_powered(hdev)) {
6721 switch (cp->type) {
6722 case BIT(BDADDR_BREDR):
6723 status = mgmt_bredr_support(hdev);
6724 if (status)
6725 eir_len = 0;
6726 else
6727 eir_len = 5;
6728 break;
6729 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6730 status = mgmt_le_support(hdev);
6731 if (status)
6732 eir_len = 0;
6733 else
6734 eir_len = 9 + 3 + 18 + 18 + 3;
6735 break;
6736 default:
6737 status = MGMT_STATUS_INVALID_PARAMS;
6738 eir_len = 0;
6739 break;
6740 }
6741 } else {
6742 status = MGMT_STATUS_NOT_POWERED;
6743 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006744 }
6745
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006746 rp_len = sizeof(*rp) + eir_len;
6747 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006748 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006749 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006750
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006751 if (status)
6752 goto complete;
6753
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006754 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006755
6756 eir_len = 0;
6757 switch (cp->type) {
6758 case BIT(BDADDR_BREDR):
Johan Hedberg40f66c02015-04-07 21:52:22 +03006759 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
6760 err = read_local_ssp_oob_req(hdev, sk, cp);
6761 hci_dev_unlock(hdev);
6762 if (!err)
6763 goto done;
6764
6765 status = MGMT_STATUS_FAILED;
6766 goto complete;
6767 } else {
6768 eir_len = eir_append_data(rp->eir, eir_len,
6769 EIR_CLASS_OF_DEV,
6770 hdev->dev_class, 3);
6771 }
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006772 break;
6773 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006774 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6775 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006776 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006777 status = MGMT_STATUS_FAILED;
6778 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006779 }
6780
Marcel Holtmanne2135682015-04-02 12:00:58 -07006781 /* This should return the active RPA, but since the RPA
6782 * is only programmed on demand, it is really hard to fill
6783 * this in at the moment. For now disallow retrieving
6784 * local out-of-band data when privacy is in use.
6785 *
6786 * Returning the identity address will not help here since
6787 * pairing happens before the identity resolving key is
6788 * known and thus the connection establishment happens
6789 * based on the RPA and not the identity address.
6790 */
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006791 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
Marcel Holtmanne2135682015-04-02 12:00:58 -07006792 hci_dev_unlock(hdev);
6793 status = MGMT_STATUS_REJECTED;
6794 goto complete;
6795 }
6796
6797 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6798 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6799 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6800 bacmp(&hdev->static_addr, BDADDR_ANY))) {
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006801 memcpy(addr, &hdev->static_addr, 6);
6802 addr[6] = 0x01;
6803 } else {
6804 memcpy(addr, &hdev->bdaddr, 6);
6805 addr[6] = 0x00;
6806 }
6807
6808 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6809 addr, sizeof(addr));
6810
6811 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6812 role = 0x02;
6813 else
6814 role = 0x01;
6815
6816 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6817 &role, sizeof(role));
6818
Marcel Holtmann5082a592015-03-16 12:39:00 -07006819 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6820 eir_len = eir_append_data(rp->eir, eir_len,
6821 EIR_LE_SC_CONFIRM,
6822 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006823
Marcel Holtmann5082a592015-03-16 12:39:00 -07006824 eir_len = eir_append_data(rp->eir, eir_len,
6825 EIR_LE_SC_RANDOM,
6826 rand, sizeof(rand));
6827 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006828
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006829 flags = get_adv_discov_flags(hdev);
6830
6831 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6832 flags |= LE_AD_NO_BREDR;
6833
6834 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6835 &flags, sizeof(flags));
6836 break;
6837 }
6838
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006839 hci_dev_unlock(hdev);
6840
Marcel Holtmann72000df2015-03-16 16:11:21 -07006841 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6842
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006843 status = MGMT_STATUS_SUCCESS;
6844
6845complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006846 rp->type = cp->type;
6847 rp->eir_len = cpu_to_le16(eir_len);
6848
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006849 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006850 status, rp, sizeof(*rp) + eir_len);
6851 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006852 goto done;
6853
6854 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6855 rp, sizeof(*rp) + eir_len,
6856 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006857
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006858done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006859 kfree(rp);
6860
6861 return err;
6862}
6863
Arman Uguray089fa8c2015-03-25 18:53:45 -07006864static u32 get_supported_adv_flags(struct hci_dev *hdev)
6865{
6866 u32 flags = 0;
6867
6868 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6869 flags |= MGMT_ADV_FLAG_DISCOV;
6870 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6871 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6872
6873 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6874 flags |= MGMT_ADV_FLAG_TX_POWER;
6875
6876 return flags;
6877}
6878
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006879static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6880 void *data, u16 data_len)
6881{
6882 struct mgmt_rp_read_adv_features *rp;
6883 size_t rp_len;
Florian Grandel286e0c82015-06-18 03:16:38 +02006884 int err, i;
Arman Uguray24b4f382015-03-23 15:57:12 -07006885 bool instance;
Florian Grandel286e0c82015-06-18 03:16:38 +02006886 struct adv_info *adv_instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006887 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006888
6889 BT_DBG("%s", hdev->name);
6890
Arman Uguray089fa8c2015-03-25 18:53:45 -07006891 if (!lmp_le_capable(hdev))
6892 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6893 MGMT_STATUS_REJECTED);
6894
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006895 hci_dev_lock(hdev);
6896
6897 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006898
Arman Uguray24b4f382015-03-23 15:57:12 -07006899 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6900 if (instance)
Florian Grandel286e0c82015-06-18 03:16:38 +02006901 rp_len += hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006902
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006903 rp = kmalloc(rp_len, GFP_ATOMIC);
6904 if (!rp) {
6905 hci_dev_unlock(hdev);
6906 return -ENOMEM;
6907 }
6908
Arman Uguray089fa8c2015-03-25 18:53:45 -07006909 supported_flags = get_supported_adv_flags(hdev);
6910
6911 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006912 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6913 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Florian Grandeld2609b32015-06-18 03:16:34 +02006914 rp->max_instances = HCI_MAX_ADV_INSTANCES;
Arman Uguray24b4f382015-03-23 15:57:12 -07006915
Arman Uguray24b4f382015-03-23 15:57:12 -07006916 if (instance) {
Florian Grandel286e0c82015-06-18 03:16:38 +02006917 i = 0;
6918 list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
6919 if (i >= hdev->adv_instance_cnt)
6920 break;
6921
6922 rp->instance[i] = adv_instance->instance;
6923 i++;
6924 }
6925 rp->num_instances = hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006926 } else {
6927 rp->num_instances = 0;
6928 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006929
6930 hci_dev_unlock(hdev);
6931
6932 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6933 MGMT_STATUS_SUCCESS, rp, rp_len);
6934
6935 kfree(rp);
6936
6937 return err;
6938}
6939
Arman Uguray4117ed72015-03-23 15:57:14 -07006940static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006941 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006942{
Arman Uguray4117ed72015-03-23 15:57:14 -07006943 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006944 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006945 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006946 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006947 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6948 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006949
Arman Uguray807ec772015-03-25 18:53:42 -07006950 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006951 flags_managed = true;
6952 max_len -= 3;
6953 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006954
Arman Uguray5507e352015-03-25 18:53:44 -07006955 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6956 tx_power_managed = true;
6957 max_len -= 3;
6958 }
6959
Arman Uguray4117ed72015-03-23 15:57:14 -07006960 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006961 return false;
6962
Arman Uguray4117ed72015-03-23 15:57:14 -07006963 /* Make sure that the data is correctly formatted. */
6964 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6965 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006966
Arman Ugurayb44133f2015-03-25 18:53:41 -07006967 if (flags_managed && data[i + 1] == EIR_FLAGS)
6968 return false;
6969
Arman Uguray5507e352015-03-25 18:53:44 -07006970 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6971 return false;
6972
Arman Uguray24b4f382015-03-23 15:57:12 -07006973 /* If the current field length would exceed the total data
6974 * length, then it's invalid.
6975 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006976 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006977 return false;
6978 }
6979
6980 return true;
6981}
6982
Arman Uguray24b4f382015-03-23 15:57:12 -07006983static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6984 u16 opcode)
6985{
6986 struct mgmt_pending_cmd *cmd;
6987 struct mgmt_rp_add_advertising rp;
6988
6989 BT_DBG("status %d", status);
6990
6991 hci_dev_lock(hdev);
6992
6993 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6994
6995 if (status) {
6996 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6997 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6998 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6999 }
7000
7001 if (!cmd)
7002 goto unlock;
7003
7004 rp.instance = 0x01;
7005
7006 if (status)
7007 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
7008 mgmt_status(status));
7009 else
7010 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
7011 mgmt_status(status), &rp, sizeof(rp));
7012
7013 mgmt_pending_remove(cmd);
7014
7015unlock:
7016 hci_dev_unlock(hdev);
7017}
7018
Florian Grandel5d900e42015-06-18 03:16:35 +02007019void mgmt_adv_timeout_expired(struct hci_dev *hdev)
Arman Uguray912098a2015-03-23 15:57:15 -07007020{
Florian Grandel5d900e42015-06-18 03:16:35 +02007021 hdev->adv_instance_timeout = 0;
Arman Uguray912098a2015-03-23 15:57:15 -07007022
7023 hci_dev_lock(hdev);
7024 clear_adv_instance(hdev);
7025 hci_dev_unlock(hdev);
7026}
7027
Arman Uguray24b4f382015-03-23 15:57:12 -07007028static int add_advertising(struct sock *sk, struct hci_dev *hdev,
7029 void *data, u16 data_len)
7030{
7031 struct mgmt_cp_add_advertising *cp = data;
7032 struct mgmt_rp_add_advertising rp;
7033 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07007034 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07007035 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07007036 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07007037 int err;
7038 struct mgmt_pending_cmd *cmd;
7039 struct hci_request req;
7040
7041 BT_DBG("%s", hdev->name);
7042
7043 status = mgmt_le_support(hdev);
7044 if (status)
7045 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7046 status);
7047
7048 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07007049 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07007050
Arman Uguray089fa8c2015-03-25 18:53:45 -07007051 /* The current implementation only supports adding one instance and only
7052 * a subset of the specified flags.
7053 */
7054 supported_flags = get_supported_adv_flags(hdev);
7055 if (cp->instance != 0x01 || (flags & ~supported_flags))
Arman Uguray24b4f382015-03-23 15:57:12 -07007056 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7057 MGMT_STATUS_INVALID_PARAMS);
7058
7059 hci_dev_lock(hdev);
7060
Arman Uguray912098a2015-03-23 15:57:15 -07007061 if (timeout && !hdev_is_powered(hdev)) {
7062 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7063 MGMT_STATUS_REJECTED);
7064 goto unlock;
7065 }
7066
Arman Uguray24b4f382015-03-23 15:57:12 -07007067 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07007068 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07007069 pending_find(MGMT_OP_SET_LE, hdev)) {
7070 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7071 MGMT_STATUS_BUSY);
7072 goto unlock;
7073 }
7074
Arman Ugurayb44133f2015-03-25 18:53:41 -07007075 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07007076 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07007077 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07007078 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7079 MGMT_STATUS_INVALID_PARAMS);
7080 goto unlock;
7081 }
7082
7083 hdev->adv_instance.flags = flags;
7084 hdev->adv_instance.adv_data_len = cp->adv_data_len;
7085 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
7086
7087 if (cp->adv_data_len)
7088 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
7089
7090 if (cp->scan_rsp_len)
7091 memcpy(hdev->adv_instance.scan_rsp_data,
7092 cp->data + cp->adv_data_len, cp->scan_rsp_len);
7093
Florian Grandel5d900e42015-06-18 03:16:35 +02007094 if (hdev->adv_instance_timeout)
7095 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07007096
Florian Grandel5d900e42015-06-18 03:16:35 +02007097 hdev->adv_instance_timeout = timeout;
Arman Uguray912098a2015-03-23 15:57:15 -07007098
7099 if (timeout)
7100 queue_delayed_work(hdev->workqueue,
Florian Grandel5d900e42015-06-18 03:16:35 +02007101 &hdev->adv_instance_expire,
Arman Uguray912098a2015-03-23 15:57:15 -07007102 msecs_to_jiffies(timeout * 1000));
7103
Arman Uguray24b4f382015-03-23 15:57:12 -07007104 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
7105 advertising_added(sk, hdev, 1);
7106
7107 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7108 * we have no HCI communication to make. Simply return.
7109 */
7110 if (!hdev_is_powered(hdev) ||
7111 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7112 rp.instance = 0x01;
7113 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7114 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7115 goto unlock;
7116 }
7117
7118 /* We're good to go, update advertising data, parameters, and start
7119 * advertising.
7120 */
7121 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
7122 data_len);
7123 if (!cmd) {
7124 err = -ENOMEM;
7125 goto unlock;
7126 }
7127
7128 hci_req_init(&req, hdev);
7129
7130 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07007131 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007132 enable_advertising(&req);
7133
7134 err = hci_req_run(&req, add_advertising_complete);
7135 if (err < 0)
7136 mgmt_pending_remove(cmd);
7137
7138unlock:
7139 hci_dev_unlock(hdev);
7140
7141 return err;
7142}
7143
Arman Ugurayda9293352015-03-23 15:57:13 -07007144static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
7145 u16 opcode)
7146{
7147 struct mgmt_pending_cmd *cmd;
7148 struct mgmt_rp_remove_advertising rp;
7149
7150 BT_DBG("status %d", status);
7151
7152 hci_dev_lock(hdev);
7153
7154 /* A failure status here only means that we failed to disable
7155 * advertising. Otherwise, the advertising instance has been removed,
7156 * so report success.
7157 */
7158 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
7159 if (!cmd)
7160 goto unlock;
7161
7162 rp.instance = 1;
7163
7164 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
7165 &rp, sizeof(rp));
7166 mgmt_pending_remove(cmd);
7167
7168unlock:
7169 hci_dev_unlock(hdev);
7170}
7171
7172static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
7173 void *data, u16 data_len)
7174{
7175 struct mgmt_cp_remove_advertising *cp = data;
7176 struct mgmt_rp_remove_advertising rp;
7177 int err;
7178 struct mgmt_pending_cmd *cmd;
7179 struct hci_request req;
7180
7181 BT_DBG("%s", hdev->name);
7182
7183 /* The current implementation only allows modifying instance no 1. A
7184 * value of 0 indicates that all instances should be cleared.
7185 */
7186 if (cp->instance > 1)
7187 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7188 MGMT_STATUS_INVALID_PARAMS);
7189
7190 hci_dev_lock(hdev);
7191
7192 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
7193 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
7194 pending_find(MGMT_OP_SET_LE, hdev)) {
7195 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7196 MGMT_STATUS_BUSY);
7197 goto unlock;
7198 }
7199
7200 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
7201 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7202 MGMT_STATUS_INVALID_PARAMS);
7203 goto unlock;
7204 }
7205
Florian Grandel5d900e42015-06-18 03:16:35 +02007206 if (hdev->adv_instance_timeout)
7207 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07007208
Arman Ugurayda9293352015-03-23 15:57:13 -07007209 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
7210
7211 advertising_removed(sk, hdev, 1);
7212
7213 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
7214
7215 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7216 * we have no HCI communication to make. Simply return.
7217 */
7218 if (!hdev_is_powered(hdev) ||
7219 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7220 rp.instance = 1;
7221 err = mgmt_cmd_complete(sk, hdev->id,
7222 MGMT_OP_REMOVE_ADVERTISING,
7223 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7224 goto unlock;
7225 }
7226
7227 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
7228 data_len);
7229 if (!cmd) {
7230 err = -ENOMEM;
7231 goto unlock;
7232 }
7233
7234 hci_req_init(&req, hdev);
7235 disable_advertising(&req);
7236
7237 err = hci_req_run(&req, remove_advertising_complete);
7238 if (err < 0)
7239 mgmt_pending_remove(cmd);
7240
7241unlock:
7242 hci_dev_unlock(hdev);
7243
7244 return err;
7245}
7246
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007247static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007248 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007249 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007250 HCI_MGMT_NO_HDEV |
7251 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007252 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007253 HCI_MGMT_NO_HDEV |
7254 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007255 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007256 HCI_MGMT_NO_HDEV |
7257 HCI_MGMT_UNTRUSTED },
7258 { read_controller_info, MGMT_READ_INFO_SIZE,
7259 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007260 { set_powered, MGMT_SETTING_SIZE },
7261 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7262 { set_connectable, MGMT_SETTING_SIZE },
7263 { set_fast_connectable, MGMT_SETTING_SIZE },
7264 { set_bondable, MGMT_SETTING_SIZE },
7265 { set_link_security, MGMT_SETTING_SIZE },
7266 { set_ssp, MGMT_SETTING_SIZE },
7267 { set_hs, MGMT_SETTING_SIZE },
7268 { set_le, MGMT_SETTING_SIZE },
7269 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7270 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7271 { add_uuid, MGMT_ADD_UUID_SIZE },
7272 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007273 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7274 HCI_MGMT_VAR_LEN },
7275 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7276 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007277 { disconnect, MGMT_DISCONNECT_SIZE },
7278 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7279 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7280 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7281 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7282 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7283 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7284 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7285 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7286 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7287 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7288 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007289 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7290 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7291 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007292 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7293 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7294 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7295 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7296 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7297 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7298 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7299 { set_advertising, MGMT_SETTING_SIZE },
7300 { set_bredr, MGMT_SETTING_SIZE },
7301 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7302 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7303 { set_secure_conn, MGMT_SETTING_SIZE },
7304 { set_debug_keys, MGMT_SETTING_SIZE },
7305 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007306 { load_irks, MGMT_LOAD_IRKS_SIZE,
7307 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007308 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7309 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7310 { add_device, MGMT_ADD_DEVICE_SIZE },
7311 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007312 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7313 HCI_MGMT_VAR_LEN },
7314 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007315 HCI_MGMT_NO_HDEV |
7316 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007317 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007318 HCI_MGMT_UNCONFIGURED |
7319 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007320 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7321 HCI_MGMT_UNCONFIGURED },
7322 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7323 HCI_MGMT_UNCONFIGURED },
7324 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7325 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007326 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007327 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007328 HCI_MGMT_NO_HDEV |
7329 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007330 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007331 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7332 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007333 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007334};
7335
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007336void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007337{
Marcel Holtmannced85542015-03-14 19:27:56 -07007338 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007339
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007340 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7341 return;
7342
Marcel Holtmannf9207332015-03-14 19:27:55 -07007343 switch (hdev->dev_type) {
7344 case HCI_BREDR:
7345 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7346 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7347 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007348 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007349 } else {
7350 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7351 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007352 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007353 }
7354 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007355 case HCI_AMP:
7356 ev.type = 0x02;
7357 break;
7358 default:
7359 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007360 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007361
7362 ev.bus = hdev->bus;
7363
7364 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7365 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007366}
7367
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007368void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007369{
Marcel Holtmannced85542015-03-14 19:27:56 -07007370 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007371 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007372
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007373 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7374 return;
7375
Marcel Holtmannf9207332015-03-14 19:27:55 -07007376 switch (hdev->dev_type) {
7377 case HCI_BREDR:
7378 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007379
Marcel Holtmannf9207332015-03-14 19:27:55 -07007380 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7381 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7382 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007383 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007384 } else {
7385 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7386 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007387 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007388 }
7389 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007390 case HCI_AMP:
7391 ev.type = 0x02;
7392 break;
7393 default:
7394 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007395 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007396
7397 ev.bus = hdev->bus;
7398
7399 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7400 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007401}
7402
Andre Guedes6046dc32014-02-26 20:21:51 -03007403/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007404static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007405{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007406 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007407 struct hci_conn_params *p;
7408
7409 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007410 /* Needed for AUTO_OFF case where might not "really"
7411 * have been powered off.
7412 */
7413 list_del_init(&p->action);
7414
7415 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007416 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007417 case HCI_AUTO_CONN_ALWAYS:
7418 list_add(&p->action, &hdev->pend_le_conns);
7419 break;
7420 case HCI_AUTO_CONN_REPORT:
7421 list_add(&p->action, &hdev->pend_le_reports);
7422 break;
7423 default:
7424 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007425 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007426 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007427
Johan Hedberg2cf22212014-12-19 22:26:00 +02007428 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007429}
7430
Marcel Holtmann1904a852015-01-11 13:50:44 -08007431static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007432{
7433 struct cmd_lookup match = { NULL, hdev };
7434
7435 BT_DBG("status 0x%02x", status);
7436
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007437 if (!status) {
7438 /* Register the available SMP channels (BR/EDR and LE) only
7439 * when successfully powering on the controller. This late
7440 * registration is required so that LE SMP can clearly
7441 * decide if the public address or static address is used.
7442 */
7443 smp_register(hdev);
7444 }
7445
Johan Hedberg229ab392013-03-15 17:06:53 -05007446 hci_dev_lock(hdev);
7447
7448 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7449
7450 new_settings(hdev, match.sk);
7451
7452 hci_dev_unlock(hdev);
7453
7454 if (match.sk)
7455 sock_put(match.sk);
7456}
7457
Johan Hedberg70da6242013-03-15 17:06:51 -05007458static int powered_update_hci(struct hci_dev *hdev)
7459{
Johan Hedberg890ea892013-03-15 17:06:52 -05007460 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007461 u8 link_sec;
7462
Johan Hedberg890ea892013-03-15 17:06:52 -05007463 hci_req_init(&req, hdev);
7464
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007465 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007466 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007467 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007468
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007469 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007470
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007471 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7472 u8 support = 0x01;
7473
7474 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7475 sizeof(support), &support);
7476 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007477 }
7478
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007479 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007480 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007481 struct hci_cp_write_le_host_supported cp;
7482
Marcel Holtmann32226e42014-07-24 20:04:16 +02007483 cp.le = 0x01;
7484 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007485
7486 /* Check first if we already have the right
7487 * host state (host features set)
7488 */
7489 if (cp.le != lmp_host_le_capable(hdev) ||
7490 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007491 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7492 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007493 }
7494
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007495 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007496 /* Make sure the controller has a good default for
7497 * advertising data. This also applies to the case
7498 * where BR/EDR was toggled during the AUTO_OFF phase.
7499 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007500 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007501 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007502 update_scan_rsp_data(&req);
7503 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007504
Arman Uguray24b4f382015-03-23 15:57:12 -07007505 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7506 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007507 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007508
7509 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007510 }
7511
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007512 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007513 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007514 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7515 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007516
7517 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007518 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007519 write_fast_connectable(&req, true);
7520 else
7521 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007522 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007523 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007524 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007525 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007526 }
7527
Johan Hedberg229ab392013-03-15 17:06:53 -05007528 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007529}
7530
Johan Hedberg744cf192011-11-08 20:40:14 +02007531int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007532{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007533 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007534 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007535 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007536
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007537 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007538 return 0;
7539
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007540 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007541 if (powered_update_hci(hdev) == 0)
7542 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007543
Johan Hedberg229ab392013-03-15 17:06:53 -05007544 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7545 &match);
7546 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007547 }
7548
Johan Hedberg229ab392013-03-15 17:06:53 -05007549 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007550
7551 /* If the power off is because of hdev unregistration let
7552 * use the appropriate INVALID_INDEX status. Otherwise use
7553 * NOT_POWERED. We cover both scenarios here since later in
7554 * mgmt_index_removed() any hci_conn callbacks will have already
7555 * been triggered, potentially causing misleading DISCONNECTED
7556 * status responses.
7557 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007558 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007559 status = MGMT_STATUS_INVALID_INDEX;
7560 else
7561 status = MGMT_STATUS_NOT_POWERED;
7562
7563 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007564
7565 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007566 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7567 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007568
7569new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007570 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007571
7572 if (match.sk)
7573 sock_put(match.sk);
7574
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007575 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007576}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007577
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007578void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007579{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007580 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007581 u8 status;
7582
Johan Hedberg333ae952015-03-17 13:48:47 +02007583 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007584 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007585 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007586
7587 if (err == -ERFKILL)
7588 status = MGMT_STATUS_RFKILLED;
7589 else
7590 status = MGMT_STATUS_FAILED;
7591
Johan Hedberga69e8372015-03-06 21:08:53 +02007592 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007593
7594 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007595}
7596
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007597void mgmt_discoverable_timeout(struct hci_dev *hdev)
7598{
7599 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007600
7601 hci_dev_lock(hdev);
7602
7603 /* When discoverable timeout triggers, then just make sure
7604 * the limited discoverable flag is cleared. Even in the case
7605 * of a timeout triggered from general discoverable, it is
7606 * safe to unconditionally clear the flag.
7607 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007608 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7609 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007610
7611 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007612 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007613 u8 scan = SCAN_PAGE;
7614 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7615 sizeof(scan), &scan);
7616 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007617 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007618
7619 /* Advertising instances don't use the global discoverable setting, so
7620 * only update AD if advertising was enabled using Set Advertising.
7621 */
7622 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7623 update_adv_data(&req);
7624
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007625 hci_req_run(&req, NULL);
7626
7627 hdev->discov_timeout = 0;
7628
Johan Hedberg9a43e252013-10-20 19:00:07 +03007629 new_settings(hdev, NULL);
7630
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007631 hci_dev_unlock(hdev);
7632}
7633
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007634void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7635 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007636{
Johan Hedberg86742e12011-11-07 23:13:38 +02007637 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007638
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007639 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007640
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007641 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007642 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007643 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007644 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007645 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007646 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007647
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007648 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007649}
Johan Hedbergf7520542011-01-20 12:34:39 +02007650
Johan Hedbergd7b25452014-05-23 13:19:53 +03007651static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7652{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007653 switch (ltk->type) {
7654 case SMP_LTK:
7655 case SMP_LTK_SLAVE:
7656 if (ltk->authenticated)
7657 return MGMT_LTK_AUTHENTICATED;
7658 return MGMT_LTK_UNAUTHENTICATED;
7659 case SMP_LTK_P256:
7660 if (ltk->authenticated)
7661 return MGMT_LTK_P256_AUTH;
7662 return MGMT_LTK_P256_UNAUTH;
7663 case SMP_LTK_P256_DEBUG:
7664 return MGMT_LTK_P256_DEBUG;
7665 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007666
7667 return MGMT_LTK_UNAUTHENTICATED;
7668}
7669
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007670void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007671{
7672 struct mgmt_ev_new_long_term_key ev;
7673
7674 memset(&ev, 0, sizeof(ev));
7675
Marcel Holtmann5192d302014-02-19 17:11:58 -08007676 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007677 * without providing an identity resolving key don't require
Marcel Holtmann5192d302014-02-19 17:11:58 -08007678 * to store long term keys. Their addresses will change the
7679 * next time around.
7680 *
7681 * Only when a remote device provides an identity address
7682 * make sure the long term key is stored. If the remote
7683 * identity is known, the long term keys are internally
7684 * mapped to the identity address. So allow static random
7685 * and public addresses here.
7686 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007687 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7688 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7689 ev.store_hint = 0x00;
7690 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007691 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007692
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007693 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007694 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007695 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007696 ev.key.enc_size = key->enc_size;
7697 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007698 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007699
Johan Hedberg2ceba532014-06-16 19:25:16 +03007700 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007701 ev.key.master = 1;
7702
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007703 /* Make sure we copy only the significant bytes based on the
7704 * encryption key size, and set the rest of the value to zeroes.
7705 */
7706 memcpy(ev.key.val, key->val, sizeof(key->enc_size));
7707 memset(ev.key.val + key->enc_size, 0,
7708 sizeof(ev.key.val) - key->enc_size);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007709
Marcel Holtmann083368f2013-10-15 14:26:29 -07007710 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007711}
7712
Johan Hedberg95fbac82014-02-19 15:18:31 +02007713void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7714{
7715 struct mgmt_ev_new_irk ev;
7716
7717 memset(&ev, 0, sizeof(ev));
7718
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007719 /* For identity resolving keys from devices that are already
7720 * using a public address or static random address, do not
7721 * ask for storing this key. The identity resolving key really
Florian Grandelf72186d2015-05-26 03:31:09 +02007722 * is only mandatory for devices using resolvable random
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007723 * addresses.
7724 *
7725 * Storing all identity resolving keys has the downside that
7726 * they will be also loaded on next boot of they system. More
7727 * identity resolving keys, means more time during scanning is
7728 * needed to actually resolve these addresses.
7729 */
7730 if (bacmp(&irk->rpa, BDADDR_ANY))
7731 ev.store_hint = 0x01;
7732 else
7733 ev.store_hint = 0x00;
7734
Johan Hedberg95fbac82014-02-19 15:18:31 +02007735 bacpy(&ev.rpa, &irk->rpa);
7736 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7737 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7738 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7739
7740 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7741}
7742
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007743void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7744 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007745{
7746 struct mgmt_ev_new_csrk ev;
7747
7748 memset(&ev, 0, sizeof(ev));
7749
7750 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007751 * without providing an identity resolving key don't require
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007752 * to store signature resolving keys. Their addresses will change
7753 * the next time around.
7754 *
7755 * Only when a remote device provides an identity address
7756 * make sure the signature resolving key is stored. So allow
7757 * static random and public addresses here.
7758 */
7759 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7760 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7761 ev.store_hint = 0x00;
7762 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007763 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007764
7765 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7766 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007767 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007768 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7769
7770 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7771}
7772
Andre Guedesffb5a8272014-07-01 18:10:11 -03007773void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007774 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7775 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007776{
7777 struct mgmt_ev_new_conn_param ev;
7778
Johan Hedbergc103aea2014-07-02 17:37:34 +03007779 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7780 return;
7781
Andre Guedesffb5a8272014-07-01 18:10:11 -03007782 memset(&ev, 0, sizeof(ev));
7783 bacpy(&ev.addr.bdaddr, bdaddr);
7784 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007785 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007786 ev.min_interval = cpu_to_le16(min_interval);
7787 ev.max_interval = cpu_to_le16(max_interval);
7788 ev.latency = cpu_to_le16(latency);
7789 ev.timeout = cpu_to_le16(timeout);
7790
7791 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7792}
7793
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007794void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7795 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007796{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007797 char buf[512];
7798 struct mgmt_ev_device_connected *ev = (void *) buf;
7799 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007800
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007801 bacpy(&ev->addr.bdaddr, &conn->dst);
7802 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007803
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007804 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007805
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007806 /* We must ensure that the EIR Data fields are ordered and
7807 * unique. Keep it simple for now and avoid the problem by not
7808 * adding any BR/EDR data to the LE adv.
7809 */
7810 if (conn->le_adv_data_len > 0) {
7811 memcpy(&ev->eir[eir_len],
7812 conn->le_adv_data, conn->le_adv_data_len);
7813 eir_len = conn->le_adv_data_len;
7814 } else {
7815 if (name_len > 0)
7816 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7817 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007818
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007819 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007820 eir_len = eir_append_data(ev->eir, eir_len,
7821 EIR_CLASS_OF_DEV,
7822 conn->dev_class, 3);
7823 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007824
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007825 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007826
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007827 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7828 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007829}
7830
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007831static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007832{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007833 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007834
Johan Hedbergf5818c22014-12-05 13:36:02 +02007835 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007836
7837 *sk = cmd->sk;
7838 sock_hold(*sk);
7839
Johan Hedberga664b5b2011-02-19 12:06:02 -03007840 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007841}
7842
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007843static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007844{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007845 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007846 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007847
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007848 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7849
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007850 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007851 mgmt_pending_remove(cmd);
7852}
7853
Johan Hedberg84c61d92014-08-01 11:13:30 +03007854bool mgmt_powering_down(struct hci_dev *hdev)
7855{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007856 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007857 struct mgmt_mode *cp;
7858
Johan Hedberg333ae952015-03-17 13:48:47 +02007859 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007860 if (!cmd)
7861 return false;
7862
7863 cp = cmd->param;
7864 if (!cp->val)
7865 return true;
7866
7867 return false;
7868}
7869
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007870void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007871 u8 link_type, u8 addr_type, u8 reason,
7872 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007873{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007874 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007875 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007876
Johan Hedberg84c61d92014-08-01 11:13:30 +03007877 /* The connection is still in hci_conn_hash so test for 1
7878 * instead of 0 to know if this is the last one.
7879 */
7880 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7881 cancel_delayed_work(&hdev->power_off);
7882 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007883 }
7884
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007885 if (!mgmt_connected)
7886 return;
7887
Andre Guedes57eb7762013-10-30 19:01:41 -03007888 if (link_type != ACL_LINK && link_type != LE_LINK)
7889 return;
7890
Johan Hedberg744cf192011-11-08 20:40:14 +02007891 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007892
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007893 bacpy(&ev.addr.bdaddr, bdaddr);
7894 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7895 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007896
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007897 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007898
7899 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007900 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007901
Johan Hedberg124f6e32012-02-09 13:50:12 +02007902 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007903 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007904}
7905
Marcel Holtmann78929242013-10-06 23:55:47 -07007906void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7907 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007908{
Andre Guedes3655bba2013-10-30 19:01:40 -03007909 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7910 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007911 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007912
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007913 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7914 hdev);
7915
Johan Hedberg333ae952015-03-17 13:48:47 +02007916 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007917 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007918 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007919
Andre Guedes3655bba2013-10-30 19:01:40 -03007920 cp = cmd->param;
7921
7922 if (bacmp(bdaddr, &cp->addr.bdaddr))
7923 return;
7924
7925 if (cp->addr.type != bdaddr_type)
7926 return;
7927
Johan Hedbergf5818c22014-12-05 13:36:02 +02007928 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007929 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007930}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007931
Marcel Holtmann445608d2013-10-06 23:55:48 -07007932void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7933 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007934{
7935 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007936
Johan Hedberg84c61d92014-08-01 11:13:30 +03007937 /* The connection is still in hci_conn_hash so test for 1
7938 * instead of 0 to know if this is the last one.
7939 */
7940 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7941 cancel_delayed_work(&hdev->power_off);
7942 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007943 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007944
Johan Hedberg4c659c32011-11-07 23:13:39 +02007945 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007946 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007947 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007948
Marcel Holtmann445608d2013-10-06 23:55:48 -07007949 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007950}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007951
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007952void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007953{
7954 struct mgmt_ev_pin_code_request ev;
7955
Johan Hedbergd8457692012-02-17 14:24:57 +02007956 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007957 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007958 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007959
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007960 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007961}
7962
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007963void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7964 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007965{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007966 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007967
Johan Hedberg333ae952015-03-17 13:48:47 +02007968 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007969 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007970 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007971
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007972 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007973 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007974}
7975
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007976void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7977 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007978{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007979 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007980
Johan Hedberg333ae952015-03-17 13:48:47 +02007981 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007982 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007983 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007984
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007985 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007986 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007987}
Johan Hedberga5c29682011-02-19 12:05:57 -03007988
Johan Hedberg744cf192011-11-08 20:40:14 +02007989int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007990 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007991 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007992{
7993 struct mgmt_ev_user_confirm_request ev;
7994
Johan Hedberg744cf192011-11-08 20:40:14 +02007995 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007996
Johan Hedberg272d90d2012-02-09 15:26:12 +02007997 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007998 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007999 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02008000 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03008001
Johan Hedberg744cf192011-11-08 20:40:14 +02008002 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008003 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03008004}
8005
Johan Hedberg272d90d2012-02-09 15:26:12 +02008006int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03008007 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08008008{
8009 struct mgmt_ev_user_passkey_request ev;
8010
8011 BT_DBG("%s", hdev->name);
8012
Johan Hedberg272d90d2012-02-09 15:26:12 +02008013 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008014 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08008015
8016 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008017 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08008018}
8019
Brian Gix0df4c182011-11-16 13:53:13 -08008020static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03008021 u8 link_type, u8 addr_type, u8 status,
8022 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03008023{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008024 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03008025
Johan Hedberg333ae952015-03-17 13:48:47 +02008026 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03008027 if (!cmd)
8028 return -ENOENT;
8029
Johan Hedberg7776d1d2014-12-05 13:36:03 +02008030 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03008031 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03008032
Johan Hedberg7776d1d2014-12-05 13:36:03 +02008033 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03008034}
8035
Johan Hedberg744cf192011-11-08 20:40:14 +02008036int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008037 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03008038{
Johan Hedberg272d90d2012-02-09 15:26:12 +02008039 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008040 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03008041}
8042
Johan Hedberg272d90d2012-02-09 15:26:12 +02008043int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008044 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03008045{
Johan Hedberg272d90d2012-02-09 15:26:12 +02008046 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03008047 status,
8048 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03008049}
Johan Hedberg2a611692011-02-19 12:06:00 -03008050
Brian Gix604086b2011-11-23 08:28:33 -08008051int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008052 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08008053{
Johan Hedberg272d90d2012-02-09 15:26:12 +02008054 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008055 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08008056}
8057
Johan Hedberg272d90d2012-02-09 15:26:12 +02008058int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008059 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08008060{
Johan Hedberg272d90d2012-02-09 15:26:12 +02008061 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03008062 status,
8063 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08008064}
8065
Johan Hedberg92a25252012-09-06 18:39:26 +03008066int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
8067 u8 link_type, u8 addr_type, u32 passkey,
8068 u8 entered)
8069{
8070 struct mgmt_ev_passkey_notify ev;
8071
8072 BT_DBG("%s", hdev->name);
8073
8074 bacpy(&ev.addr.bdaddr, bdaddr);
8075 ev.addr.type = link_to_bdaddr(link_type, addr_type);
8076 ev.passkey = __cpu_to_le32(passkey);
8077 ev.entered = entered;
8078
8079 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
8080}
8081
Johan Hedberge1e930f2014-09-08 17:09:49 -07008082void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03008083{
8084 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008085 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07008086 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03008087
Johan Hedberge1e930f2014-09-08 17:09:49 -07008088 bacpy(&ev.addr.bdaddr, &conn->dst);
8089 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
8090 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03008091
Johan Hedberge1e930f2014-09-08 17:09:49 -07008092 cmd = find_pairing(conn);
8093
8094 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
8095 cmd ? cmd->sk : NULL);
8096
Johan Hedberga511b352014-12-11 21:45:45 +02008097 if (cmd) {
8098 cmd->cmd_complete(cmd, status);
8099 mgmt_pending_remove(cmd);
8100 }
Johan Hedberg2a611692011-02-19 12:06:00 -03008101}
Johan Hedbergb312b1612011-03-16 14:29:37 +02008102
Marcel Holtmann464996a2013-10-15 14:26:24 -07008103void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008104{
8105 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07008106 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008107
8108 if (status) {
8109 u8 mgmt_err = mgmt_status(status);
8110 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008111 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07008112 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008113 }
8114
Marcel Holtmann464996a2013-10-15 14:26:24 -07008115 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07008116 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07008117 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008118 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02008119
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008120 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008121 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008122
Johan Hedberg47990ea2012-02-22 11:58:37 +02008123 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07008124 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008125
8126 if (match.sk)
8127 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008128}
8129
Johan Hedberg890ea892013-03-15 17:06:52 -05008130static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02008131{
Johan Hedberg890ea892013-03-15 17:06:52 -05008132 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008133 struct hci_cp_write_eir cp;
8134
Johan Hedberg976eb202012-10-24 21:12:01 +03008135 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05008136 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008137
Johan Hedbergc80da272012-02-22 15:38:48 +02008138 memset(hdev->eir, 0, sizeof(hdev->eir));
8139
Johan Hedbergcacaf522012-02-21 00:52:42 +02008140 memset(&cp, 0, sizeof(cp));
8141
Johan Hedberg890ea892013-03-15 17:06:52 -05008142 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02008143}
8144
Marcel Holtmann3e248562013-10-15 14:26:25 -07008145void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008146{
8147 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05008148 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008149 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008150
8151 if (status) {
8152 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008153
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008154 if (enable && hci_dev_test_and_clear_flag(hdev,
8155 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008156 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008157 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008158 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008159
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008160 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
8161 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008162 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008163 }
8164
8165 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07008166 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008167 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008168 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008169 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008170 changed = hci_dev_test_and_clear_flag(hdev,
8171 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008172 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008173 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008174 }
8175
8176 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
8177
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008178 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07008179 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008180
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02008181 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008182 sock_put(match.sk);
8183
Johan Hedberg890ea892013-03-15 17:06:52 -05008184 hci_req_init(&req, hdev);
8185
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008186 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
8187 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03008188 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
8189 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05008190 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008191 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05008192 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008193 }
Johan Hedberg890ea892013-03-15 17:06:52 -05008194
8195 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008196}
8197
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008198static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02008199{
8200 struct cmd_lookup *match = data;
8201
Johan Hedberg90e70452012-02-23 23:09:40 +02008202 if (match->sk == NULL) {
8203 match->sk = cmd->sk;
8204 sock_hold(match->sk);
8205 }
Johan Hedberg90e70452012-02-23 23:09:40 +02008206}
8207
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07008208void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
8209 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008210{
Johan Hedberg90e70452012-02-23 23:09:40 +02008211 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008212
Johan Hedberg92da6092013-03-15 17:06:55 -05008213 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
8214 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
8215 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02008216
8217 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008218 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
8219 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02008220
8221 if (match.sk)
8222 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008223}
8224
Marcel Holtmann7667da32013-10-15 14:26:27 -07008225void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02008226{
Johan Hedbergb312b1612011-03-16 14:29:37 +02008227 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008228 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008229
Johan Hedberg13928972013-03-15 17:07:00 -05008230 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07008231 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008232
8233 memset(&ev, 0, sizeof(ev));
8234 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008235 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008236
Johan Hedberg333ae952015-03-17 13:48:47 +02008237 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05008238 if (!cmd) {
8239 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02008240
Johan Hedberg13928972013-03-15 17:07:00 -05008241 /* If this is a HCI command related to powering on the
8242 * HCI dev don't send any mgmt signals.
8243 */
Johan Hedberg333ae952015-03-17 13:48:47 +02008244 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07008245 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008246 }
8247
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008248 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
8249 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008250}
Szymon Jancc35938b2011-03-22 13:12:21 +01008251
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008252static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
8253{
8254 int i;
8255
8256 for (i = 0; i < uuid_count; i++) {
8257 if (!memcmp(uuid, uuids[i], 16))
8258 return true;
8259 }
8260
8261 return false;
8262}
8263
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008264static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
8265{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008266 u16 parsed = 0;
8267
8268 while (parsed < eir_len) {
8269 u8 field_len = eir[0];
8270 u8 uuid[16];
8271 int i;
8272
8273 if (field_len == 0)
8274 break;
8275
8276 if (eir_len - parsed < field_len + 1)
8277 break;
8278
8279 switch (eir[1]) {
8280 case EIR_UUID16_ALL:
8281 case EIR_UUID16_SOME:
8282 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008283 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008284 uuid[13] = eir[i + 3];
8285 uuid[12] = eir[i + 2];
8286 if (has_uuid(uuid, uuid_count, uuids))
8287 return true;
8288 }
8289 break;
8290 case EIR_UUID32_ALL:
8291 case EIR_UUID32_SOME:
8292 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008293 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008294 uuid[15] = eir[i + 5];
8295 uuid[14] = eir[i + 4];
8296 uuid[13] = eir[i + 3];
8297 uuid[12] = eir[i + 2];
8298 if (has_uuid(uuid, uuid_count, uuids))
8299 return true;
8300 }
8301 break;
8302 case EIR_UUID128_ALL:
8303 case EIR_UUID128_SOME:
8304 for (i = 0; i + 17 <= field_len; i += 16) {
8305 memcpy(uuid, eir + i + 2, 16);
8306 if (has_uuid(uuid, uuid_count, uuids))
8307 return true;
8308 }
8309 break;
8310 }
8311
8312 parsed += field_len + 1;
8313 eir += field_len + 1;
8314 }
8315
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008316 return false;
8317}
8318
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008319static void restart_le_scan(struct hci_dev *hdev)
8320{
8321 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008322 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008323 return;
8324
8325 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8326 hdev->discovery.scan_start +
8327 hdev->discovery.scan_duration))
8328 return;
8329
8330 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8331 DISCOV_LE_RESTART_DELAY);
8332}
8333
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008334static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8335 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8336{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008337 /* If a RSSI threshold has been specified, and
8338 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8339 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8340 * is set, let it through for further processing, as we might need to
8341 * restart the scan.
8342 *
8343 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8344 * the results are also dropped.
8345 */
8346 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8347 (rssi == HCI_RSSI_INVALID ||
8348 (rssi < hdev->discovery.rssi &&
8349 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8350 return false;
8351
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008352 if (hdev->discovery.uuid_count != 0) {
8353 /* If a list of UUIDs is provided in filter, results with no
8354 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008355 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008356 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8357 hdev->discovery.uuids) &&
8358 !eir_has_uuids(scan_rsp, scan_rsp_len,
8359 hdev->discovery.uuid_count,
8360 hdev->discovery.uuids))
8361 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008362 }
8363
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008364 /* If duplicate filtering does not report RSSI changes, then restart
8365 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008366 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008367 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8368 restart_le_scan(hdev);
8369
8370 /* Validate RSSI value against the RSSI threshold once more. */
8371 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8372 rssi < hdev->discovery.rssi)
8373 return false;
8374 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008375
8376 return true;
8377}
8378
Marcel Holtmann901801b2013-10-06 23:55:51 -07008379void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008380 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8381 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008382{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008383 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008384 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008385 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008386
Johan Hedberg75ce2082014-07-02 22:42:01 +03008387 /* Don't send events for a non-kernel initiated discovery. With
8388 * LE one exception is if we have pend_le_reports > 0 in which
8389 * case we're doing passive scanning and want these events.
8390 */
8391 if (!hci_discovery_active(hdev)) {
8392 if (link_type == ACL_LINK)
8393 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008394 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008395 return;
8396 }
Andre Guedes12602d02013-04-30 15:29:40 -03008397
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008398 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008399 /* We are using service discovery */
8400 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8401 scan_rsp_len))
8402 return;
8403 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008404
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008405 /* Make sure that the buffer is big enough. The 5 extra bytes
8406 * are for the potential CoD field.
8407 */
8408 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008409 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008410
Johan Hedberg1dc06092012-01-15 21:01:23 +02008411 memset(buf, 0, sizeof(buf));
8412
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008413 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8414 * RSSI value was reported as 0 when not available. This behavior
8415 * is kept when using device discovery. This is required for full
8416 * backwards compatibility with the API.
8417 *
8418 * However when using service discovery, the value 127 will be
8419 * returned when the RSSI is not available.
8420 */
Szymon Janc91200e92015-01-22 16:57:05 +01008421 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8422 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008423 rssi = 0;
8424
Johan Hedberg841c5642014-07-07 12:45:54 +03008425 bacpy(&ev->addr.bdaddr, bdaddr);
8426 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008427 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008428 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008429
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008430 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008431 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008432 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008433
Johan Hedberg1dc06092012-01-15 21:01:23 +02008434 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8435 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008436 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008437
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008438 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008439 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008440 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008441
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008442 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8443 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008444
Marcel Holtmann901801b2013-10-06 23:55:51 -07008445 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008446}
Johan Hedberga88a9652011-03-30 13:18:12 +03008447
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008448void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8449 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008450{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008451 struct mgmt_ev_device_found *ev;
8452 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8453 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008454
Johan Hedbergb644ba32012-01-17 21:48:47 +02008455 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008456
Johan Hedbergb644ba32012-01-17 21:48:47 +02008457 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008458
Johan Hedbergb644ba32012-01-17 21:48:47 +02008459 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008460 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008461 ev->rssi = rssi;
8462
8463 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008464 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008465
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008466 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008467
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008468 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008469}
Johan Hedberg314b2382011-04-27 10:29:57 -04008470
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008471void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008472{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008473 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008474
Andre Guedes343fb142011-11-22 17:14:19 -03008475 BT_DBG("%s discovering %u", hdev->name, discovering);
8476
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008477 memset(&ev, 0, sizeof(ev));
8478 ev.type = hdev->discovery.type;
8479 ev.discovering = discovering;
8480
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008481 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008482}
Antti Julku5e762442011-08-25 16:48:02 +03008483
Marcel Holtmann1904a852015-01-11 13:50:44 -08008484static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008485{
8486 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008487}
8488
8489void mgmt_reenable_advertising(struct hci_dev *hdev)
8490{
8491 struct hci_request req;
8492
Arman Uguray24b4f382015-03-23 15:57:12 -07008493 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8494 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008495 return;
8496
8497 hci_req_init(&req, hdev);
8498 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008499 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008500}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008501
8502static struct hci_mgmt_chan chan = {
8503 .channel = HCI_CHANNEL_CONTROL,
8504 .handler_count = ARRAY_SIZE(mgmt_handlers),
8505 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008506 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008507};
8508
8509int mgmt_init(void)
8510{
8511 return hci_mgmt_chan_register(&chan);
8512}
8513
8514void mgmt_exit(void)
8515{
8516 hci_mgmt_chan_unregister(&chan);
8517}