blob: 38b03bd147237010249fdbdb2ea63c133e4a0202 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg71290692015-02-20 13:26:23 +020032#include <net/bluetooth/hci_sock.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030033#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020034#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070035
Johan Hedberg0857dd32014-12-19 13:40:20 +020036#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070037#include "smp.h"
Johan Hedberga380b6c2015-03-17 13:48:48 +020038#include "mgmt_util.h"
Johan Hedberg03811012010-12-08 00:21:06 +020039
Johan Hedberg2da9c552012-02-17 14:39:28 +020040#define MGMT_VERSION 1
Marcel Holtmannbeb1c212015-03-10 14:04:52 -070041#define MGMT_REVISION 9
Johan Hedberg02d98122010-12-13 21:07:04 +020042
Johan Hedberge70bb2e2012-02-13 16:59:33 +020043static const u16 mgmt_commands[] = {
44 MGMT_OP_READ_INDEX_LIST,
45 MGMT_OP_READ_INFO,
46 MGMT_OP_SET_POWERED,
47 MGMT_OP_SET_DISCOVERABLE,
48 MGMT_OP_SET_CONNECTABLE,
49 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030050 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020051 MGMT_OP_SET_LINK_SECURITY,
52 MGMT_OP_SET_SSP,
53 MGMT_OP_SET_HS,
54 MGMT_OP_SET_LE,
55 MGMT_OP_SET_DEV_CLASS,
56 MGMT_OP_SET_LOCAL_NAME,
57 MGMT_OP_ADD_UUID,
58 MGMT_OP_REMOVE_UUID,
59 MGMT_OP_LOAD_LINK_KEYS,
60 MGMT_OP_LOAD_LONG_TERM_KEYS,
61 MGMT_OP_DISCONNECT,
62 MGMT_OP_GET_CONNECTIONS,
63 MGMT_OP_PIN_CODE_REPLY,
64 MGMT_OP_PIN_CODE_NEG_REPLY,
65 MGMT_OP_SET_IO_CAPABILITY,
66 MGMT_OP_PAIR_DEVICE,
67 MGMT_OP_CANCEL_PAIR_DEVICE,
68 MGMT_OP_UNPAIR_DEVICE,
69 MGMT_OP_USER_CONFIRM_REPLY,
70 MGMT_OP_USER_CONFIRM_NEG_REPLY,
71 MGMT_OP_USER_PASSKEY_REPLY,
72 MGMT_OP_USER_PASSKEY_NEG_REPLY,
73 MGMT_OP_READ_LOCAL_OOB_DATA,
74 MGMT_OP_ADD_REMOTE_OOB_DATA,
75 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
76 MGMT_OP_START_DISCOVERY,
77 MGMT_OP_STOP_DISCOVERY,
78 MGMT_OP_CONFIRM_NAME,
79 MGMT_OP_BLOCK_DEVICE,
80 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070081 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030082 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030083 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070084 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070085 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080086 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080087 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020088 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020089 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020090 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030091 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020092 MGMT_OP_ADD_DEVICE,
93 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030094 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020095 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020096 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020097 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020098 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010099 MGMT_OP_START_SERVICE_DISCOVERY,
Marcel Holtmann4f0f1552015-03-14 22:43:19 -0700100 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann96f14742015-03-14 19:27:57 -0700101 MGMT_OP_READ_EXT_INDEX_LIST,
Marcel Holtmannd3d53052015-03-14 20:53:25 -0700102 MGMT_OP_READ_ADV_FEATURES,
Arman Uguray24b4f382015-03-23 15:57:12 -0700103 MGMT_OP_ADD_ADVERTISING,
Arman Ugurayda9293352015-03-23 15:57:13 -0700104 MGMT_OP_REMOVE_ADVERTISING,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200105};
106
107static const u16 mgmt_events[] = {
108 MGMT_EV_CONTROLLER_ERROR,
109 MGMT_EV_INDEX_ADDED,
110 MGMT_EV_INDEX_REMOVED,
111 MGMT_EV_NEW_SETTINGS,
112 MGMT_EV_CLASS_OF_DEV_CHANGED,
113 MGMT_EV_LOCAL_NAME_CHANGED,
114 MGMT_EV_NEW_LINK_KEY,
115 MGMT_EV_NEW_LONG_TERM_KEY,
116 MGMT_EV_DEVICE_CONNECTED,
117 MGMT_EV_DEVICE_DISCONNECTED,
118 MGMT_EV_CONNECT_FAILED,
119 MGMT_EV_PIN_CODE_REQUEST,
120 MGMT_EV_USER_CONFIRM_REQUEST,
121 MGMT_EV_USER_PASSKEY_REQUEST,
122 MGMT_EV_AUTH_FAILED,
123 MGMT_EV_DEVICE_FOUND,
124 MGMT_EV_DISCOVERING,
125 MGMT_EV_DEVICE_BLOCKED,
126 MGMT_EV_DEVICE_UNBLOCKED,
127 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300128 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800129 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700130 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200131 MGMT_EV_DEVICE_ADDED,
132 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300133 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200134 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200135 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200136 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700137 MGMT_EV_EXT_INDEX_ADDED,
138 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700139 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Arman Uguray24b4f382015-03-23 15:57:12 -0700140 MGMT_EV_ADVERTISING_ADDED,
141 MGMT_EV_ADVERTISING_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200142};
143
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700144static const u16 mgmt_untrusted_commands[] = {
145 MGMT_OP_READ_INDEX_LIST,
146 MGMT_OP_READ_INFO,
147 MGMT_OP_READ_UNCONF_INDEX_LIST,
148 MGMT_OP_READ_CONFIG_INFO,
149 MGMT_OP_READ_EXT_INDEX_LIST,
150};
151
152static const u16 mgmt_untrusted_events[] = {
153 MGMT_EV_INDEX_ADDED,
154 MGMT_EV_INDEX_REMOVED,
155 MGMT_EV_NEW_SETTINGS,
156 MGMT_EV_CLASS_OF_DEV_CHANGED,
157 MGMT_EV_LOCAL_NAME_CHANGED,
158 MGMT_EV_UNCONF_INDEX_ADDED,
159 MGMT_EV_UNCONF_INDEX_REMOVED,
160 MGMT_EV_NEW_CONFIG_OPTIONS,
161 MGMT_EV_EXT_INDEX_ADDED,
162 MGMT_EV_EXT_INDEX_REMOVED,
163};
164
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800165#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200166
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200167#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
168 "\x00\x00\x00\x00\x00\x00\x00\x00"
169
Johan Hedbergca69b792011-11-11 18:10:00 +0200170/* HCI to MGMT error code conversion table */
171static u8 mgmt_status_table[] = {
172 MGMT_STATUS_SUCCESS,
173 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
174 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
175 MGMT_STATUS_FAILED, /* Hardware Failure */
176 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
177 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200178 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200179 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
180 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
181 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
182 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
183 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
184 MGMT_STATUS_BUSY, /* Command Disallowed */
185 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
186 MGMT_STATUS_REJECTED, /* Rejected Security */
187 MGMT_STATUS_REJECTED, /* Rejected Personal */
188 MGMT_STATUS_TIMEOUT, /* Host Timeout */
189 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
190 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
191 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
192 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
193 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
194 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
195 MGMT_STATUS_BUSY, /* Repeated Attempts */
196 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
197 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
198 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
199 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
200 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
201 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
202 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
203 MGMT_STATUS_FAILED, /* Unspecified Error */
204 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
205 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
206 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
207 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
208 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
209 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
210 MGMT_STATUS_FAILED, /* Unit Link Key Used */
211 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
212 MGMT_STATUS_TIMEOUT, /* Instant Passed */
213 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
214 MGMT_STATUS_FAILED, /* Transaction Collision */
215 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
216 MGMT_STATUS_REJECTED, /* QoS Rejected */
217 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
218 MGMT_STATUS_REJECTED, /* Insufficient Security */
219 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
220 MGMT_STATUS_BUSY, /* Role Switch Pending */
221 MGMT_STATUS_FAILED, /* Slot Violation */
222 MGMT_STATUS_FAILED, /* Role Switch Failed */
223 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
224 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
225 MGMT_STATUS_BUSY, /* Host Busy Pairing */
226 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
227 MGMT_STATUS_BUSY, /* Controller Busy */
228 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
229 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
230 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
231 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
232 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
233};
234
235static u8 mgmt_status(u8 hci_status)
236{
237 if (hci_status < ARRAY_SIZE(mgmt_status_table))
238 return mgmt_status_table[hci_status];
239
240 return MGMT_STATUS_FAILED;
241}
242
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700243static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
244 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700245{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700246 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
247 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700248}
249
Marcel Holtmann72000df2015-03-16 16:11:21 -0700250static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
251 u16 len, int flag, struct sock *skip_sk)
252{
253 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
254 flag, skip_sk);
255}
256
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700257static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
258 u16 len, struct sock *skip_sk)
259{
260 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
261 HCI_MGMT_GENERIC_EVENTS, skip_sk);
262}
263
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200264static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
265 struct sock *skip_sk)
266{
267 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700268 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200269}
270
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300271static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
272 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200273{
274 struct mgmt_rp_read_version rp;
275
276 BT_DBG("sock %p", sk);
277
278 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700279 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200280
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200281 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
282 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200283}
284
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300285static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
286 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200287{
288 struct mgmt_rp_read_commands *rp;
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700289 u16 num_commands, num_events;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200290 size_t rp_size;
291 int i, err;
292
293 BT_DBG("sock %p", sk);
294
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700295 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
296 num_commands = ARRAY_SIZE(mgmt_commands);
297 num_events = ARRAY_SIZE(mgmt_events);
298 } else {
299 num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
300 num_events = ARRAY_SIZE(mgmt_untrusted_events);
301 }
302
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200303 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
304
305 rp = kmalloc(rp_size, GFP_KERNEL);
306 if (!rp)
307 return -ENOMEM;
308
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700309 rp->num_commands = cpu_to_le16(num_commands);
310 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700312 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
313 __le16 *opcode = rp->opcodes;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200314
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700315 for (i = 0; i < num_commands; i++, opcode++)
316 put_unaligned_le16(mgmt_commands[i], opcode);
317
318 for (i = 0; i < num_events; i++, opcode++)
319 put_unaligned_le16(mgmt_events[i], opcode);
320 } else {
321 __le16 *opcode = rp->opcodes;
322
323 for (i = 0; i < num_commands; i++, opcode++)
324 put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
325
326 for (i = 0; i < num_events; i++, opcode++)
327 put_unaligned_le16(mgmt_untrusted_events[i], opcode);
328 }
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200329
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200330 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
331 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 kfree(rp);
333
334 return err;
335}
336
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300337static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
338 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200341 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200342 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200343 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300344 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345
346 BT_DBG("sock %p", sk);
347
348 read_lock(&hci_dev_list_lock);
349
350 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300351 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200352 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700353 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700354 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200355 }
356
Johan Hedberga38528f2011-01-22 06:46:43 +0200357 rp_len = sizeof(*rp) + (2 * count);
358 rp = kmalloc(rp_len, GFP_ATOMIC);
359 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100360 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100362 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363
Johan Hedberg476e44c2012-10-19 20:10:46 +0300364 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200365 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700366 if (hci_dev_test_flag(d, HCI_SETUP) ||
367 hci_dev_test_flag(d, HCI_CONFIG) ||
368 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200369 continue;
370
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200371 /* Devices marked as raw-only are neither configured
372 * nor unconfigured controllers.
373 */
374 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700375 continue;
376
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200377 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700378 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700379 rp->index[count++] = cpu_to_le16(d->id);
380 BT_DBG("Added hci%u", d->id);
381 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 }
383
Johan Hedberg476e44c2012-10-19 20:10:46 +0300384 rp->num_controllers = cpu_to_le16(count);
385 rp_len = sizeof(*rp) + (2 * count);
386
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200387 read_unlock(&hci_dev_list_lock);
388
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200389 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
390 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200391
Johan Hedberga38528f2011-01-22 06:46:43 +0200392 kfree(rp);
393
394 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200395}
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
398 void *data, u16 data_len)
399{
400 struct mgmt_rp_read_unconf_index_list *rp;
401 struct hci_dev *d;
402 size_t rp_len;
403 u16 count;
404 int err;
405
406 BT_DBG("sock %p", sk);
407
408 read_lock(&hci_dev_list_lock);
409
410 count = 0;
411 list_for_each_entry(d, &hci_dev_list, list) {
412 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700413 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200414 count++;
415 }
416
417 rp_len = sizeof(*rp) + (2 * count);
418 rp = kmalloc(rp_len, GFP_ATOMIC);
419 if (!rp) {
420 read_unlock(&hci_dev_list_lock);
421 return -ENOMEM;
422 }
423
424 count = 0;
425 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700426 if (hci_dev_test_flag(d, HCI_SETUP) ||
427 hci_dev_test_flag(d, HCI_CONFIG) ||
428 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200429 continue;
430
431 /* Devices marked as raw-only are neither configured
432 * nor unconfigured controllers.
433 */
434 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
435 continue;
436
437 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700438 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200439 rp->index[count++] = cpu_to_le16(d->id);
440 BT_DBG("Added hci%u", d->id);
441 }
442 }
443
444 rp->num_controllers = cpu_to_le16(count);
445 rp_len = sizeof(*rp) + (2 * count);
446
447 read_unlock(&hci_dev_list_lock);
448
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200449 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
450 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200451
452 kfree(rp);
453
454 return err;
455}
456
Marcel Holtmann96f14742015-03-14 19:27:57 -0700457static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
458 void *data, u16 data_len)
459{
460 struct mgmt_rp_read_ext_index_list *rp;
461 struct hci_dev *d;
462 size_t rp_len;
463 u16 count;
464 int err;
465
466 BT_DBG("sock %p", sk);
467
468 read_lock(&hci_dev_list_lock);
469
470 count = 0;
471 list_for_each_entry(d, &hci_dev_list, list) {
472 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
473 count++;
474 }
475
476 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
477 rp = kmalloc(rp_len, GFP_ATOMIC);
478 if (!rp) {
479 read_unlock(&hci_dev_list_lock);
480 return -ENOMEM;
481 }
482
483 count = 0;
484 list_for_each_entry(d, &hci_dev_list, list) {
485 if (hci_dev_test_flag(d, HCI_SETUP) ||
486 hci_dev_test_flag(d, HCI_CONFIG) ||
487 hci_dev_test_flag(d, HCI_USER_CHANNEL))
488 continue;
489
490 /* Devices marked as raw-only are neither configured
491 * nor unconfigured controllers.
492 */
493 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
494 continue;
495
496 if (d->dev_type == HCI_BREDR) {
497 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
498 rp->entry[count].type = 0x01;
499 else
500 rp->entry[count].type = 0x00;
501 } else if (d->dev_type == HCI_AMP) {
502 rp->entry[count].type = 0x02;
503 } else {
504 continue;
505 }
506
507 rp->entry[count].bus = d->bus;
508 rp->entry[count++].index = cpu_to_le16(d->id);
509 BT_DBG("Added hci%u", d->id);
510 }
511
512 rp->num_controllers = cpu_to_le16(count);
513 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
514
515 read_unlock(&hci_dev_list_lock);
516
517 /* If this command is called at least once, then all the
518 * default index and unconfigured index events are disabled
519 * and from now on only extended index events are used.
520 */
521 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
522 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
523 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
524
525 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
526 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
527
528 kfree(rp);
529
530 return err;
531}
532
Marcel Holtmanndbece372014-07-04 18:11:55 +0200533static bool is_configured(struct hci_dev *hdev)
534{
535 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700536 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200537 return false;
538
539 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
540 !bacmp(&hdev->public_addr, BDADDR_ANY))
541 return false;
542
543 return true;
544}
545
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200546static __le32 get_missing_options(struct hci_dev *hdev)
547{
548 u32 options = 0;
549
Marcel Holtmanndbece372014-07-04 18:11:55 +0200550 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700551 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200552 options |= MGMT_OPTION_EXTERNAL_CONFIG;
553
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200554 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
555 !bacmp(&hdev->public_addr, BDADDR_ANY))
556 options |= MGMT_OPTION_PUBLIC_ADDRESS;
557
558 return cpu_to_le32(options);
559}
560
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200561static int new_options(struct hci_dev *hdev, struct sock *skip)
562{
563 __le32 options = get_missing_options(hdev);
564
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700565 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
566 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200567}
568
Marcel Holtmanndbece372014-07-04 18:11:55 +0200569static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
570{
571 __le32 options = get_missing_options(hdev);
572
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200573 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
574 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200575}
576
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200577static int read_config_info(struct sock *sk, struct hci_dev *hdev,
578 void *data, u16 data_len)
579{
580 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200581 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200582
583 BT_DBG("sock %p %s", sk, hdev->name);
584
585 hci_dev_lock(hdev);
586
587 memset(&rp, 0, sizeof(rp));
588 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200589
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200590 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
591 options |= MGMT_OPTION_EXTERNAL_CONFIG;
592
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200593 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200594 options |= MGMT_OPTION_PUBLIC_ADDRESS;
595
596 rp.supported_options = cpu_to_le32(options);
597 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200598
599 hci_dev_unlock(hdev);
600
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200601 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
602 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200603}
604
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200606{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200608
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300610 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800611 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300612 settings |= MGMT_SETTING_CONNECTABLE;
613 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200614
Andre Guedesed3fa312012-07-24 15:03:46 -0300615 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500616 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
617 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_BREDR;
619 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700620
621 if (lmp_ssp_capable(hdev)) {
622 settings |= MGMT_SETTING_SSP;
623 settings |= MGMT_SETTING_HS;
624 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800625
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800626 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700628 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100629
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300630 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200631 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300632 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300633 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800635 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300636 }
Johan Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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
696 * will never bet set. If the address is configured, then if the
697 * address is actually used decides if the flag is set or not.
698 *
699 * For single mode LE only controllers and dual-mode controllers
700 * with BR/EDR disabled, the existence of the static address will
701 * be evaluated.
702 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700703 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700704 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
706 if (bacmp(&hdev->static_addr, BDADDR_ANY))
707 settings |= MGMT_SETTING_STATIC_ADDRESS;
708 }
709
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200710 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200711}
712
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300713#define PNP_INFO_SVCLASS_ID 0x1200
714
Johan Hedberg213202e2013-01-27 00:31:33 +0200715static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 4)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 u16 uuid16;
725
726 if (uuid->size != 16)
727 continue;
728
729 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
730 if (uuid16 < 0x1100)
731 continue;
732
733 if (uuid16 == PNP_INFO_SVCLASS_ID)
734 continue;
735
736 if (!uuids_start) {
737 uuids_start = ptr;
738 uuids_start[0] = 1;
739 uuids_start[1] = EIR_UUID16_ALL;
740 ptr += 2;
741 }
742
743 /* Stop if not enough space to put next UUID */
744 if ((ptr - data) + sizeof(u16) > len) {
745 uuids_start[1] = EIR_UUID16_SOME;
746 break;
747 }
748
749 *ptr++ = (uuid16 & 0x00ff);
750 *ptr++ = (uuid16 & 0xff00) >> 8;
751 uuids_start[0] += sizeof(uuid16);
752 }
753
754 return ptr;
755}
756
Johan Hedbergcdf19632013-01-27 00:31:34 +0200757static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
758{
759 u8 *ptr = data, *uuids_start = NULL;
760 struct bt_uuid *uuid;
761
762 if (len < 6)
763 return ptr;
764
765 list_for_each_entry(uuid, &hdev->uuids, list) {
766 if (uuid->size != 32)
767 continue;
768
769 if (!uuids_start) {
770 uuids_start = ptr;
771 uuids_start[0] = 1;
772 uuids_start[1] = EIR_UUID32_ALL;
773 ptr += 2;
774 }
775
776 /* Stop if not enough space to put next UUID */
777 if ((ptr - data) + sizeof(u32) > len) {
778 uuids_start[1] = EIR_UUID32_SOME;
779 break;
780 }
781
782 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
783 ptr += sizeof(u32);
784 uuids_start[0] += sizeof(u32);
785 }
786
787 return ptr;
788}
789
Johan Hedbergc00d5752013-01-27 00:31:35 +0200790static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
791{
792 u8 *ptr = data, *uuids_start = NULL;
793 struct bt_uuid *uuid;
794
795 if (len < 18)
796 return ptr;
797
798 list_for_each_entry(uuid, &hdev->uuids, list) {
799 if (uuid->size != 128)
800 continue;
801
802 if (!uuids_start) {
803 uuids_start = ptr;
804 uuids_start[0] = 1;
805 uuids_start[1] = EIR_UUID128_ALL;
806 ptr += 2;
807 }
808
809 /* Stop if not enough space to put next UUID */
810 if ((ptr - data) + 16 > len) {
811 uuids_start[1] = EIR_UUID128_SOME;
812 break;
813 }
814
815 memcpy(ptr, uuid->uuid, 16);
816 ptr += 16;
817 uuids_start[0] += 16;
818 }
819
820 return ptr;
821}
822
Johan Hedberg333ae952015-03-17 13:48:47 +0200823static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
824{
825 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
826}
827
Johan Hedberg333ae952015-03-17 13:48:47 +0200828static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
829 struct hci_dev *hdev,
830 const void *data)
831{
832 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
833}
834
Arman Uguray4117ed72015-03-23 15:57:14 -0700835static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700836{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700837 u8 ad_len = 0;
838 size_t name_len;
839
840 name_len = strlen(hdev->dev_name);
841 if (name_len > 0) {
842 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
843
844 if (name_len > max_len) {
845 name_len = max_len;
846 ptr[1] = EIR_NAME_SHORT;
847 } else
848 ptr[1] = EIR_NAME_COMPLETE;
849
850 ptr[0] = name_len + 1;
851
852 memcpy(ptr + 2, hdev->dev_name, name_len);
853
854 ad_len += (name_len + 2);
855 ptr += (name_len + 2);
856 }
857
858 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700859}
860
Arman Uguray4117ed72015-03-23 15:57:14 -0700861static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
862{
863 /* TODO: Set the appropriate entries based on advertising instance flags
864 * here once flags other than 0 are supported.
865 */
866 memcpy(ptr, hdev->adv_instance.scan_rsp_data,
867 hdev->adv_instance.scan_rsp_len);
868
869 return hdev->adv_instance.scan_rsp_len;
870}
871
872static void update_scan_rsp_data_for_instance(struct hci_request *req,
873 u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700874{
875 struct hci_dev *hdev = req->hdev;
876 struct hci_cp_le_set_scan_rsp_data cp;
877 u8 len;
878
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700880 return;
881
882 memset(&cp, 0, sizeof(cp));
883
Arman Uguray4117ed72015-03-23 15:57:14 -0700884 if (instance)
885 len = create_instance_scan_rsp_data(hdev, cp.data);
886 else
887 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700888
Johan Hedbergeb438b52013-10-16 15:31:07 +0300889 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700890 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700891 return;
892
Johan Hedbergeb438b52013-10-16 15:31:07 +0300893 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
894 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700895
896 cp.length = len;
897
898 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
899}
900
Arman Uguray4117ed72015-03-23 15:57:14 -0700901static void update_scan_rsp_data(struct hci_request *req)
902{
903 struct hci_dev *hdev = req->hdev;
904 u8 instance;
905
906 /* The "Set Advertising" setting supersedes the "Add Advertising"
907 * setting. Here we set the scan response data based on which
908 * setting was set. When neither apply, default to the global settings,
909 * represented by instance "0".
910 */
911 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
912 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
913 instance = 0x01;
914 else
915 instance = 0x00;
916
917 update_scan_rsp_data_for_instance(req, instance);
918}
919
Johan Hedberg9a43e252013-10-20 19:00:07 +0300920static u8 get_adv_discov_flags(struct hci_dev *hdev)
921{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200922 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300923
924 /* If there's a pending mgmt command the flags will not yet have
925 * their final values, so check for this first.
926 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200927 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300928 if (cmd) {
929 struct mgmt_mode *cp = cmd->param;
930 if (cp->val == 0x01)
931 return LE_AD_GENERAL;
932 else if (cp->val == 0x02)
933 return LE_AD_LIMITED;
934 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700935 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300936 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700937 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300938 return LE_AD_GENERAL;
939 }
940
941 return 0;
942}
943
Arman Uguray24b4f382015-03-23 15:57:12 -0700944static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700945{
946 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700947
Johan Hedberg9a43e252013-10-20 19:00:07 +0300948 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700949
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700950 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700951 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700952
953 if (flags) {
954 BT_DBG("adv flags 0x%02x", flags);
955
956 ptr[0] = 2;
957 ptr[1] = EIR_FLAGS;
958 ptr[2] = flags;
959
960 ad_len += 3;
961 ptr += 3;
962 }
963
964 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
965 ptr[0] = 2;
966 ptr[1] = EIR_TX_POWER;
967 ptr[2] = (u8) hdev->adv_tx_power;
968
969 ad_len += 3;
970 ptr += 3;
971 }
972
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700973 return ad_len;
974}
975
Arman Uguray24b4f382015-03-23 15:57:12 -0700976static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
977{
978 /* TODO: Set the appropriate entries based on advertising instance flags
979 * here once flags other than 0 are supported.
980 */
981 memcpy(ptr, hdev->adv_instance.adv_data,
982 hdev->adv_instance.adv_data_len);
983
984 return hdev->adv_instance.adv_data_len;
985}
986
987static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700988{
989 struct hci_dev *hdev = req->hdev;
990 struct hci_cp_le_set_adv_data cp;
991 u8 len;
992
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700993 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700994 return;
995
996 memset(&cp, 0, sizeof(cp));
997
Arman Uguray24b4f382015-03-23 15:57:12 -0700998 if (instance)
999 len = create_instance_adv_data(hdev, cp.data);
1000 else
1001 len = create_default_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001002
Arman Uguray24b4f382015-03-23 15:57:12 -07001003 /* There's nothing to do if the data hasn't changed */
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001004 if (hdev->adv_data_len == len &&
1005 memcmp(cp.data, hdev->adv_data, len) == 0)
1006 return;
1007
1008 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1009 hdev->adv_data_len = len;
1010
1011 cp.length = len;
1012
1013 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1014}
1015
Arman Uguray24b4f382015-03-23 15:57:12 -07001016static void update_adv_data(struct hci_request *req)
1017{
1018 struct hci_dev *hdev = req->hdev;
1019 u8 instance;
1020
1021 /* The "Set Advertising" setting supersedes the "Add Advertising"
1022 * setting. Here we set the advertising data based on which
1023 * setting was set. When neither apply, default to the global settings,
1024 * represented by instance "0".
1025 */
1026 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
1027 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
1028 instance = 0x01;
1029 else
1030 instance = 0x00;
1031
1032 update_adv_data_for_instance(req, instance);
1033}
1034
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001035int mgmt_update_adv_data(struct hci_dev *hdev)
1036{
1037 struct hci_request req;
1038
1039 hci_req_init(&req, hdev);
1040 update_adv_data(&req);
1041
1042 return hci_req_run(&req, NULL);
1043}
1044
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001045static void create_eir(struct hci_dev *hdev, u8 *data)
1046{
1047 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001048 size_t name_len;
1049
1050 name_len = strlen(hdev->dev_name);
1051
1052 if (name_len > 0) {
1053 /* EIR Data type */
1054 if (name_len > 48) {
1055 name_len = 48;
1056 ptr[1] = EIR_NAME_SHORT;
1057 } else
1058 ptr[1] = EIR_NAME_COMPLETE;
1059
1060 /* EIR Data length */
1061 ptr[0] = name_len + 1;
1062
1063 memcpy(ptr + 2, hdev->dev_name, name_len);
1064
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001065 ptr += (name_len + 2);
1066 }
1067
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001068 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001069 ptr[0] = 2;
1070 ptr[1] = EIR_TX_POWER;
1071 ptr[2] = (u8) hdev->inq_tx_power;
1072
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001073 ptr += 3;
1074 }
1075
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001076 if (hdev->devid_source > 0) {
1077 ptr[0] = 9;
1078 ptr[1] = EIR_DEVICE_ID;
1079
1080 put_unaligned_le16(hdev->devid_source, ptr + 2);
1081 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1082 put_unaligned_le16(hdev->devid_product, ptr + 6);
1083 put_unaligned_le16(hdev->devid_version, ptr + 8);
1084
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001085 ptr += 10;
1086 }
1087
Johan Hedberg213202e2013-01-27 00:31:33 +02001088 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001089 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001090 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001091}
1092
Johan Hedberg890ea892013-03-15 17:06:52 -05001093static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001094{
Johan Hedberg890ea892013-03-15 17:06:52 -05001095 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001096 struct hci_cp_write_eir cp;
1097
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001098 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001099 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001100
Johan Hedberg976eb202012-10-24 21:12:01 +03001101 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001102 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001103
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001104 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001105 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001106
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001107 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001108 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001109
1110 memset(&cp, 0, sizeof(cp));
1111
1112 create_eir(hdev, cp.data);
1113
1114 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001115 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001116
1117 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1118
Johan Hedberg890ea892013-03-15 17:06:52 -05001119 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001120}
1121
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001122static u8 get_service_classes(struct hci_dev *hdev)
1123{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001124 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001125 u8 val = 0;
1126
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001127 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001128 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001129
1130 return val;
1131}
1132
Johan Hedberg890ea892013-03-15 17:06:52 -05001133static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001134{
Johan Hedberg890ea892013-03-15 17:06:52 -05001135 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001136 u8 cod[3];
1137
1138 BT_DBG("%s", hdev->name);
1139
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001140 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001141 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001142
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001143 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001144 return;
1145
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001146 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001147 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001148
1149 cod[0] = hdev->minor_class;
1150 cod[1] = hdev->major_class;
1151 cod[2] = get_service_classes(hdev);
1152
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001153 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001154 cod[1] |= 0x20;
1155
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001156 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001157 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001158
Johan Hedberg890ea892013-03-15 17:06:52 -05001159 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001160}
1161
Johan Hedberga4858cb2014-02-25 19:56:31 +02001162static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001163{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001164 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001165
1166 /* If there's a pending mgmt command the flag will not yet have
1167 * it's final value, so check for this first.
1168 */
Johan Hedberg333ae952015-03-17 13:48:47 +02001169 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001170 if (cmd) {
1171 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001172 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001173 }
1174
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001175 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001176}
1177
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001178static void disable_advertising(struct hci_request *req)
1179{
1180 u8 enable = 0x00;
1181
1182 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1183}
1184
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001185static void enable_advertising(struct hci_request *req)
1186{
1187 struct hci_dev *hdev = req->hdev;
1188 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001189 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001190 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001191
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001192 if (hci_conn_num(hdev, LE_LINK) > 0)
1193 return;
1194
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001195 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001196 disable_advertising(req);
1197
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001198 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001199 * hci_update_random_address knows that it's safe to go ahead
1200 * and write a new random address. The flag will be set back on
1201 * as soon as the SET_ADV_ENABLE HCI command completes.
1202 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001203 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001204
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001205 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001206 connectable = true;
1207 else
1208 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001209
Johan Hedberga4858cb2014-02-25 19:56:31 +02001210 /* Set require_privacy to true only when non-connectable
1211 * advertising is used. In that case it is fine to use a
1212 * non-resolvable private address.
1213 */
1214 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001215 return;
1216
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001217 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001218 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1219 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001220 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001221 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001222 cp.channel_map = hdev->le_adv_channel_map;
1223
1224 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1225
1226 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1227}
1228
Johan Hedberg7d785252011-12-15 00:47:39 +02001229static void service_cache_off(struct work_struct *work)
1230{
1231 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001232 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001233 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001234
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001235 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001236 return;
1237
Johan Hedberg890ea892013-03-15 17:06:52 -05001238 hci_req_init(&req, hdev);
1239
Johan Hedberg7d785252011-12-15 00:47:39 +02001240 hci_dev_lock(hdev);
1241
Johan Hedberg890ea892013-03-15 17:06:52 -05001242 update_eir(&req);
1243 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001244
1245 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001246
1247 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001248}
1249
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001250static void rpa_expired(struct work_struct *work)
1251{
1252 struct hci_dev *hdev = container_of(work, struct hci_dev,
1253 rpa_expired.work);
1254 struct hci_request req;
1255
1256 BT_DBG("");
1257
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001258 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001259
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001260 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001261 return;
1262
1263 /* The generation of a new RPA and programming it into the
1264 * controller happens in the enable_advertising() function.
1265 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001266 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001267 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001268 hci_req_run(&req, NULL);
1269}
1270
Johan Hedberg6a919082012-02-28 06:17:26 +02001271static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001272{
Marcel Holtmann238be782015-03-13 02:11:06 -07001273 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001274 return;
1275
Johan Hedberg4f87da82012-03-02 19:55:56 +02001276 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001277 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001278
Johan Hedberg4f87da82012-03-02 19:55:56 +02001279 /* Non-mgmt controlled devices get this bit set
1280 * implicitly so that pairing works for them, however
1281 * for mgmt we require user-space to explicitly enable
1282 * it
1283 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001284 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001285}
1286
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001287static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001288 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001289{
1290 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001291
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001292 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001293
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001294 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001295
Johan Hedberg03811012010-12-08 00:21:06 +02001296 memset(&rp, 0, sizeof(rp));
1297
Johan Hedberg03811012010-12-08 00:21:06 +02001298 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001299
1300 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001301 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001302
1303 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1304 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1305
1306 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001307
1308 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001309 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001310
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001311 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001312
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001313 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1314 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001315}
1316
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001317static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001318{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001319 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001320
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001321 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1322 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001323}
1324
Marcel Holtmann1904a852015-01-11 13:50:44 -08001325static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001326{
1327 BT_DBG("%s status 0x%02x", hdev->name, status);
1328
Johan Hedberga3172b72014-02-28 09:33:44 +02001329 if (hci_conn_count(hdev) == 0) {
1330 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001331 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001332 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001333}
1334
Johan Hedberg23a48092014-07-08 16:05:06 +03001335static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001336{
1337 struct hci_dev *hdev = req->hdev;
1338 struct hci_cp_remote_name_req_cancel cp;
1339 struct inquiry_entry *e;
1340
1341 switch (hdev->discovery.state) {
1342 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001343 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001344 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001345
1346 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001347 cancel_delayed_work(&hdev->le_scan_disable);
1348 hci_req_add_le_scan_disable(req);
1349 }
1350
Johan Hedberg23a48092014-07-08 16:05:06 +03001351 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001352
1353 case DISCOVERY_RESOLVING:
1354 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1355 NAME_PENDING);
1356 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001357 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001358
1359 bacpy(&cp.bdaddr, &e->data.bdaddr);
1360 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1361 &cp);
1362
Johan Hedberg23a48092014-07-08 16:05:06 +03001363 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001364
1365 default:
1366 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001367 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001368 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001369 return true;
1370 }
1371
Johan Hedberg21a60d32014-06-10 14:05:58 +03001372 break;
1373 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001374
1375 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001376}
1377
Arman Uguray912098a2015-03-23 15:57:15 -07001378static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1379 u8 instance)
1380{
1381 struct mgmt_ev_advertising_added ev;
1382
1383 ev.instance = instance;
1384
1385 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1386}
1387
1388static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1389 u8 instance)
1390{
1391 struct mgmt_ev_advertising_removed ev;
1392
1393 ev.instance = instance;
1394
1395 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1396}
1397
1398static void clear_adv_instance(struct hci_dev *hdev)
1399{
1400 struct hci_request req;
1401
1402 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1403 return;
1404
1405 if (hdev->adv_instance.timeout)
1406 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
1407
1408 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1409 advertising_removed(NULL, hdev, 1);
1410 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1411
1412 if (!hdev_is_powered(hdev) ||
1413 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1414 return;
1415
1416 hci_req_init(&req, hdev);
1417 disable_advertising(&req);
1418 hci_req_run(&req, NULL);
1419}
1420
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421static int clean_up_hci_state(struct hci_dev *hdev)
1422{
1423 struct hci_request req;
1424 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001425 bool discov_stopped;
1426 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001427
1428 hci_req_init(&req, hdev);
1429
1430 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1431 test_bit(HCI_PSCAN, &hdev->flags)) {
1432 u8 scan = 0x00;
1433 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1434 }
1435
Arman Uguray912098a2015-03-23 15:57:15 -07001436 if (hdev->adv_instance.timeout)
1437 clear_adv_instance(hdev);
1438
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001439 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001440 disable_advertising(&req);
1441
Johan Hedberg23a48092014-07-08 16:05:06 +03001442 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001443
1444 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1445 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001446 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001447
Johan Hedbergc9910d02014-02-27 14:35:12 +02001448 switch (conn->state) {
1449 case BT_CONNECTED:
1450 case BT_CONFIG:
1451 dc.handle = cpu_to_le16(conn->handle);
1452 dc.reason = 0x15; /* Terminated due to Power Off */
1453 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1454 break;
1455 case BT_CONNECT:
1456 if (conn->type == LE_LINK)
1457 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1458 0, NULL);
1459 else if (conn->type == ACL_LINK)
1460 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1461 6, &conn->dst);
1462 break;
1463 case BT_CONNECT2:
1464 bacpy(&rej.bdaddr, &conn->dst);
1465 rej.reason = 0x15; /* Terminated due to Power Off */
1466 if (conn->type == ACL_LINK)
1467 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1468 sizeof(rej), &rej);
1469 else if (conn->type == SCO_LINK)
1470 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1471 sizeof(rej), &rej);
1472 break;
1473 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001474 }
1475
Johan Hedberg23a48092014-07-08 16:05:06 +03001476 err = hci_req_run(&req, clean_up_hci_complete);
1477 if (!err && discov_stopped)
1478 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1479
1480 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001481}
1482
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001483static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001484 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001485{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001486 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001487 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001488 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001489
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001490 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001491
Johan Hedberga7e80f22013-01-09 16:05:19 +02001492 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001493 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1494 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001495
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001496 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001497
Johan Hedberg333ae952015-03-17 13:48:47 +02001498 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001499 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1500 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001501 goto failed;
1502 }
1503
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001504 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001505 cancel_delayed_work(&hdev->power_off);
1506
1507 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001508 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1509 data, len);
1510 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001511 goto failed;
1512 }
1513 }
1514
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001515 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001516 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001517 goto failed;
1518 }
1519
Johan Hedberg03811012010-12-08 00:21:06 +02001520 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1521 if (!cmd) {
1522 err = -ENOMEM;
1523 goto failed;
1524 }
1525
Johan Hedberg8b064a32014-02-24 14:52:22 +02001526 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001527 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001528 err = 0;
1529 } else {
1530 /* Disconnect connections, stop scans, etc */
1531 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001532 if (!err)
1533 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1534 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001535
Johan Hedberg8b064a32014-02-24 14:52:22 +02001536 /* ENODATA means there were no HCI commands queued */
1537 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001538 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001539 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1540 err = 0;
1541 }
1542 }
Johan Hedberg03811012010-12-08 00:21:06 +02001543
1544failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001545 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001546 return err;
1547}
1548
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001549static int new_settings(struct hci_dev *hdev, struct sock *skip)
1550{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001551 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001552
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001553 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1554 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001555}
1556
Johan Hedberg91a668b2014-07-09 13:28:26 +03001557int mgmt_new_settings(struct hci_dev *hdev)
1558{
1559 return new_settings(hdev, NULL);
1560}
1561
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001562struct cmd_lookup {
1563 struct sock *sk;
1564 struct hci_dev *hdev;
1565 u8 mgmt_status;
1566};
1567
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001568static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001569{
1570 struct cmd_lookup *match = data;
1571
1572 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1573
1574 list_del(&cmd->list);
1575
1576 if (match->sk == NULL) {
1577 match->sk = cmd->sk;
1578 sock_hold(match->sk);
1579 }
1580
1581 mgmt_pending_free(cmd);
1582}
1583
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001584static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001585{
1586 u8 *status = data;
1587
Johan Hedberga69e8372015-03-06 21:08:53 +02001588 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001589 mgmt_pending_remove(cmd);
1590}
1591
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001592static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001593{
1594 if (cmd->cmd_complete) {
1595 u8 *status = data;
1596
1597 cmd->cmd_complete(cmd, *status);
1598 mgmt_pending_remove(cmd);
1599
1600 return;
1601 }
1602
1603 cmd_status_rsp(cmd, data);
1604}
1605
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001606static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001607{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001608 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1609 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001610}
1611
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001612static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001613{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001614 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1615 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001616}
1617
Johan Hedberge6fe7982013-10-02 15:45:22 +03001618static u8 mgmt_bredr_support(struct hci_dev *hdev)
1619{
1620 if (!lmp_bredr_capable(hdev))
1621 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001622 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001623 return MGMT_STATUS_REJECTED;
1624 else
1625 return MGMT_STATUS_SUCCESS;
1626}
1627
1628static u8 mgmt_le_support(struct hci_dev *hdev)
1629{
1630 if (!lmp_le_capable(hdev))
1631 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001632 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001633 return MGMT_STATUS_REJECTED;
1634 else
1635 return MGMT_STATUS_SUCCESS;
1636}
1637
Marcel Holtmann1904a852015-01-11 13:50:44 -08001638static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1639 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001640{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001641 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001642 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001643 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001644 bool changed;
1645
1646 BT_DBG("status 0x%02x", status);
1647
1648 hci_dev_lock(hdev);
1649
Johan Hedberg333ae952015-03-17 13:48:47 +02001650 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001651 if (!cmd)
1652 goto unlock;
1653
1654 if (status) {
1655 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001656 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001657 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001658 goto remove_cmd;
1659 }
1660
1661 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001662 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001663 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001664
1665 if (hdev->discov_timeout > 0) {
1666 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1667 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1668 to);
1669 }
1670 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001671 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001672 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001673
1674 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1675
1676 if (changed)
1677 new_settings(hdev, cmd->sk);
1678
Marcel Holtmann970ba522013-10-15 06:33:57 -07001679 /* When the discoverable mode gets changed, make sure
1680 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001681 * bit correctly set. Also update page scan based on whitelist
1682 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001683 */
1684 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001685 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001686 update_class(&req);
1687 hci_req_run(&req, NULL);
1688
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001689remove_cmd:
1690 mgmt_pending_remove(cmd);
1691
1692unlock:
1693 hci_dev_unlock(hdev);
1694}
1695
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001696static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001697 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001698{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001699 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001700 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001701 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001702 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001703 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001704 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001706 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001707
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001708 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1709 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001710 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1711 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001712
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001713 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001714 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1715 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001716
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001717 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001718
1719 /* Disabling discoverable requires that no timeout is set,
1720 * and enabling limited discoverable requires a timeout.
1721 */
1722 if ((cp->val == 0x00 && timeout > 0) ||
1723 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001724 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1725 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001726
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001727 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001728
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001729 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001730 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1731 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001732 goto failed;
1733 }
1734
Johan Hedberg333ae952015-03-17 13:48:47 +02001735 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1736 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001737 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1738 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001739 goto failed;
1740 }
1741
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001742 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001743 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1744 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001745 goto failed;
1746 }
1747
1748 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001749 bool changed = false;
1750
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001751 /* Setting limited discoverable when powered off is
1752 * not a valid operation since it requires a timeout
1753 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1754 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001755 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001756 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001757 changed = true;
1758 }
1759
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001760 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001761 if (err < 0)
1762 goto failed;
1763
1764 if (changed)
1765 err = new_settings(hdev, sk);
1766
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001767 goto failed;
1768 }
1769
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001770 /* If the current mode is the same, then just update the timeout
1771 * value with the new value. And if only the timeout gets updated,
1772 * then no need for any HCI transactions.
1773 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001774 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1775 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1776 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001777 cancel_delayed_work(&hdev->discov_off);
1778 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001779
Marcel Holtmann36261542013-10-15 08:28:51 -07001780 if (cp->val && hdev->discov_timeout > 0) {
1781 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001782 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001783 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001784 }
1785
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001786 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001787 goto failed;
1788 }
1789
1790 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1791 if (!cmd) {
1792 err = -ENOMEM;
1793 goto failed;
1794 }
1795
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001796 /* Cancel any potential discoverable timeout that might be
1797 * still active and store new timeout value. The arming of
1798 * the timeout happens in the complete handler.
1799 */
1800 cancel_delayed_work(&hdev->discov_off);
1801 hdev->discov_timeout = timeout;
1802
Johan Hedbergb456f872013-10-19 23:38:22 +03001803 /* Limited discoverable mode */
1804 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001805 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001806 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001807 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001808
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001809 hci_req_init(&req, hdev);
1810
Johan Hedberg9a43e252013-10-20 19:00:07 +03001811 /* The procedure for LE-only controllers is much simpler - just
1812 * update the advertising data.
1813 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001814 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001815 goto update_ad;
1816
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001817 scan = SCAN_PAGE;
1818
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001819 if (cp->val) {
1820 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001821
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001822 if (cp->val == 0x02) {
1823 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001824 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001825 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1826 hci_cp.iac_lap[1] = 0x8b;
1827 hci_cp.iac_lap[2] = 0x9e;
1828 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1829 hci_cp.iac_lap[4] = 0x8b;
1830 hci_cp.iac_lap[5] = 0x9e;
1831 } else {
1832 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001833 hci_cp.num_iac = 1;
1834 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1835 hci_cp.iac_lap[1] = 0x8b;
1836 hci_cp.iac_lap[2] = 0x9e;
1837 }
1838
1839 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1840 (hci_cp.num_iac * 3) + 1, &hci_cp);
1841
1842 scan |= SCAN_INQUIRY;
1843 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001844 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001845 }
1846
1847 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001848
Johan Hedberg9a43e252013-10-20 19:00:07 +03001849update_ad:
1850 update_adv_data(&req);
1851
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001852 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001853 if (err < 0)
1854 mgmt_pending_remove(cmd);
1855
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001856failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001857 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001858 return err;
1859}
1860
Johan Hedberg406d7802013-03-15 17:07:09 -05001861static void write_fast_connectable(struct hci_request *req, bool enable)
1862{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001863 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001864 struct hci_cp_write_page_scan_activity acp;
1865 u8 type;
1866
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001867 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001868 return;
1869
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001870 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1871 return;
1872
Johan Hedberg406d7802013-03-15 17:07:09 -05001873 if (enable) {
1874 type = PAGE_SCAN_TYPE_INTERLACED;
1875
1876 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001877 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001878 } else {
1879 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1880
1881 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001882 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001883 }
1884
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001885 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001886
Johan Hedbergbd98b992013-03-15 17:07:13 -05001887 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1888 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1889 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1890 sizeof(acp), &acp);
1891
1892 if (hdev->page_scan_type != type)
1893 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001894}
1895
Marcel Holtmann1904a852015-01-11 13:50:44 -08001896static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1897 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001899 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001900 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001901 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001902
1903 BT_DBG("status 0x%02x", status);
1904
1905 hci_dev_lock(hdev);
1906
Johan Hedberg333ae952015-03-17 13:48:47 +02001907 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001908 if (!cmd)
1909 goto unlock;
1910
Johan Hedberg37438c12013-10-14 16:20:05 +03001911 if (status) {
1912 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001913 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001914 goto remove_cmd;
1915 }
1916
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001917 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001918 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001919 conn_changed = !hci_dev_test_and_set_flag(hdev,
1920 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001921 discov_changed = false;
1922 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001923 conn_changed = hci_dev_test_and_clear_flag(hdev,
1924 HCI_CONNECTABLE);
1925 discov_changed = hci_dev_test_and_clear_flag(hdev,
1926 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001927 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001928
Johan Hedberg2b76f452013-03-15 17:07:04 -05001929 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1930
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001931 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001932 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001933 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001934 if (discov_changed)
1935 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001936 hci_update_background_scan(hdev);
1937 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001938
Johan Hedberg37438c12013-10-14 16:20:05 +03001939remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001940 mgmt_pending_remove(cmd);
1941
1942unlock:
1943 hci_dev_unlock(hdev);
1944}
1945
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001946static int set_connectable_update_settings(struct hci_dev *hdev,
1947 struct sock *sk, u8 val)
1948{
1949 bool changed = false;
1950 int err;
1951
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001952 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001953 changed = true;
1954
1955 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001956 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001957 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001958 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
1959 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001960 }
1961
1962 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1963 if (err < 0)
1964 return err;
1965
Johan Hedberg562064e2014-07-08 16:35:34 +03001966 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001967 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001968 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001969 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001970 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001971
1972 return 0;
1973}
1974
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001975static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001976 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001977{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001978 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001979 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001980 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001981 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001982 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001983
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001984 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001985
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001986 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1987 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001988 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1989 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001990
Johan Hedberga7e80f22013-01-09 16:05:19 +02001991 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001992 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1993 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001994
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001995 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001996
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001997 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001998 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001999 goto failed;
2000 }
2001
Johan Hedberg333ae952015-03-17 13:48:47 +02002002 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2003 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002004 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2005 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002006 goto failed;
2007 }
2008
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002009 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2010 if (!cmd) {
2011 err = -ENOMEM;
2012 goto failed;
2013 }
2014
Johan Hedberg2b76f452013-03-15 17:07:04 -05002015 hci_req_init(&req, hdev);
2016
Johan Hedberg9a43e252013-10-20 19:00:07 +03002017 /* If BR/EDR is not enabled and we disable advertising as a
2018 * by-product of disabling connectable, we need to update the
2019 * advertising flags.
2020 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002021 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002022 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002023 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2024 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002025 }
2026 update_adv_data(&req);
2027 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002028 if (cp->val) {
2029 scan = SCAN_PAGE;
2030 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002031 /* If we don't have any whitelist entries just
2032 * disable all scanning. If there are entries
2033 * and we had both page and inquiry scanning
2034 * enabled then fall back to only page scanning.
2035 * Otherwise no changes are needed.
2036 */
2037 if (list_empty(&hdev->whitelist))
2038 scan = SCAN_DISABLED;
2039 else if (test_bit(HCI_ISCAN, &hdev->flags))
2040 scan = SCAN_PAGE;
2041 else
2042 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002043
2044 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002045 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002046 cancel_delayed_work(&hdev->discov_off);
2047 }
2048
2049 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2050 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002051
Johan Hedberg3bd27242014-07-28 20:53:58 +03002052no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002053 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002054 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002055 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002056
Johan Hedberg2b76f452013-03-15 17:07:04 -05002057 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002058 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002059 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002060 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002061 err = set_connectable_update_settings(hdev, sk,
2062 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002063 goto failed;
2064 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002065
2066failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002067 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002068 return err;
2069}
2070
Johan Hedbergb2939472014-07-30 09:22:23 +03002071static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002072 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002073{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002074 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002075 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002076 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002077
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002078 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002079
Johan Hedberga7e80f22013-01-09 16:05:19 +02002080 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002081 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2082 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002083
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002084 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002085
2086 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002087 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002088 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002089 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002090
Johan Hedbergb2939472014-07-30 09:22:23 +03002091 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002092 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002093 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002094
Marcel Holtmann55594352013-10-06 16:11:57 -07002095 if (changed)
2096 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002097
Marcel Holtmann55594352013-10-06 16:11:57 -07002098unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002099 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002100 return err;
2101}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002102
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002103static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2104 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002105{
2106 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002107 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002108 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002109 int err;
2110
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002111 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002112
Johan Hedberge6fe7982013-10-02 15:45:22 +03002113 status = mgmt_bredr_support(hdev);
2114 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002115 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2116 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002117
Johan Hedberga7e80f22013-01-09 16:05:19 +02002118 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002119 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2120 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002121
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002122 hci_dev_lock(hdev);
2123
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002124 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002125 bool changed = false;
2126
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002127 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002128 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002129 changed = true;
2130 }
2131
2132 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2133 if (err < 0)
2134 goto failed;
2135
2136 if (changed)
2137 err = new_settings(hdev, sk);
2138
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002139 goto failed;
2140 }
2141
Johan Hedberg333ae952015-03-17 13:48:47 +02002142 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002143 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2144 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002145 goto failed;
2146 }
2147
2148 val = !!cp->val;
2149
2150 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2151 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2152 goto failed;
2153 }
2154
2155 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2156 if (!cmd) {
2157 err = -ENOMEM;
2158 goto failed;
2159 }
2160
2161 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2162 if (err < 0) {
2163 mgmt_pending_remove(cmd);
2164 goto failed;
2165 }
2166
2167failed:
2168 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002169 return err;
2170}
2171
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002172static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002173{
2174 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002175 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002176 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002177 int err;
2178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002179 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002180
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002181 status = mgmt_bredr_support(hdev);
2182 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002183 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002184
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002185 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002186 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2187 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002188
Johan Hedberga7e80f22013-01-09 16:05:19 +02002189 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002190 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2191 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002192
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002193 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002194
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002195 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002196 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002197
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002198 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002199 changed = !hci_dev_test_and_set_flag(hdev,
2200 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002201 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002202 changed = hci_dev_test_and_clear_flag(hdev,
2203 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002204 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002205 changed = hci_dev_test_and_clear_flag(hdev,
2206 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002207 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002208 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002209 }
2210
2211 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2212 if (err < 0)
2213 goto failed;
2214
2215 if (changed)
2216 err = new_settings(hdev, sk);
2217
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002218 goto failed;
2219 }
2220
Johan Hedberg333ae952015-03-17 13:48:47 +02002221 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002222 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2223 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002224 goto failed;
2225 }
2226
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002227 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002228 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2229 goto failed;
2230 }
2231
2232 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2233 if (!cmd) {
2234 err = -ENOMEM;
2235 goto failed;
2236 }
2237
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002238 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002239 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2240 sizeof(cp->val), &cp->val);
2241
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002242 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002243 if (err < 0) {
2244 mgmt_pending_remove(cmd);
2245 goto failed;
2246 }
2247
2248failed:
2249 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002250 return err;
2251}
2252
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002253static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002254{
2255 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002256 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002257 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002258 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002259
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002260 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002261
Johan Hedberge6fe7982013-10-02 15:45:22 +03002262 status = mgmt_bredr_support(hdev);
2263 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002264 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002265
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002266 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002267 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2268 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002269
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002270 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002271 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2272 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002273
Johan Hedberga7e80f22013-01-09 16:05:19 +02002274 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002275 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2276 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002277
Marcel Holtmannee392692013-10-01 22:59:23 -07002278 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002279
Johan Hedberg333ae952015-03-17 13:48:47 +02002280 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002281 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2282 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002283 goto unlock;
2284 }
2285
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002286 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002287 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002288 } else {
2289 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002290 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2291 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002292 goto unlock;
2293 }
2294
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002295 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002296 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002297
2298 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2299 if (err < 0)
2300 goto unlock;
2301
2302 if (changed)
2303 err = new_settings(hdev, sk);
2304
2305unlock:
2306 hci_dev_unlock(hdev);
2307 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002308}
2309
Marcel Holtmann1904a852015-01-11 13:50:44 -08002310static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002311{
2312 struct cmd_lookup match = { NULL, hdev };
2313
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302314 hci_dev_lock(hdev);
2315
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002316 if (status) {
2317 u8 mgmt_err = mgmt_status(status);
2318
2319 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2320 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302321 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002322 }
2323
2324 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2325
2326 new_settings(hdev, match.sk);
2327
2328 if (match.sk)
2329 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002330
2331 /* Make sure the controller has a good default for
2332 * advertising data. Restrict the update to when LE
2333 * has actually been enabled. During power on, the
2334 * update in powered_update_hci will take care of it.
2335 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002336 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002337 struct hci_request req;
2338
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002339 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002340 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002341 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002342 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002343 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002344 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302345
2346unlock:
2347 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002348}
2349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002350static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002351{
2352 struct mgmt_mode *cp = data;
2353 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002354 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002355 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002356 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002357 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002358
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002359 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002360
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002361 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002362 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2363 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002364
Johan Hedberga7e80f22013-01-09 16:05:19 +02002365 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002366 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2367 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002368
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002369 /* Bluetooth single mode LE only controllers or dual-mode
2370 * controllers configured as LE only devices, do not allow
2371 * switching LE off. These have either LE enabled explicitly
2372 * or BR/EDR has been previously switched off.
2373 *
2374 * When trying to enable an already enabled LE, then gracefully
2375 * send a positive response. Trying to disable it however will
2376 * result into rejection.
2377 */
2378 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2379 if (cp->val == 0x01)
2380 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2381
Johan Hedberga69e8372015-03-06 21:08:53 +02002382 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2383 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002384 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002385
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002386 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002387
2388 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002389 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002390
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002391 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002392 bool changed = false;
2393
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002394 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002395 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002396 changed = true;
2397 }
2398
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002399 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002400 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002401 changed = true;
2402 }
2403
Johan Hedberg06199cf2012-02-22 16:37:11 +02002404 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2405 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002406 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002407
2408 if (changed)
2409 err = new_settings(hdev, sk);
2410
Johan Hedberg1de028c2012-02-29 19:55:35 -08002411 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002412 }
2413
Johan Hedberg333ae952015-03-17 13:48:47 +02002414 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2415 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002416 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2417 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002418 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002419 }
2420
2421 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2422 if (!cmd) {
2423 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002424 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002425 }
2426
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002427 hci_req_init(&req, hdev);
2428
Johan Hedberg06199cf2012-02-22 16:37:11 +02002429 memset(&hci_cp, 0, sizeof(hci_cp));
2430
2431 if (val) {
2432 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002433 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002434 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002435 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002436 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002437 }
2438
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002439 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2440 &hci_cp);
2441
2442 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302443 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002444 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002445
Johan Hedberg1de028c2012-02-29 19:55:35 -08002446unlock:
2447 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002448 return err;
2449}
2450
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002451/* This is a helper function to test for pending mgmt commands that can
2452 * cause CoD or EIR HCI commands. We can only allow one such pending
2453 * mgmt command at a time since otherwise we cannot easily track what
2454 * the current values are, will be, and based on that calculate if a new
2455 * HCI command needs to be sent and if yes with what value.
2456 */
2457static bool pending_eir_or_class(struct hci_dev *hdev)
2458{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002459 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002460
2461 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2462 switch (cmd->opcode) {
2463 case MGMT_OP_ADD_UUID:
2464 case MGMT_OP_REMOVE_UUID:
2465 case MGMT_OP_SET_DEV_CLASS:
2466 case MGMT_OP_SET_POWERED:
2467 return true;
2468 }
2469 }
2470
2471 return false;
2472}
2473
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002474static const u8 bluetooth_base_uuid[] = {
2475 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2476 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2477};
2478
2479static u8 get_uuid_size(const u8 *uuid)
2480{
2481 u32 val;
2482
2483 if (memcmp(uuid, bluetooth_base_uuid, 12))
2484 return 128;
2485
2486 val = get_unaligned_le32(&uuid[12]);
2487 if (val > 0xffff)
2488 return 32;
2489
2490 return 16;
2491}
2492
Johan Hedberg92da6092013-03-15 17:06:55 -05002493static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2494{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002495 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002496
2497 hci_dev_lock(hdev);
2498
Johan Hedberg333ae952015-03-17 13:48:47 +02002499 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002500 if (!cmd)
2501 goto unlock;
2502
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002503 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2504 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002505
2506 mgmt_pending_remove(cmd);
2507
2508unlock:
2509 hci_dev_unlock(hdev);
2510}
2511
Marcel Holtmann1904a852015-01-11 13:50:44 -08002512static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002513{
2514 BT_DBG("status 0x%02x", status);
2515
2516 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2517}
2518
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002519static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002521 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002522 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002523 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002524 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002525 int err;
2526
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002527 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002528
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002529 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002530
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002531 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002532 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2533 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002534 goto failed;
2535 }
2536
Andre Guedes92c4c202012-06-07 19:05:44 -03002537 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002538 if (!uuid) {
2539 err = -ENOMEM;
2540 goto failed;
2541 }
2542
2543 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002544 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002545 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546
Johan Hedbergde66aa62013-01-27 00:31:27 +02002547 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002548
Johan Hedberg890ea892013-03-15 17:06:52 -05002549 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002550
Johan Hedberg890ea892013-03-15 17:06:52 -05002551 update_class(&req);
2552 update_eir(&req);
2553
Johan Hedberg92da6092013-03-15 17:06:55 -05002554 err = hci_req_run(&req, add_uuid_complete);
2555 if (err < 0) {
2556 if (err != -ENODATA)
2557 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002558
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002559 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2560 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002561 goto failed;
2562 }
2563
2564 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002565 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002566 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002567 goto failed;
2568 }
2569
2570 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002571
2572failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002574 return err;
2575}
2576
Johan Hedberg24b78d02012-02-23 23:24:30 +02002577static bool enable_service_cache(struct hci_dev *hdev)
2578{
2579 if (!hdev_is_powered(hdev))
2580 return false;
2581
Marcel Holtmann238be782015-03-13 02:11:06 -07002582 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002583 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2584 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002585 return true;
2586 }
2587
2588 return false;
2589}
2590
Marcel Holtmann1904a852015-01-11 13:50:44 -08002591static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002592{
2593 BT_DBG("status 0x%02x", status);
2594
2595 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2596}
2597
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002598static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002599 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002600{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002601 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002602 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002603 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002604 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 -05002605 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002606 int err, found;
2607
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002608 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002609
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002610 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002611
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002612 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002613 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2614 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002615 goto unlock;
2616 }
2617
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002618 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002619 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002620
Johan Hedberg24b78d02012-02-23 23:24:30 +02002621 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002622 err = mgmt_cmd_complete(sk, hdev->id,
2623 MGMT_OP_REMOVE_UUID,
2624 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002625 goto unlock;
2626 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002627
Johan Hedberg9246a862012-02-23 21:33:16 +02002628 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002629 }
2630
2631 found = 0;
2632
Johan Hedberg056341c2013-01-27 00:31:30 +02002633 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002634 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2635 continue;
2636
2637 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002638 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002639 found++;
2640 }
2641
2642 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002643 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2644 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002645 goto unlock;
2646 }
2647
Johan Hedberg9246a862012-02-23 21:33:16 +02002648update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002649 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002650
Johan Hedberg890ea892013-03-15 17:06:52 -05002651 update_class(&req);
2652 update_eir(&req);
2653
Johan Hedberg92da6092013-03-15 17:06:55 -05002654 err = hci_req_run(&req, remove_uuid_complete);
2655 if (err < 0) {
2656 if (err != -ENODATA)
2657 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002658
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002659 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2660 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002661 goto unlock;
2662 }
2663
2664 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002665 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002666 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002667 goto unlock;
2668 }
2669
2670 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002671
2672unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002673 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002674 return err;
2675}
2676
Marcel Holtmann1904a852015-01-11 13:50:44 -08002677static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002678{
2679 BT_DBG("status 0x%02x", status);
2680
2681 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2682}
2683
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002684static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002685 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002686{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002687 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002688 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002689 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002690 int err;
2691
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002692 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002693
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002694 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002695 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2696 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002697
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002698 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002699
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002700 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002701 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2702 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002703 goto unlock;
2704 }
2705
2706 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002707 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2708 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002709 goto unlock;
2710 }
2711
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002712 hdev->major_class = cp->major;
2713 hdev->minor_class = cp->minor;
2714
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002715 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002716 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2717 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002718 goto unlock;
2719 }
2720
Johan Hedberg890ea892013-03-15 17:06:52 -05002721 hci_req_init(&req, hdev);
2722
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002723 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002724 hci_dev_unlock(hdev);
2725 cancel_delayed_work_sync(&hdev->service_cache);
2726 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002727 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002728 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002729
Johan Hedberg890ea892013-03-15 17:06:52 -05002730 update_class(&req);
2731
Johan Hedberg92da6092013-03-15 17:06:55 -05002732 err = hci_req_run(&req, set_class_complete);
2733 if (err < 0) {
2734 if (err != -ENODATA)
2735 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002736
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002737 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2738 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002739 goto unlock;
2740 }
2741
2742 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002743 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002744 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002745 goto unlock;
2746 }
2747
2748 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002749
Johan Hedbergb5235a62012-02-21 14:32:24 +02002750unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002751 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002752 return err;
2753}
2754
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002756 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002757{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002758 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002759 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2760 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002761 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002762 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002763 int i;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002764
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002765 BT_DBG("request for %s", hdev->name);
2766
2767 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002768 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2769 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002770
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002771 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002772 if (key_count > max_key_count) {
2773 BT_ERR("load_link_keys: too big key_count value %u",
2774 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002775 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2776 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002777 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002778
Johan Hedberg86742e12011-11-07 23:13:38 +02002779 expected_len = sizeof(*cp) + key_count *
2780 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002781 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002782 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002783 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002784 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2785 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002786 }
2787
Johan Hedberg4ae14302013-01-20 14:27:13 +02002788 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002789 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2790 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002791
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002792 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002793 key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002794
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002795 for (i = 0; i < key_count; i++) {
2796 struct mgmt_link_key_info *key = &cp->keys[i];
2797
Marcel Holtmann8e991132014-01-10 02:07:25 -08002798 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002799 return mgmt_cmd_status(sk, hdev->id,
2800 MGMT_OP_LOAD_LINK_KEYS,
2801 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002802 }
2803
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002804 hci_dev_lock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002805
2806 hci_link_keys_clear(hdev);
2807
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002808 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002809 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002810 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002811 changed = hci_dev_test_and_clear_flag(hdev,
2812 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002813
2814 if (changed)
2815 new_settings(hdev, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002816
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002817 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002818 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002819
Johan Hedberg58e92932014-06-24 14:00:26 +03002820 /* Always ignore debug keys and require a new pairing if
2821 * the user wants to use them.
2822 */
2823 if (key->type == HCI_LK_DEBUG_COMBINATION)
2824 continue;
2825
Johan Hedberg7652ff62014-06-24 13:15:49 +03002826 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2827 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002828 }
2829
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002830 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002831
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002832 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002833
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002834 return 0;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002835}
2836
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002837static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002838 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002839{
2840 struct mgmt_ev_device_unpaired ev;
2841
2842 bacpy(&ev.addr.bdaddr, bdaddr);
2843 ev.addr.type = addr_type;
2844
2845 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002846 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002847}
2848
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002849static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002850 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002851{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002852 struct mgmt_cp_unpair_device *cp = data;
2853 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002854 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002855 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002856 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002857 int err;
2858
Johan Hedberga8a1d192011-11-10 15:54:38 +02002859 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002860 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2861 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002862
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002863 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002864 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2865 MGMT_STATUS_INVALID_PARAMS,
2866 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002867
Johan Hedberg118da702013-01-20 14:27:20 +02002868 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002869 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2870 MGMT_STATUS_INVALID_PARAMS,
2871 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002872
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002873 hci_dev_lock(hdev);
2874
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002875 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002876 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2877 MGMT_STATUS_NOT_POWERED, &rp,
2878 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002879 goto unlock;
2880 }
2881
Johan Hedberge0b2b272014-02-18 17:14:31 +02002882 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002883 /* If disconnection is requested, then look up the
2884 * connection. If the remote device is connected, it
2885 * will be later used to terminate the link.
2886 *
2887 * Setting it to NULL explicitly will cause no
2888 * termination of the link.
2889 */
2890 if (cp->disconnect)
2891 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2892 &cp->addr.bdaddr);
2893 else
2894 conn = NULL;
2895
Johan Hedberg124f6e32012-02-09 13:50:12 +02002896 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002897 } else {
2898 u8 addr_type;
2899
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002900 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2901 &cp->addr.bdaddr);
2902 if (conn) {
2903 /* Defer clearing up the connection parameters
2904 * until closing to give a chance of keeping
2905 * them if a repairing happens.
2906 */
2907 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2908
2909 /* If disconnection is not requested, then
2910 * clear the connection variable so that the
2911 * link is not terminated.
2912 */
2913 if (!cp->disconnect)
2914 conn = NULL;
2915 }
2916
Johan Hedberge0b2b272014-02-18 17:14:31 +02002917 if (cp->addr.type == BDADDR_LE_PUBLIC)
2918 addr_type = ADDR_LE_DEV_PUBLIC;
2919 else
2920 addr_type = ADDR_LE_DEV_RANDOM;
2921
Johan Hedberga7ec7332014-02-18 17:14:35 +02002922 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2923
Johan Hedberge0b2b272014-02-18 17:14:31 +02002924 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2925 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002926
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002927 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002928 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2929 MGMT_STATUS_NOT_PAIRED, &rp,
2930 sizeof(rp));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002931 goto unlock;
2932 }
2933
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002934 /* If the connection variable is set, then termination of the
2935 * link is requested.
2936 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002937 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002938 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2939 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002940 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002941 goto unlock;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002942 }
2943
Johan Hedberg124f6e32012-02-09 13:50:12 +02002944 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002945 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002946 if (!cmd) {
2947 err = -ENOMEM;
2948 goto unlock;
2949 }
2950
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002951 cmd->cmd_complete = addr_cmd_complete;
2952
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002953 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002954 dc.reason = 0x13; /* Remote User Terminated Connection */
2955 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2956 if (err < 0)
2957 mgmt_pending_remove(cmd);
2958
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002959unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002960 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002961 return err;
2962}
2963
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002964static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002965 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002966{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002967 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002968 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002969 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002970 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002971 int err;
2972
2973 BT_DBG("");
2974
Johan Hedberg06a63b12013-01-20 14:27:21 +02002975 memset(&rp, 0, sizeof(rp));
2976 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2977 rp.addr.type = cp->addr.type;
2978
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002979 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002980 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2981 MGMT_STATUS_INVALID_PARAMS,
2982 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002983
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002984 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002985
2986 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002987 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2988 MGMT_STATUS_NOT_POWERED, &rp,
2989 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002990 goto failed;
2991 }
2992
Johan Hedberg333ae952015-03-17 13:48:47 +02002993 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002994 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2995 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002996 goto failed;
2997 }
2998
Andre Guedes591f47f2012-04-24 21:02:49 -03002999 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003000 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3001 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003002 else
3003 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003004
Vishal Agarwalf9607272012-06-13 05:32:43 +05303005 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003006 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3007 MGMT_STATUS_NOT_CONNECTED, &rp,
3008 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003009 goto failed;
3010 }
3011
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003012 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003013 if (!cmd) {
3014 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003015 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003016 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003017
Johan Hedbergf5818c22014-12-05 13:36:02 +02003018 cmd->cmd_complete = generic_cmd_complete;
3019
Johan Hedberge3f2f922014-08-18 20:33:33 +03003020 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003021 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003022 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003023
3024failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003025 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003026 return err;
3027}
3028
Andre Guedes57c14772012-04-24 21:02:50 -03003029static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003030{
3031 switch (link_type) {
3032 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003033 switch (addr_type) {
3034 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003035 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003036
Johan Hedberg48264f02011-11-09 13:58:58 +02003037 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003038 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003039 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003040 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003041
Johan Hedberg4c659c32011-11-07 23:13:39 +02003042 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003043 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003044 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003045 }
3046}
3047
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003048static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3049 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003050{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003051 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003052 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003053 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003054 int err;
3055 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003056
3057 BT_DBG("");
3058
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003059 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003060
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003061 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003062 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3063 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003064 goto unlock;
3065 }
3066
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003067 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003068 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3069 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003070 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003071 }
3072
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003073 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003074 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003075 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003076 err = -ENOMEM;
3077 goto unlock;
3078 }
3079
Johan Hedberg2784eb42011-01-21 13:56:35 +02003080 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003081 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003082 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3083 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003084 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003085 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003086 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003087 continue;
3088 i++;
3089 }
3090
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003091 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003092
Johan Hedberg4c659c32011-11-07 23:13:39 +02003093 /* Recalculate length in case of filtered SCO connections, etc */
3094 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003095
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003096 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3097 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003098
Johan Hedberga38528f2011-01-22 06:46:43 +02003099 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003100
3101unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003102 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003103 return err;
3104}
3105
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003106static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003107 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003108{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003109 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003110 int err;
3111
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003112 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003113 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003114 if (!cmd)
3115 return -ENOMEM;
3116
Johan Hedbergd8457692012-02-17 14:24:57 +02003117 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003118 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003119 if (err < 0)
3120 mgmt_pending_remove(cmd);
3121
3122 return err;
3123}
3124
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003125static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003126 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003127{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003128 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003129 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003130 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003131 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003132 int err;
3133
3134 BT_DBG("");
3135
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003136 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003137
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003138 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003139 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3140 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003141 goto failed;
3142 }
3143
Johan Hedbergd8457692012-02-17 14:24:57 +02003144 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003145 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003146 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3147 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003148 goto failed;
3149 }
3150
3151 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003152 struct mgmt_cp_pin_code_neg_reply ncp;
3153
3154 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003155
3156 BT_ERR("PIN code is not 16 bytes long");
3157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003158 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003159 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003160 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3161 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003162
3163 goto failed;
3164 }
3165
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003166 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003167 if (!cmd) {
3168 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003169 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003170 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003171
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003172 cmd->cmd_complete = addr_cmd_complete;
3173
Johan Hedbergd8457692012-02-17 14:24:57 +02003174 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003175 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003176 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003177
3178 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3179 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003180 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003181
3182failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003183 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003184 return err;
3185}
3186
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003187static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3188 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003189{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003190 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003191
3192 BT_DBG("");
3193
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003194 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003195 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3196 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003197
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003198 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003199
3200 hdev->io_capability = cp->io_capability;
3201
3202 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003203 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003204
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003205 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003206
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003207 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3208 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003209}
3210
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003211static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003212{
3213 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003214 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003215
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003216 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003217 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3218 continue;
3219
Johan Hedberge9a416b2011-02-19 12:05:56 -03003220 if (cmd->user_data != conn)
3221 continue;
3222
3223 return cmd;
3224 }
3225
3226 return NULL;
3227}
3228
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003229static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003230{
3231 struct mgmt_rp_pair_device rp;
3232 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003233 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003234
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003235 bacpy(&rp.addr.bdaddr, &conn->dst);
3236 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003237
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003238 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3239 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003240
3241 /* So we don't get further callbacks for this connection */
3242 conn->connect_cfm_cb = NULL;
3243 conn->security_cfm_cb = NULL;
3244 conn->disconn_cfm_cb = NULL;
3245
David Herrmann76a68ba2013-04-06 20:28:37 +02003246 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003247
3248 /* The device is paired so there is no need to remove
3249 * its connection parameters anymore.
3250 */
3251 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003252
3253 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003254
3255 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003256}
3257
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003258void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3259{
3260 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003261 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003262
3263 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003264 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003265 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003266 mgmt_pending_remove(cmd);
3267 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003268}
3269
Johan Hedberge9a416b2011-02-19 12:05:56 -03003270static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3271{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003272 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003273
3274 BT_DBG("status %u", status);
3275
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003276 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003277 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003278 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003279 return;
3280 }
3281
3282 cmd->cmd_complete(cmd, mgmt_status(status));
3283 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003284}
3285
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003286static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303287{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003288 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303289
3290 BT_DBG("status %u", status);
3291
3292 if (!status)
3293 return;
3294
3295 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003296 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303297 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003298 return;
3299 }
3300
3301 cmd->cmd_complete(cmd, mgmt_status(status));
3302 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303303}
3304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003306 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003307{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003308 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003309 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003310 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003311 u8 sec_level, auth_type;
3312 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003313 int err;
3314
3315 BT_DBG("");
3316
Szymon Jancf950a30e2013-01-18 12:48:07 +01003317 memset(&rp, 0, sizeof(rp));
3318 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3319 rp.addr.type = cp->addr.type;
3320
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003321 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003322 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3323 MGMT_STATUS_INVALID_PARAMS,
3324 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003325
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003326 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003327 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3328 MGMT_STATUS_INVALID_PARAMS,
3329 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003330
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003331 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003332
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003333 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003334 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3335 MGMT_STATUS_NOT_POWERED, &rp,
3336 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003337 goto unlock;
3338 }
3339
Johan Hedberg55e76b32015-03-10 22:34:40 +02003340 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3341 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3342 MGMT_STATUS_ALREADY_PAIRED, &rp,
3343 sizeof(rp));
3344 goto unlock;
3345 }
3346
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003347 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003348 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003349
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003350 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003351 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3352 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003353 } else {
3354 u8 addr_type;
3355
3356 /* Convert from L2CAP channel address type to HCI address type
3357 */
3358 if (cp->addr.type == BDADDR_LE_PUBLIC)
3359 addr_type = ADDR_LE_DEV_PUBLIC;
3360 else
3361 addr_type = ADDR_LE_DEV_RANDOM;
3362
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003363 /* When pairing a new device, it is expected to remember
3364 * this device for future connections. Adding the connection
3365 * parameter information ahead of time allows tracking
3366 * of the slave preferred values and will speed up any
3367 * further connection establishment.
3368 *
3369 * If connection parameters already exist, then they
3370 * will be kept and this function does nothing.
3371 */
3372 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3373
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003374 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003375 sec_level, HCI_LE_CONN_TIMEOUT,
3376 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003377 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003378
Ville Tervo30e76272011-02-22 16:10:53 -03003379 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003380 int status;
3381
3382 if (PTR_ERR(conn) == -EBUSY)
3383 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003384 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3385 status = MGMT_STATUS_NOT_SUPPORTED;
3386 else if (PTR_ERR(conn) == -ECONNREFUSED)
3387 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003388 else
3389 status = MGMT_STATUS_CONNECT_FAILED;
3390
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003391 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3392 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003393 goto unlock;
3394 }
3395
3396 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003397 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003398 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3399 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003400 goto unlock;
3401 }
3402
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003403 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003404 if (!cmd) {
3405 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003406 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003407 goto unlock;
3408 }
3409
Johan Hedberg04ab2742014-12-05 13:36:04 +02003410 cmd->cmd_complete = pairing_complete;
3411
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003412 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003413 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003414 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003415 conn->security_cfm_cb = pairing_complete_cb;
3416 conn->disconn_cfm_cb = pairing_complete_cb;
3417 } else {
3418 conn->connect_cfm_cb = le_pairing_complete_cb;
3419 conn->security_cfm_cb = le_pairing_complete_cb;
3420 conn->disconn_cfm_cb = le_pairing_complete_cb;
3421 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003422
Johan Hedberge9a416b2011-02-19 12:05:56 -03003423 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003424 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003425
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003426 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003427 hci_conn_security(conn, sec_level, auth_type, true)) {
3428 cmd->cmd_complete(cmd, 0);
3429 mgmt_pending_remove(cmd);
3430 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003431
3432 err = 0;
3433
3434unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003435 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003436 return err;
3437}
3438
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003439static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3440 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003441{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003442 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003443 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003444 struct hci_conn *conn;
3445 int err;
3446
3447 BT_DBG("");
3448
Johan Hedberg28424702012-02-02 04:02:29 +02003449 hci_dev_lock(hdev);
3450
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003451 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003452 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3453 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003454 goto unlock;
3455 }
3456
Johan Hedberg333ae952015-03-17 13:48:47 +02003457 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003458 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003459 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3460 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003461 goto unlock;
3462 }
3463
3464 conn = cmd->user_data;
3465
3466 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003467 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3468 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003469 goto unlock;
3470 }
3471
Johan Hedberga511b352014-12-11 21:45:45 +02003472 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3473 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003474
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003475 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3476 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003477unlock:
3478 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003479 return err;
3480}
3481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003483 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003485{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003486 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003487 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003488 int err;
3489
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003490 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003491
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003492 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003493 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3494 MGMT_STATUS_NOT_POWERED, addr,
3495 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003496 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003497 }
3498
Johan Hedberg1707c602013-03-15 17:07:15 -05003499 if (addr->type == BDADDR_BREDR)
3500 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003501 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003502 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003503
Johan Hedberg272d90d2012-02-09 15:26:12 +02003504 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003505 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3506 MGMT_STATUS_NOT_CONNECTED, addr,
3507 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003508 goto done;
3509 }
3510
Johan Hedberg1707c602013-03-15 17:07:15 -05003511 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003512 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003513 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003514 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3515 MGMT_STATUS_SUCCESS, addr,
3516 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003517 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003518 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3519 MGMT_STATUS_FAILED, addr,
3520 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003521
Brian Gix47c15e22011-11-16 13:53:14 -08003522 goto done;
3523 }
3524
Johan Hedberg1707c602013-03-15 17:07:15 -05003525 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003526 if (!cmd) {
3527 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003528 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003529 }
3530
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003531 cmd->cmd_complete = addr_cmd_complete;
3532
Brian Gix0df4c182011-11-16 13:53:13 -08003533 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003534 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3535 struct hci_cp_user_passkey_reply cp;
3536
Johan Hedberg1707c602013-03-15 17:07:15 -05003537 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003538 cp.passkey = passkey;
3539 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3540 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003541 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3542 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003543
Johan Hedberga664b5b2011-02-19 12:06:02 -03003544 if (err < 0)
3545 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003546
Brian Gix0df4c182011-11-16 13:53:13 -08003547done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003548 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003549 return err;
3550}
3551
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303552static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3553 void *data, u16 len)
3554{
3555 struct mgmt_cp_pin_code_neg_reply *cp = data;
3556
3557 BT_DBG("");
3558
Johan Hedberg1707c602013-03-15 17:07:15 -05003559 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303560 MGMT_OP_PIN_CODE_NEG_REPLY,
3561 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3562}
3563
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003564static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3565 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003566{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003567 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003568
3569 BT_DBG("");
3570
3571 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003572 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3573 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003574
Johan Hedberg1707c602013-03-15 17:07:15 -05003575 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003576 MGMT_OP_USER_CONFIRM_REPLY,
3577 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003578}
3579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003580static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003581 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003582{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003583 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003584
3585 BT_DBG("");
3586
Johan Hedberg1707c602013-03-15 17:07:15 -05003587 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003588 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3589 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003590}
3591
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003592static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3593 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003594{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003595 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003596
3597 BT_DBG("");
3598
Johan Hedberg1707c602013-03-15 17:07:15 -05003599 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003600 MGMT_OP_USER_PASSKEY_REPLY,
3601 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003602}
3603
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003604static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003605 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003606{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003607 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003608
3609 BT_DBG("");
3610
Johan Hedberg1707c602013-03-15 17:07:15 -05003611 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003612 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3613 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003614}
3615
Johan Hedberg13928972013-03-15 17:07:00 -05003616static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003617{
Johan Hedberg13928972013-03-15 17:07:00 -05003618 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003619 struct hci_cp_write_local_name cp;
3620
Johan Hedberg13928972013-03-15 17:07:00 -05003621 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003622
Johan Hedberg890ea892013-03-15 17:06:52 -05003623 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003624}
3625
Marcel Holtmann1904a852015-01-11 13:50:44 -08003626static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003627{
3628 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003629 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003630
3631 BT_DBG("status 0x%02x", status);
3632
3633 hci_dev_lock(hdev);
3634
Johan Hedberg333ae952015-03-17 13:48:47 +02003635 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003636 if (!cmd)
3637 goto unlock;
3638
3639 cp = cmd->param;
3640
3641 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003642 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3643 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003644 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003645 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3646 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003647
3648 mgmt_pending_remove(cmd);
3649
3650unlock:
3651 hci_dev_unlock(hdev);
3652}
3653
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003654static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003655 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003656{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003657 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003658 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003659 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003660 int err;
3661
3662 BT_DBG("");
3663
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003664 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003665
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003666 /* If the old values are the same as the new ones just return a
3667 * direct command complete event.
3668 */
3669 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3670 !memcmp(hdev->short_name, cp->short_name,
3671 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003672 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3673 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003674 goto failed;
3675 }
3676
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003677 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003678
Johan Hedbergb5235a62012-02-21 14:32:24 +02003679 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003680 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003681
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003682 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3683 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003684 if (err < 0)
3685 goto failed;
3686
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003687 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3688 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003689
Johan Hedbergb5235a62012-02-21 14:32:24 +02003690 goto failed;
3691 }
3692
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003693 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003694 if (!cmd) {
3695 err = -ENOMEM;
3696 goto failed;
3697 }
3698
Johan Hedberg13928972013-03-15 17:07:00 -05003699 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3700
Johan Hedberg890ea892013-03-15 17:06:52 -05003701 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003702
3703 if (lmp_bredr_capable(hdev)) {
3704 update_name(&req);
3705 update_eir(&req);
3706 }
3707
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003708 /* The name is stored in the scan response data and so
3709 * no need to udpate the advertising data here.
3710 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003711 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003712 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003713
Johan Hedberg13928972013-03-15 17:07:00 -05003714 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003715 if (err < 0)
3716 mgmt_pending_remove(cmd);
3717
3718failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003719 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003720 return err;
3721}
3722
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003723static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003724 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003725{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003726 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003727 int err;
3728
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003729 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003730
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003731 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003732
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003733 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003734 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3735 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003736 goto unlock;
3737 }
3738
Andre Guedes9a1a1992012-07-24 15:03:48 -03003739 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003740 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3741 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003742 goto unlock;
3743 }
3744
Johan Hedberg333ae952015-03-17 13:48:47 +02003745 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003746 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3747 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003748 goto unlock;
3749 }
3750
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003751 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003752 if (!cmd) {
3753 err = -ENOMEM;
3754 goto unlock;
3755 }
3756
Johan Hedberg710f11c2014-05-26 11:21:22 +03003757 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003758 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3759 0, NULL);
3760 else
3761 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3762
Szymon Jancc35938b2011-03-22 13:12:21 +01003763 if (err < 0)
3764 mgmt_pending_remove(cmd);
3765
3766unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003767 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003768 return err;
3769}
3770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003771static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003772 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003773{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003774 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003775 int err;
3776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003777 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003778
Johan Hedberg5d57e792015-01-23 10:10:38 +02003779 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003780 return mgmt_cmd_complete(sk, hdev->id,
3781 MGMT_OP_ADD_REMOTE_OOB_DATA,
3782 MGMT_STATUS_INVALID_PARAMS,
3783 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003784
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003785 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003786
Marcel Holtmannec109112014-01-10 02:07:30 -08003787 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3788 struct mgmt_cp_add_remote_oob_data *cp = data;
3789 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003790
Johan Hedbergc19a4952014-11-17 20:52:19 +02003791 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003792 err = mgmt_cmd_complete(sk, hdev->id,
3793 MGMT_OP_ADD_REMOTE_OOB_DATA,
3794 MGMT_STATUS_INVALID_PARAMS,
3795 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003796 goto unlock;
3797 }
3798
Marcel Holtmannec109112014-01-10 02:07:30 -08003799 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003800 cp->addr.type, cp->hash,
3801 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003802 if (err < 0)
3803 status = MGMT_STATUS_FAILED;
3804 else
3805 status = MGMT_STATUS_SUCCESS;
3806
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003807 err = mgmt_cmd_complete(sk, hdev->id,
3808 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3809 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003810 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3811 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003812 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003813 u8 status;
3814
Johan Hedberg86df9202014-10-26 20:52:27 +01003815 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003816 /* Enforce zero-valued 192-bit parameters as
3817 * long as legacy SMP OOB isn't implemented.
3818 */
3819 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3820 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003821 err = mgmt_cmd_complete(sk, hdev->id,
3822 MGMT_OP_ADD_REMOTE_OOB_DATA,
3823 MGMT_STATUS_INVALID_PARAMS,
3824 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003825 goto unlock;
3826 }
3827
Johan Hedberg86df9202014-10-26 20:52:27 +01003828 rand192 = NULL;
3829 hash192 = NULL;
3830 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003831 /* In case one of the P-192 values is set to zero,
3832 * then just disable OOB data for P-192.
3833 */
3834 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3835 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3836 rand192 = NULL;
3837 hash192 = NULL;
3838 } else {
3839 rand192 = cp->rand192;
3840 hash192 = cp->hash192;
3841 }
3842 }
3843
3844 /* In case one of the P-256 values is set to zero, then just
3845 * disable OOB data for P-256.
3846 */
3847 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3848 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3849 rand256 = NULL;
3850 hash256 = NULL;
3851 } else {
3852 rand256 = cp->rand256;
3853 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003854 }
3855
Johan Hedberg81328d52014-10-26 20:33:47 +01003856 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003857 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003858 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003859 if (err < 0)
3860 status = MGMT_STATUS_FAILED;
3861 else
3862 status = MGMT_STATUS_SUCCESS;
3863
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003864 err = mgmt_cmd_complete(sk, hdev->id,
3865 MGMT_OP_ADD_REMOTE_OOB_DATA,
3866 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003867 } else {
3868 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003869 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3870 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003871 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003872
Johan Hedbergc19a4952014-11-17 20:52:19 +02003873unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003874 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003875 return err;
3876}
3877
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003878static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003879 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003880{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003881 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003882 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003883 int err;
3884
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003885 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003886
Johan Hedbergc19a4952014-11-17 20:52:19 +02003887 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003888 return mgmt_cmd_complete(sk, hdev->id,
3889 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3890 MGMT_STATUS_INVALID_PARAMS,
3891 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003892
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003893 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003894
Johan Hedbergeedbd582014-11-15 09:34:23 +02003895 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3896 hci_remote_oob_data_clear(hdev);
3897 status = MGMT_STATUS_SUCCESS;
3898 goto done;
3899 }
3900
Johan Hedberg6928a922014-10-26 20:46:09 +01003901 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003902 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003903 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003904 else
Szymon Janca6785be2012-12-13 15:11:21 +01003905 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003906
Johan Hedbergeedbd582014-11-15 09:34:23 +02003907done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003908 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3909 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003910
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003911 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003912 return err;
3913}
3914
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003915static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
3916{
3917 struct hci_dev *hdev = req->hdev;
3918 struct hci_cp_inquiry cp;
3919 /* General inquiry access code (GIAC) */
3920 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3921
3922 *status = mgmt_bredr_support(hdev);
3923 if (*status)
3924 return false;
3925
3926 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
3927 *status = MGMT_STATUS_BUSY;
3928 return false;
3929 }
3930
3931 hci_inquiry_cache_flush(hdev);
3932
3933 memset(&cp, 0, sizeof(cp));
3934 memcpy(&cp.lap, lap, sizeof(cp.lap));
3935 cp.length = DISCOV_BREDR_INQUIRY_LEN;
3936
3937 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
3938
3939 return true;
3940}
3941
3942static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003943{
Marcel Holtmann80190442014-12-04 11:36:36 +01003944 struct hci_dev *hdev = req->hdev;
3945 struct hci_cp_le_set_scan_param param_cp;
3946 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01003947 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003948 int err;
3949
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003950 *status = mgmt_le_support(hdev);
3951 if (*status)
3952 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003953
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003954 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
3955 /* Don't let discovery abort an outgoing connection attempt
3956 * that's using directed advertising.
3957 */
3958 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
3959 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01003960 return false;
3961 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003962
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003963 disable_advertising(req);
3964 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003965
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003966 /* If controller is scanning, it means the background scanning is
3967 * running. Thus, we should temporarily stop it in order to set the
3968 * discovery scanning parameters.
3969 */
3970 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
3971 hci_req_add_le_scan_disable(req);
3972
3973 /* All active scans will be done with either a resolvable private
3974 * address (when privacy feature has been enabled) or non-resolvable
3975 * private address.
3976 */
3977 err = hci_update_random_address(req, true, &own_addr_type);
3978 if (err < 0) {
3979 *status = MGMT_STATUS_FAILED;
3980 return false;
3981 }
3982
3983 memset(&param_cp, 0, sizeof(param_cp));
3984 param_cp.type = LE_SCAN_ACTIVE;
3985 param_cp.interval = cpu_to_le16(interval);
3986 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3987 param_cp.own_address_type = own_addr_type;
3988
3989 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3990 &param_cp);
3991
3992 memset(&enable_cp, 0, sizeof(enable_cp));
3993 enable_cp.enable = LE_SCAN_ENABLE;
3994 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3995
3996 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3997 &enable_cp);
3998
3999 return true;
4000}
4001
4002static bool trigger_discovery(struct hci_request *req, u8 *status)
4003{
4004 struct hci_dev *hdev = req->hdev;
4005
4006 switch (hdev->discovery.type) {
4007 case DISCOV_TYPE_BREDR:
4008 if (!trigger_bredr_inquiry(req, status))
4009 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004010 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004011
Marcel Holtmann80190442014-12-04 11:36:36 +01004012 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004013 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4014 &hdev->quirks)) {
4015 /* During simultaneous discovery, we double LE scan
4016 * interval. We must leave some time for the controller
4017 * to do BR/EDR inquiry.
4018 */
4019 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4020 status))
4021 return false;
4022
4023 if (!trigger_bredr_inquiry(req, status))
4024 return false;
4025
4026 return true;
4027 }
4028
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004029 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004030 *status = MGMT_STATUS_NOT_SUPPORTED;
4031 return false;
4032 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004033 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004034
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004035 case DISCOV_TYPE_LE:
4036 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004037 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004038 break;
4039
4040 default:
4041 *status = MGMT_STATUS_INVALID_PARAMS;
4042 return false;
4043 }
4044
4045 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004046}
4047
Marcel Holtmann1904a852015-01-11 13:50:44 -08004048static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4049 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004050{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004051 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004052 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004053
Andre Guedes7c307722013-04-30 15:29:28 -03004054 BT_DBG("status %d", status);
4055
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004056 hci_dev_lock(hdev);
4057
Johan Hedberg333ae952015-03-17 13:48:47 +02004058 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004059 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004060 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004061
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004062 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004063 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004064 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004065 }
4066
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004067 if (status) {
4068 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4069 goto unlock;
4070 }
4071
Andre Guedes7c307722013-04-30 15:29:28 -03004072 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004073
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004074 /* If the scan involves LE scan, pick proper timeout to schedule
4075 * hdev->le_scan_disable that will stop it.
4076 */
Andre Guedes7c307722013-04-30 15:29:28 -03004077 switch (hdev->discovery.type) {
4078 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004079 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004080 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004081 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004082 /* When running simultaneous discovery, the LE scanning time
4083 * should occupy the whole discovery time sine BR/EDR inquiry
4084 * and LE scanning are scheduled by the controller.
4085 *
4086 * For interleaving discovery in comparison, BR/EDR inquiry
4087 * and LE scanning are done sequentially with separate
4088 * timeouts.
4089 */
4090 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4091 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4092 else
4093 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004094 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004095 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004096 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004097 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004098 default:
4099 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004100 timeout = 0;
4101 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004102 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004103
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004104 if (timeout) {
4105 /* When service discovery is used and the controller has
4106 * a strict duplicate filter, it is important to remember
4107 * the start and duration of the scan. This is required
4108 * for restarting scanning during the discovery phase.
4109 */
4110 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4111 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004112 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004113 hdev->discovery.scan_start = jiffies;
4114 hdev->discovery.scan_duration = timeout;
4115 }
4116
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004117 queue_delayed_work(hdev->workqueue,
4118 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004119 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004120
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004121unlock:
4122 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004123}
4124
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004125static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004126 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004127{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004128 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004129 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004130 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004131 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004132 int err;
4133
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004134 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004135
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004136 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004137
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004138 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004139 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4140 MGMT_STATUS_NOT_POWERED,
4141 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004142 goto failed;
4143 }
4144
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004145 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004146 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004147 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4148 MGMT_STATUS_BUSY, &cp->type,
4149 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004150 goto failed;
4151 }
4152
Johan Hedberg2922a942014-12-05 13:36:06 +02004153 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004154 if (!cmd) {
4155 err = -ENOMEM;
4156 goto failed;
4157 }
4158
Johan Hedberg2922a942014-12-05 13:36:06 +02004159 cmd->cmd_complete = generic_cmd_complete;
4160
Marcel Holtmann22078802014-12-05 11:45:22 +01004161 /* Clear the discovery filter first to free any previously
4162 * allocated memory for the UUID list.
4163 */
4164 hci_discovery_filter_clear(hdev);
4165
Andre Guedes4aab14e2012-02-17 20:39:36 -03004166 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004167 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004168
Andre Guedes7c307722013-04-30 15:29:28 -03004169 hci_req_init(&req, hdev);
4170
Marcel Holtmann80190442014-12-04 11:36:36 +01004171 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004172 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4173 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004174 mgmt_pending_remove(cmd);
4175 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004176 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004177
Andre Guedes7c307722013-04-30 15:29:28 -03004178 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004179 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004180 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004181 goto failed;
4182 }
4183
4184 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004185
4186failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004187 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004188 return err;
4189}
4190
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004191static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4192 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004193{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004194 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4195 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004196}
4197
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004198static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4199 void *data, u16 len)
4200{
4201 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004202 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004203 struct hci_request req;
4204 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4205 u16 uuid_count, expected_len;
4206 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004207 int err;
4208
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004209 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004210
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004211 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004212
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004213 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004214 err = mgmt_cmd_complete(sk, hdev->id,
4215 MGMT_OP_START_SERVICE_DISCOVERY,
4216 MGMT_STATUS_NOT_POWERED,
4217 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004218 goto failed;
4219 }
4220
4221 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004222 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004223 err = mgmt_cmd_complete(sk, hdev->id,
4224 MGMT_OP_START_SERVICE_DISCOVERY,
4225 MGMT_STATUS_BUSY, &cp->type,
4226 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004227 goto failed;
4228 }
4229
4230 uuid_count = __le16_to_cpu(cp->uuid_count);
4231 if (uuid_count > max_uuid_count) {
4232 BT_ERR("service_discovery: too big uuid_count value %u",
4233 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004234 err = mgmt_cmd_complete(sk, hdev->id,
4235 MGMT_OP_START_SERVICE_DISCOVERY,
4236 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4237 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004238 goto failed;
4239 }
4240
4241 expected_len = sizeof(*cp) + uuid_count * 16;
4242 if (expected_len != len) {
4243 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4244 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004245 err = mgmt_cmd_complete(sk, hdev->id,
4246 MGMT_OP_START_SERVICE_DISCOVERY,
4247 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4248 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004249 goto failed;
4250 }
4251
4252 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004253 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004254 if (!cmd) {
4255 err = -ENOMEM;
4256 goto failed;
4257 }
4258
Johan Hedberg2922a942014-12-05 13:36:06 +02004259 cmd->cmd_complete = service_discovery_cmd_complete;
4260
Marcel Holtmann22078802014-12-05 11:45:22 +01004261 /* Clear the discovery filter first to free any previously
4262 * allocated memory for the UUID list.
4263 */
4264 hci_discovery_filter_clear(hdev);
4265
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004266 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004267 hdev->discovery.type = cp->type;
4268 hdev->discovery.rssi = cp->rssi;
4269 hdev->discovery.uuid_count = uuid_count;
4270
4271 if (uuid_count > 0) {
4272 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4273 GFP_KERNEL);
4274 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004275 err = mgmt_cmd_complete(sk, hdev->id,
4276 MGMT_OP_START_SERVICE_DISCOVERY,
4277 MGMT_STATUS_FAILED,
4278 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004279 mgmt_pending_remove(cmd);
4280 goto failed;
4281 }
4282 }
4283
4284 hci_req_init(&req, hdev);
4285
4286 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004287 err = mgmt_cmd_complete(sk, hdev->id,
4288 MGMT_OP_START_SERVICE_DISCOVERY,
4289 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004290 mgmt_pending_remove(cmd);
4291 goto failed;
4292 }
4293
4294 err = hci_req_run(&req, start_discovery_complete);
4295 if (err < 0) {
4296 mgmt_pending_remove(cmd);
4297 goto failed;
4298 }
4299
4300 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4301
4302failed:
4303 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004304 return err;
4305}
4306
Marcel Holtmann1904a852015-01-11 13:50:44 -08004307static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004308{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004309 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004310
Andre Guedes0e05bba2013-04-30 15:29:33 -03004311 BT_DBG("status %d", status);
4312
4313 hci_dev_lock(hdev);
4314
Johan Hedberg333ae952015-03-17 13:48:47 +02004315 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004316 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004317 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004318 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004319 }
4320
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004321 if (!status)
4322 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004323
Andre Guedes0e05bba2013-04-30 15:29:33 -03004324 hci_dev_unlock(hdev);
4325}
4326
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004327static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004328 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004329{
Johan Hedbergd9306502012-02-20 23:25:18 +02004330 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004331 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004332 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004333 int err;
4334
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004335 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004336
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004337 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004338
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004339 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004340 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4341 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4342 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004343 goto unlock;
4344 }
4345
4346 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004347 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4348 MGMT_STATUS_INVALID_PARAMS,
4349 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004350 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004351 }
4352
Johan Hedberg2922a942014-12-05 13:36:06 +02004353 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004354 if (!cmd) {
4355 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004356 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004357 }
4358
Johan Hedberg2922a942014-12-05 13:36:06 +02004359 cmd->cmd_complete = generic_cmd_complete;
4360
Andre Guedes0e05bba2013-04-30 15:29:33 -03004361 hci_req_init(&req, hdev);
4362
Johan Hedberg21a60d32014-06-10 14:05:58 +03004363 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004364
Johan Hedberg21a60d32014-06-10 14:05:58 +03004365 err = hci_req_run(&req, stop_discovery_complete);
4366 if (!err) {
4367 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004368 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004369 }
4370
Johan Hedberg21a60d32014-06-10 14:05:58 +03004371 mgmt_pending_remove(cmd);
4372
4373 /* If no HCI commands were sent we're done */
4374 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004375 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4376 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004377 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4378 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004379
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004380unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004381 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004382 return err;
4383}
4384
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004385static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004386 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004387{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004388 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004389 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004390 int err;
4391
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004392 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004393
Johan Hedberg561aafb2012-01-04 13:31:59 +02004394 hci_dev_lock(hdev);
4395
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004396 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004397 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4398 MGMT_STATUS_FAILED, &cp->addr,
4399 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004400 goto failed;
4401 }
4402
Johan Hedberga198e7b2012-02-17 14:27:06 +02004403 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004404 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004405 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4406 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4407 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004408 goto failed;
4409 }
4410
4411 if (cp->name_known) {
4412 e->name_state = NAME_KNOWN;
4413 list_del(&e->list);
4414 } else {
4415 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004416 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004417 }
4418
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004419 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4420 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004421
4422failed:
4423 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004424 return err;
4425}
4426
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004427static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004428 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004429{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004430 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004431 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004432 int err;
4433
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004434 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004435
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004436 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004437 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4438 MGMT_STATUS_INVALID_PARAMS,
4439 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004440
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004441 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004442
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004443 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4444 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004445 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004446 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004447 goto done;
4448 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004449
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004450 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4451 sk);
4452 status = MGMT_STATUS_SUCCESS;
4453
4454done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004455 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4456 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004457
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004458 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004459
4460 return err;
4461}
4462
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004463static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004464 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004465{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004466 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004467 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004468 int err;
4469
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004470 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004471
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004472 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004473 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4474 MGMT_STATUS_INVALID_PARAMS,
4475 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004476
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004477 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004478
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004479 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4480 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004481 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004482 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004483 goto done;
4484 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004485
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004486 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4487 sk);
4488 status = MGMT_STATUS_SUCCESS;
4489
4490done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004491 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4492 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004493
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004494 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004495
4496 return err;
4497}
4498
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004499static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4500 u16 len)
4501{
4502 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004503 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004504 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004505 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004506
4507 BT_DBG("%s", hdev->name);
4508
Szymon Jancc72d4b82012-03-16 16:02:57 +01004509 source = __le16_to_cpu(cp->source);
4510
4511 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004512 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4513 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004514
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004515 hci_dev_lock(hdev);
4516
Szymon Jancc72d4b82012-03-16 16:02:57 +01004517 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004518 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4519 hdev->devid_product = __le16_to_cpu(cp->product);
4520 hdev->devid_version = __le16_to_cpu(cp->version);
4521
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004522 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4523 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004524
Johan Hedberg890ea892013-03-15 17:06:52 -05004525 hci_req_init(&req, hdev);
4526 update_eir(&req);
4527 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004528
4529 hci_dev_unlock(hdev);
4530
4531 return err;
4532}
4533
Arman Uguray24b4f382015-03-23 15:57:12 -07004534static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4535 u16 opcode)
4536{
4537 BT_DBG("status %d", status);
4538}
4539
Marcel Holtmann1904a852015-01-11 13:50:44 -08004540static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4541 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004542{
4543 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004544 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004545
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304546 hci_dev_lock(hdev);
4547
Johan Hedberg4375f102013-09-25 13:26:10 +03004548 if (status) {
4549 u8 mgmt_err = mgmt_status(status);
4550
4551 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4552 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304553 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004554 }
4555
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004556 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004557 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004558 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004559 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004560
Johan Hedberg4375f102013-09-25 13:26:10 +03004561 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4562 &match);
4563
4564 new_settings(hdev, match.sk);
4565
4566 if (match.sk)
4567 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304568
Arman Uguray24b4f382015-03-23 15:57:12 -07004569 /* If "Set Advertising" was just disabled and instance advertising was
4570 * set up earlier, then enable the advertising instance.
4571 */
4572 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4573 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4574 goto unlock;
4575
4576 hci_req_init(&req, hdev);
4577
4578 update_adv_data(&req);
4579 enable_advertising(&req);
4580
4581 if (hci_req_run(&req, enable_advertising_instance) < 0)
4582 BT_ERR("Failed to re-configure advertising");
4583
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304584unlock:
4585 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004586}
4587
Marcel Holtmann21b51872013-10-10 09:47:53 -07004588static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4589 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004590{
4591 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004592 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004593 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004594 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004595 int err;
4596
4597 BT_DBG("request for %s", hdev->name);
4598
Johan Hedberge6fe7982013-10-02 15:45:22 +03004599 status = mgmt_le_support(hdev);
4600 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004601 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4602 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004603
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004604 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004605 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4606 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004607
4608 hci_dev_lock(hdev);
4609
4610 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004611
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004612 /* The following conditions are ones which mean that we should
4613 * not do any HCI communication but directly send a mgmt
4614 * response to user space (after toggling the flag if
4615 * necessary).
4616 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004617 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004618 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4619 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004620 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004621 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004622 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004623 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004624
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004625 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004626 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004627 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004628 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004629 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004630 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004631 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004632 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004633 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004634 }
4635
4636 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4637 if (err < 0)
4638 goto unlock;
4639
4640 if (changed)
4641 err = new_settings(hdev, sk);
4642
4643 goto unlock;
4644 }
4645
Johan Hedberg333ae952015-03-17 13:48:47 +02004646 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4647 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004648 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4649 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004650 goto unlock;
4651 }
4652
4653 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4654 if (!cmd) {
4655 err = -ENOMEM;
4656 goto unlock;
4657 }
4658
4659 hci_req_init(&req, hdev);
4660
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004661 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004662 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004663 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004664 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004665
Arman Uguray24b4f382015-03-23 15:57:12 -07004666 if (val) {
4667 /* Switch to instance "0" for the Set Advertising setting. */
4668 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004669 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004670 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004671 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004672 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004673 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004674
4675 err = hci_req_run(&req, set_advertising_complete);
4676 if (err < 0)
4677 mgmt_pending_remove(cmd);
4678
4679unlock:
4680 hci_dev_unlock(hdev);
4681 return err;
4682}
4683
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004684static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4685 void *data, u16 len)
4686{
4687 struct mgmt_cp_set_static_address *cp = data;
4688 int err;
4689
4690 BT_DBG("%s", hdev->name);
4691
Marcel Holtmann62af4442013-10-02 22:10:32 -07004692 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004693 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4694 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004695
4696 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004697 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4698 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004699
4700 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4701 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004702 return mgmt_cmd_status(sk, hdev->id,
4703 MGMT_OP_SET_STATIC_ADDRESS,
4704 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004705
4706 /* Two most significant bits shall be set */
4707 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004708 return mgmt_cmd_status(sk, hdev->id,
4709 MGMT_OP_SET_STATIC_ADDRESS,
4710 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004711 }
4712
4713 hci_dev_lock(hdev);
4714
4715 bacpy(&hdev->static_addr, &cp->bdaddr);
4716
Marcel Holtmann93690c22015-03-06 10:11:21 -08004717 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4718 if (err < 0)
4719 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004720
Marcel Holtmann93690c22015-03-06 10:11:21 -08004721 err = new_settings(hdev, sk);
4722
4723unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004724 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004725 return err;
4726}
4727
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004728static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4729 void *data, u16 len)
4730{
4731 struct mgmt_cp_set_scan_params *cp = data;
4732 __u16 interval, window;
4733 int err;
4734
4735 BT_DBG("%s", hdev->name);
4736
4737 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004738 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4739 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004740
4741 interval = __le16_to_cpu(cp->interval);
4742
4743 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004744 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4745 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004746
4747 window = __le16_to_cpu(cp->window);
4748
4749 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004750 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4751 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004752
Marcel Holtmann899e1072013-10-14 09:55:32 -07004753 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004754 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4755 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004756
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004757 hci_dev_lock(hdev);
4758
4759 hdev->le_scan_interval = interval;
4760 hdev->le_scan_window = window;
4761
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004762 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4763 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004764
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004765 /* If background scan is running, restart it so new parameters are
4766 * loaded.
4767 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004768 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004769 hdev->discovery.state == DISCOVERY_STOPPED) {
4770 struct hci_request req;
4771
4772 hci_req_init(&req, hdev);
4773
4774 hci_req_add_le_scan_disable(&req);
4775 hci_req_add_le_passive_scan(&req);
4776
4777 hci_req_run(&req, NULL);
4778 }
4779
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004780 hci_dev_unlock(hdev);
4781
4782 return err;
4783}
4784
Marcel Holtmann1904a852015-01-11 13:50:44 -08004785static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4786 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004787{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004788 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004789
4790 BT_DBG("status 0x%02x", status);
4791
4792 hci_dev_lock(hdev);
4793
Johan Hedberg333ae952015-03-17 13:48:47 +02004794 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004795 if (!cmd)
4796 goto unlock;
4797
4798 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004799 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4800 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004801 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004802 struct mgmt_mode *cp = cmd->param;
4803
4804 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004805 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004806 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004807 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004808
Johan Hedberg33e38b32013-03-15 17:07:05 -05004809 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4810 new_settings(hdev, cmd->sk);
4811 }
4812
4813 mgmt_pending_remove(cmd);
4814
4815unlock:
4816 hci_dev_unlock(hdev);
4817}
4818
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004819static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004820 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004821{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004822 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004823 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004824 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004825 int err;
4826
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004827 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004828
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004829 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004830 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004831 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4832 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004833
Johan Hedberga7e80f22013-01-09 16:05:19 +02004834 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004835 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4836 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004837
Antti Julkuf6422ec2011-06-22 13:11:56 +03004838 hci_dev_lock(hdev);
4839
Johan Hedberg333ae952015-03-17 13:48:47 +02004840 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004841 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4842 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004843 goto unlock;
4844 }
4845
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004846 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004847 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4848 hdev);
4849 goto unlock;
4850 }
4851
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004852 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004853 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004854 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4855 hdev);
4856 new_settings(hdev, sk);
4857 goto unlock;
4858 }
4859
Johan Hedberg33e38b32013-03-15 17:07:05 -05004860 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4861 data, len);
4862 if (!cmd) {
4863 err = -ENOMEM;
4864 goto unlock;
4865 }
4866
4867 hci_req_init(&req, hdev);
4868
Johan Hedberg406d7802013-03-15 17:07:09 -05004869 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004870
4871 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004872 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004873 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4874 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004875 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004876 }
4877
Johan Hedberg33e38b32013-03-15 17:07:05 -05004878unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004879 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004880
Antti Julkuf6422ec2011-06-22 13:11:56 +03004881 return err;
4882}
4883
Marcel Holtmann1904a852015-01-11 13:50:44 -08004884static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004885{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004886 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004887
4888 BT_DBG("status 0x%02x", status);
4889
4890 hci_dev_lock(hdev);
4891
Johan Hedberg333ae952015-03-17 13:48:47 +02004892 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004893 if (!cmd)
4894 goto unlock;
4895
4896 if (status) {
4897 u8 mgmt_err = mgmt_status(status);
4898
4899 /* We need to restore the flag if related HCI commands
4900 * failed.
4901 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004902 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004903
Johan Hedberga69e8372015-03-06 21:08:53 +02004904 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004905 } else {
4906 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4907 new_settings(hdev, cmd->sk);
4908 }
4909
4910 mgmt_pending_remove(cmd);
4911
4912unlock:
4913 hci_dev_unlock(hdev);
4914}
4915
4916static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4917{
4918 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004919 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004920 struct hci_request req;
4921 int err;
4922
4923 BT_DBG("request for %s", hdev->name);
4924
4925 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004926 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4927 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004928
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004929 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004930 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4931 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004932
4933 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004934 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4935 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004936
4937 hci_dev_lock(hdev);
4938
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004939 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004940 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4941 goto unlock;
4942 }
4943
4944 if (!hdev_is_powered(hdev)) {
4945 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004946 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4947 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4948 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4949 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4950 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004951 }
4952
Marcel Holtmannce05d602015-03-13 02:11:03 -07004953 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004954
4955 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4956 if (err < 0)
4957 goto unlock;
4958
4959 err = new_settings(hdev, sk);
4960 goto unlock;
4961 }
4962
4963 /* Reject disabling when powered on */
4964 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004965 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4966 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004967 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004968 } else {
4969 /* When configuring a dual-mode controller to operate
4970 * with LE only and using a static address, then switching
4971 * BR/EDR back on is not allowed.
4972 *
4973 * Dual-mode controllers shall operate with the public
4974 * address as its identity address for BR/EDR and LE. So
4975 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004976 *
4977 * The same restrictions applies when secure connections
4978 * has been enabled. For BR/EDR this is a controller feature
4979 * while for LE it is a host stack feature. This means that
4980 * switching BR/EDR back on when secure connections has been
4981 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004982 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004983 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004984 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004985 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004986 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4987 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004988 goto unlock;
4989 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004990 }
4991
Johan Hedberg333ae952015-03-17 13:48:47 +02004992 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004993 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4994 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004995 goto unlock;
4996 }
4997
4998 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4999 if (!cmd) {
5000 err = -ENOMEM;
5001 goto unlock;
5002 }
5003
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005004 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005005 * generates the correct flags.
5006 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005007 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005008
5009 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005010
Johan Hedberg432df052014-08-01 11:13:31 +03005011 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005012 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005013
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005014 /* Since only the advertising data flags will change, there
5015 * is no need to update the scan response data.
5016 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005017 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005018
Johan Hedberg0663ca22013-10-02 13:43:14 +03005019 err = hci_req_run(&req, set_bredr_complete);
5020 if (err < 0)
5021 mgmt_pending_remove(cmd);
5022
5023unlock:
5024 hci_dev_unlock(hdev);
5025 return err;
5026}
5027
Johan Hedberga1443f52015-01-23 15:42:46 +02005028static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5029{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005030 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005031 struct mgmt_mode *cp;
5032
5033 BT_DBG("%s status %u", hdev->name, status);
5034
5035 hci_dev_lock(hdev);
5036
Johan Hedberg333ae952015-03-17 13:48:47 +02005037 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005038 if (!cmd)
5039 goto unlock;
5040
5041 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005042 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5043 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005044 goto remove;
5045 }
5046
5047 cp = cmd->param;
5048
5049 switch (cp->val) {
5050 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005051 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5052 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005053 break;
5054 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005055 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005056 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005057 break;
5058 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005059 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5060 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005061 break;
5062 }
5063
5064 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5065 new_settings(hdev, cmd->sk);
5066
5067remove:
5068 mgmt_pending_remove(cmd);
5069unlock:
5070 hci_dev_unlock(hdev);
5071}
5072
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005073static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5074 void *data, u16 len)
5075{
5076 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005077 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005078 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005079 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005080 int err;
5081
5082 BT_DBG("request for %s", hdev->name);
5083
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005084 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005085 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005086 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5087 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005088
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005089 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005090 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005091 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005092 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5093 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005094
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005095 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005096 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005097 MGMT_STATUS_INVALID_PARAMS);
5098
5099 hci_dev_lock(hdev);
5100
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005101 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005102 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005103 bool changed;
5104
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005105 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005106 changed = !hci_dev_test_and_set_flag(hdev,
5107 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005108 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005109 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005110 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005111 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005112 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005113 changed = hci_dev_test_and_clear_flag(hdev,
5114 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005115 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005116 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005117
5118 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5119 if (err < 0)
5120 goto failed;
5121
5122 if (changed)
5123 err = new_settings(hdev, sk);
5124
5125 goto failed;
5126 }
5127
Johan Hedberg333ae952015-03-17 13:48:47 +02005128 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005129 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5130 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005131 goto failed;
5132 }
5133
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005134 val = !!cp->val;
5135
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005136 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5137 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005138 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5139 goto failed;
5140 }
5141
5142 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5143 if (!cmd) {
5144 err = -ENOMEM;
5145 goto failed;
5146 }
5147
Johan Hedberga1443f52015-01-23 15:42:46 +02005148 hci_req_init(&req, hdev);
5149 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5150 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005151 if (err < 0) {
5152 mgmt_pending_remove(cmd);
5153 goto failed;
5154 }
5155
5156failed:
5157 hci_dev_unlock(hdev);
5158 return err;
5159}
5160
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005161static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5162 void *data, u16 len)
5163{
5164 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005165 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005166 int err;
5167
5168 BT_DBG("request for %s", hdev->name);
5169
Johan Hedbergb97109792014-06-24 14:00:28 +03005170 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005171 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5172 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005173
5174 hci_dev_lock(hdev);
5175
5176 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005177 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005178 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005179 changed = hci_dev_test_and_clear_flag(hdev,
5180 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005181
Johan Hedbergb97109792014-06-24 14:00:28 +03005182 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005183 use_changed = !hci_dev_test_and_set_flag(hdev,
5184 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005185 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005186 use_changed = hci_dev_test_and_clear_flag(hdev,
5187 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005188
5189 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005190 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005191 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5192 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5193 sizeof(mode), &mode);
5194 }
5195
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005196 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5197 if (err < 0)
5198 goto unlock;
5199
5200 if (changed)
5201 err = new_settings(hdev, sk);
5202
5203unlock:
5204 hci_dev_unlock(hdev);
5205 return err;
5206}
5207
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005208static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5209 u16 len)
5210{
5211 struct mgmt_cp_set_privacy *cp = cp_data;
5212 bool changed;
5213 int err;
5214
5215 BT_DBG("request for %s", hdev->name);
5216
5217 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005218 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5219 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005220
5221 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005222 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5223 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005224
5225 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005226 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5227 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005228
5229 hci_dev_lock(hdev);
5230
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005231 /* If user space supports this command it is also expected to
5232 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5233 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005234 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005235
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005236 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005237 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005238 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005239 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005240 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005241 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005242 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005243 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005244 }
5245
5246 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5247 if (err < 0)
5248 goto unlock;
5249
5250 if (changed)
5251 err = new_settings(hdev, sk);
5252
5253unlock:
5254 hci_dev_unlock(hdev);
5255 return err;
5256}
5257
Johan Hedberg41edf162014-02-18 10:19:35 +02005258static bool irk_is_valid(struct mgmt_irk_info *irk)
5259{
5260 switch (irk->addr.type) {
5261 case BDADDR_LE_PUBLIC:
5262 return true;
5263
5264 case BDADDR_LE_RANDOM:
5265 /* Two most significant bits shall be set */
5266 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5267 return false;
5268 return true;
5269 }
5270
5271 return false;
5272}
5273
5274static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5275 u16 len)
5276{
5277 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005278 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5279 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005280 u16 irk_count, expected_len;
5281 int i, err;
5282
5283 BT_DBG("request for %s", hdev->name);
5284
5285 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005286 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5287 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005288
5289 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005290 if (irk_count > max_irk_count) {
5291 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005292 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5293 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005294 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005295
5296 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5297 if (expected_len != len) {
5298 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005299 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005300 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5301 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005302 }
5303
5304 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5305
5306 for (i = 0; i < irk_count; i++) {
5307 struct mgmt_irk_info *key = &cp->irks[i];
5308
5309 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005310 return mgmt_cmd_status(sk, hdev->id,
5311 MGMT_OP_LOAD_IRKS,
5312 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005313 }
5314
5315 hci_dev_lock(hdev);
5316
5317 hci_smp_irks_clear(hdev);
5318
5319 for (i = 0; i < irk_count; i++) {
5320 struct mgmt_irk_info *irk = &cp->irks[i];
5321 u8 addr_type;
5322
5323 if (irk->addr.type == BDADDR_LE_PUBLIC)
5324 addr_type = ADDR_LE_DEV_PUBLIC;
5325 else
5326 addr_type = ADDR_LE_DEV_RANDOM;
5327
5328 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5329 BDADDR_ANY);
5330 }
5331
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005332 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005333
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005334 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005335
5336 hci_dev_unlock(hdev);
5337
5338 return err;
5339}
5340
Johan Hedberg3f706b72013-01-20 14:27:16 +02005341static bool ltk_is_valid(struct mgmt_ltk_info *key)
5342{
5343 if (key->master != 0x00 && key->master != 0x01)
5344 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005345
5346 switch (key->addr.type) {
5347 case BDADDR_LE_PUBLIC:
5348 return true;
5349
5350 case BDADDR_LE_RANDOM:
5351 /* Two most significant bits shall be set */
5352 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5353 return false;
5354 return true;
5355 }
5356
5357 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005358}
5359
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005360static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005361 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005362{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005363 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005364 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5365 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005366 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005367 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005368
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005369 BT_DBG("request for %s", hdev->name);
5370
5371 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005372 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5373 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005374
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005375 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005376 if (key_count > max_key_count) {
5377 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005378 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5379 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005380 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005381
5382 expected_len = sizeof(*cp) + key_count *
5383 sizeof(struct mgmt_ltk_info);
5384 if (expected_len != len) {
5385 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005386 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005387 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5388 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005389 }
5390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005391 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005392
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005393 for (i = 0; i < key_count; i++) {
5394 struct mgmt_ltk_info *key = &cp->keys[i];
5395
Johan Hedberg3f706b72013-01-20 14:27:16 +02005396 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005397 return mgmt_cmd_status(sk, hdev->id,
5398 MGMT_OP_LOAD_LONG_TERM_KEYS,
5399 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005400 }
5401
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005402 hci_dev_lock(hdev);
5403
5404 hci_smp_ltks_clear(hdev);
5405
5406 for (i = 0; i < key_count; i++) {
5407 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005408 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005409
5410 if (key->addr.type == BDADDR_LE_PUBLIC)
5411 addr_type = ADDR_LE_DEV_PUBLIC;
5412 else
5413 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005414
Johan Hedberg61b43352014-05-29 19:36:53 +03005415 switch (key->type) {
5416 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005417 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005418 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005419 break;
5420 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005421 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005422 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005423 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005424 case MGMT_LTK_P256_UNAUTH:
5425 authenticated = 0x00;
5426 type = SMP_LTK_P256;
5427 break;
5428 case MGMT_LTK_P256_AUTH:
5429 authenticated = 0x01;
5430 type = SMP_LTK_P256;
5431 break;
5432 case MGMT_LTK_P256_DEBUG:
5433 authenticated = 0x00;
5434 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005435 default:
5436 continue;
5437 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005438
Johan Hedberg35d70272014-02-19 14:57:47 +02005439 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005440 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005441 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005442 }
5443
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005444 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005445 NULL, 0);
5446
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005447 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005448
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005449 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005450}
5451
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005452static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005453{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005454 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005455 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005456 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005457
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005458 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005459
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005460 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005461 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005462 rp.tx_power = conn->tx_power;
5463 rp.max_tx_power = conn->max_tx_power;
5464 } else {
5465 rp.rssi = HCI_RSSI_INVALID;
5466 rp.tx_power = HCI_TX_POWER_INVALID;
5467 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005468 }
5469
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005470 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5471 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005472
5473 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005474 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005475
5476 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005477}
5478
Marcel Holtmann1904a852015-01-11 13:50:44 -08005479static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5480 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005481{
5482 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005483 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005484 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005485 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005486 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005487
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005488 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005489
5490 hci_dev_lock(hdev);
5491
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005492 /* Commands sent in request are either Read RSSI or Read Transmit Power
5493 * Level so we check which one was last sent to retrieve connection
5494 * handle. Both commands have handle as first parameter so it's safe to
5495 * cast data on the same command struct.
5496 *
5497 * First command sent is always Read RSSI and we fail only if it fails.
5498 * In other case we simply override error to indicate success as we
5499 * already remembered if TX power value is actually valid.
5500 */
5501 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5502 if (!cp) {
5503 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005504 status = MGMT_STATUS_SUCCESS;
5505 } else {
5506 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005507 }
5508
5509 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005510 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005511 goto unlock;
5512 }
5513
5514 handle = __le16_to_cpu(cp->handle);
5515 conn = hci_conn_hash_lookup_handle(hdev, handle);
5516 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005517 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005518 goto unlock;
5519 }
5520
Johan Hedberg333ae952015-03-17 13:48:47 +02005521 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005522 if (!cmd)
5523 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005524
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005525 cmd->cmd_complete(cmd, status);
5526 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005527
5528unlock:
5529 hci_dev_unlock(hdev);
5530}
5531
5532static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5533 u16 len)
5534{
5535 struct mgmt_cp_get_conn_info *cp = data;
5536 struct mgmt_rp_get_conn_info rp;
5537 struct hci_conn *conn;
5538 unsigned long conn_info_age;
5539 int err = 0;
5540
5541 BT_DBG("%s", hdev->name);
5542
5543 memset(&rp, 0, sizeof(rp));
5544 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5545 rp.addr.type = cp->addr.type;
5546
5547 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005548 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5549 MGMT_STATUS_INVALID_PARAMS,
5550 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005551
5552 hci_dev_lock(hdev);
5553
5554 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005555 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5556 MGMT_STATUS_NOT_POWERED, &rp,
5557 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005558 goto unlock;
5559 }
5560
5561 if (cp->addr.type == BDADDR_BREDR)
5562 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5563 &cp->addr.bdaddr);
5564 else
5565 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5566
5567 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005568 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5569 MGMT_STATUS_NOT_CONNECTED, &rp,
5570 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005571 goto unlock;
5572 }
5573
Johan Hedberg333ae952015-03-17 13:48:47 +02005574 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005575 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5576 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005577 goto unlock;
5578 }
5579
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005580 /* To avoid client trying to guess when to poll again for information we
5581 * calculate conn info age as random value between min/max set in hdev.
5582 */
5583 conn_info_age = hdev->conn_info_min_age +
5584 prandom_u32_max(hdev->conn_info_max_age -
5585 hdev->conn_info_min_age);
5586
5587 /* Query controller to refresh cached values if they are too old or were
5588 * never read.
5589 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005590 if (time_after(jiffies, conn->conn_info_timestamp +
5591 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005592 !conn->conn_info_timestamp) {
5593 struct hci_request req;
5594 struct hci_cp_read_tx_power req_txp_cp;
5595 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005596 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005597
5598 hci_req_init(&req, hdev);
5599 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5600 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5601 &req_rssi_cp);
5602
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005603 /* For LE links TX power does not change thus we don't need to
5604 * query for it once value is known.
5605 */
5606 if (!bdaddr_type_is_le(cp->addr.type) ||
5607 conn->tx_power == HCI_TX_POWER_INVALID) {
5608 req_txp_cp.handle = cpu_to_le16(conn->handle);
5609 req_txp_cp.type = 0x00;
5610 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5611 sizeof(req_txp_cp), &req_txp_cp);
5612 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005613
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005614 /* Max TX power needs to be read only once per connection */
5615 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5616 req_txp_cp.handle = cpu_to_le16(conn->handle);
5617 req_txp_cp.type = 0x01;
5618 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5619 sizeof(req_txp_cp), &req_txp_cp);
5620 }
5621
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005622 err = hci_req_run(&req, conn_info_refresh_complete);
5623 if (err < 0)
5624 goto unlock;
5625
5626 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5627 data, len);
5628 if (!cmd) {
5629 err = -ENOMEM;
5630 goto unlock;
5631 }
5632
5633 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005634 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005635 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005636
5637 conn->conn_info_timestamp = jiffies;
5638 } else {
5639 /* Cache is valid, just reply with values cached in hci_conn */
5640 rp.rssi = conn->rssi;
5641 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005642 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005643
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005644 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5645 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005646 }
5647
5648unlock:
5649 hci_dev_unlock(hdev);
5650 return err;
5651}
5652
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005653static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005654{
5655 struct hci_conn *conn = cmd->user_data;
5656 struct mgmt_rp_get_clock_info rp;
5657 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005658 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005659
5660 memset(&rp, 0, sizeof(rp));
5661 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5662
5663 if (status)
5664 goto complete;
5665
5666 hdev = hci_dev_get(cmd->index);
5667 if (hdev) {
5668 rp.local_clock = cpu_to_le32(hdev->clock);
5669 hci_dev_put(hdev);
5670 }
5671
5672 if (conn) {
5673 rp.piconet_clock = cpu_to_le32(conn->clock);
5674 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5675 }
5676
5677complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005678 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5679 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005680
5681 if (conn) {
5682 hci_conn_drop(conn);
5683 hci_conn_put(conn);
5684 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005685
5686 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005687}
5688
Marcel Holtmann1904a852015-01-11 13:50:44 -08005689static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005690{
Johan Hedberg95868422014-06-28 17:54:07 +03005691 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005692 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005693 struct hci_conn *conn;
5694
5695 BT_DBG("%s status %u", hdev->name, status);
5696
5697 hci_dev_lock(hdev);
5698
5699 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5700 if (!hci_cp)
5701 goto unlock;
5702
5703 if (hci_cp->which) {
5704 u16 handle = __le16_to_cpu(hci_cp->handle);
5705 conn = hci_conn_hash_lookup_handle(hdev, handle);
5706 } else {
5707 conn = NULL;
5708 }
5709
Johan Hedberg333ae952015-03-17 13:48:47 +02005710 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005711 if (!cmd)
5712 goto unlock;
5713
Johan Hedberg69487372014-12-05 13:36:07 +02005714 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005715 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005716
5717unlock:
5718 hci_dev_unlock(hdev);
5719}
5720
5721static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5722 u16 len)
5723{
5724 struct mgmt_cp_get_clock_info *cp = data;
5725 struct mgmt_rp_get_clock_info rp;
5726 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005727 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005728 struct hci_request req;
5729 struct hci_conn *conn;
5730 int err;
5731
5732 BT_DBG("%s", hdev->name);
5733
5734 memset(&rp, 0, sizeof(rp));
5735 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5736 rp.addr.type = cp->addr.type;
5737
5738 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005739 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5740 MGMT_STATUS_INVALID_PARAMS,
5741 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005742
5743 hci_dev_lock(hdev);
5744
5745 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005746 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5747 MGMT_STATUS_NOT_POWERED, &rp,
5748 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005749 goto unlock;
5750 }
5751
5752 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5753 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5754 &cp->addr.bdaddr);
5755 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005756 err = mgmt_cmd_complete(sk, hdev->id,
5757 MGMT_OP_GET_CLOCK_INFO,
5758 MGMT_STATUS_NOT_CONNECTED,
5759 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005760 goto unlock;
5761 }
5762 } else {
5763 conn = NULL;
5764 }
5765
5766 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5767 if (!cmd) {
5768 err = -ENOMEM;
5769 goto unlock;
5770 }
5771
Johan Hedberg69487372014-12-05 13:36:07 +02005772 cmd->cmd_complete = clock_info_cmd_complete;
5773
Johan Hedberg95868422014-06-28 17:54:07 +03005774 hci_req_init(&req, hdev);
5775
5776 memset(&hci_cp, 0, sizeof(hci_cp));
5777 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5778
5779 if (conn) {
5780 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005781 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005782
5783 hci_cp.handle = cpu_to_le16(conn->handle);
5784 hci_cp.which = 0x01; /* Piconet clock */
5785 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5786 }
5787
5788 err = hci_req_run(&req, get_clock_info_complete);
5789 if (err < 0)
5790 mgmt_pending_remove(cmd);
5791
5792unlock:
5793 hci_dev_unlock(hdev);
5794 return err;
5795}
5796
Johan Hedberg5a154e62014-12-19 22:26:02 +02005797static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5798{
5799 struct hci_conn *conn;
5800
5801 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5802 if (!conn)
5803 return false;
5804
5805 if (conn->dst_type != type)
5806 return false;
5807
5808 if (conn->state != BT_CONNECTED)
5809 return false;
5810
5811 return true;
5812}
5813
5814/* This function requires the caller holds hdev->lock */
5815static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5816 u8 addr_type, u8 auto_connect)
5817{
5818 struct hci_dev *hdev = req->hdev;
5819 struct hci_conn_params *params;
5820
5821 params = hci_conn_params_add(hdev, addr, addr_type);
5822 if (!params)
5823 return -EIO;
5824
5825 if (params->auto_connect == auto_connect)
5826 return 0;
5827
5828 list_del_init(&params->action);
5829
5830 switch (auto_connect) {
5831 case HCI_AUTO_CONN_DISABLED:
5832 case HCI_AUTO_CONN_LINK_LOSS:
5833 __hci_update_background_scan(req);
5834 break;
5835 case HCI_AUTO_CONN_REPORT:
5836 list_add(&params->action, &hdev->pend_le_reports);
5837 __hci_update_background_scan(req);
5838 break;
5839 case HCI_AUTO_CONN_DIRECT:
5840 case HCI_AUTO_CONN_ALWAYS:
5841 if (!is_connected(hdev, addr, addr_type)) {
5842 list_add(&params->action, &hdev->pend_le_conns);
5843 __hci_update_background_scan(req);
5844 }
5845 break;
5846 }
5847
5848 params->auto_connect = auto_connect;
5849
5850 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5851 auto_connect);
5852
5853 return 0;
5854}
5855
Marcel Holtmann8afef092014-06-29 22:28:34 +02005856static void device_added(struct sock *sk, struct hci_dev *hdev,
5857 bdaddr_t *bdaddr, u8 type, u8 action)
5858{
5859 struct mgmt_ev_device_added ev;
5860
5861 bacpy(&ev.addr.bdaddr, bdaddr);
5862 ev.addr.type = type;
5863 ev.action = action;
5864
5865 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5866}
5867
Marcel Holtmann1904a852015-01-11 13:50:44 -08005868static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005869{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005870 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005871
5872 BT_DBG("status 0x%02x", status);
5873
5874 hci_dev_lock(hdev);
5875
Johan Hedberg333ae952015-03-17 13:48:47 +02005876 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005877 if (!cmd)
5878 goto unlock;
5879
5880 cmd->cmd_complete(cmd, mgmt_status(status));
5881 mgmt_pending_remove(cmd);
5882
5883unlock:
5884 hci_dev_unlock(hdev);
5885}
5886
Marcel Holtmann2faade52014-06-29 19:44:03 +02005887static int add_device(struct sock *sk, struct hci_dev *hdev,
5888 void *data, u16 len)
5889{
5890 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005891 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005892 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005893 u8 auto_conn, addr_type;
5894 int err;
5895
5896 BT_DBG("%s", hdev->name);
5897
Johan Hedberg66593582014-07-09 12:59:14 +03005898 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005899 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005900 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5901 MGMT_STATUS_INVALID_PARAMS,
5902 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005903
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005904 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005905 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5906 MGMT_STATUS_INVALID_PARAMS,
5907 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005908
Johan Hedberg5a154e62014-12-19 22:26:02 +02005909 hci_req_init(&req, hdev);
5910
Marcel Holtmann2faade52014-06-29 19:44:03 +02005911 hci_dev_lock(hdev);
5912
Johan Hedberg5a154e62014-12-19 22:26:02 +02005913 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5914 if (!cmd) {
5915 err = -ENOMEM;
5916 goto unlock;
5917 }
5918
5919 cmd->cmd_complete = addr_cmd_complete;
5920
Johan Hedberg66593582014-07-09 12:59:14 +03005921 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005922 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005923 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005924 err = cmd->cmd_complete(cmd,
5925 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005926 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005927 goto unlock;
5928 }
5929
5930 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5931 cp->addr.type);
5932 if (err)
5933 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005934
Johan Hedberg5a154e62014-12-19 22:26:02 +02005935 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005936
Johan Hedberg66593582014-07-09 12:59:14 +03005937 goto added;
5938 }
5939
Marcel Holtmann2faade52014-06-29 19:44:03 +02005940 if (cp->addr.type == BDADDR_LE_PUBLIC)
5941 addr_type = ADDR_LE_DEV_PUBLIC;
5942 else
5943 addr_type = ADDR_LE_DEV_RANDOM;
5944
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005945 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005946 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005947 else if (cp->action == 0x01)
5948 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005949 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005950 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005951
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005952 /* If the connection parameters don't exist for this device,
5953 * they will be created and configured with defaults.
5954 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005955 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005956 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005957 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005958 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005959 goto unlock;
5960 }
5961
Johan Hedberg66593582014-07-09 12:59:14 +03005962added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005963 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5964
Johan Hedberg5a154e62014-12-19 22:26:02 +02005965 err = hci_req_run(&req, add_device_complete);
5966 if (err < 0) {
5967 /* ENODATA means no HCI commands were needed (e.g. if
5968 * the adapter is powered off).
5969 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005970 if (err == -ENODATA)
5971 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005972 mgmt_pending_remove(cmd);
5973 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005974
5975unlock:
5976 hci_dev_unlock(hdev);
5977 return err;
5978}
5979
Marcel Holtmann8afef092014-06-29 22:28:34 +02005980static void device_removed(struct sock *sk, struct hci_dev *hdev,
5981 bdaddr_t *bdaddr, u8 type)
5982{
5983 struct mgmt_ev_device_removed ev;
5984
5985 bacpy(&ev.addr.bdaddr, bdaddr);
5986 ev.addr.type = type;
5987
5988 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5989}
5990
Marcel Holtmann1904a852015-01-11 13:50:44 -08005991static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005992{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005993 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005994
5995 BT_DBG("status 0x%02x", status);
5996
5997 hci_dev_lock(hdev);
5998
Johan Hedberg333ae952015-03-17 13:48:47 +02005999 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006000 if (!cmd)
6001 goto unlock;
6002
6003 cmd->cmd_complete(cmd, mgmt_status(status));
6004 mgmt_pending_remove(cmd);
6005
6006unlock:
6007 hci_dev_unlock(hdev);
6008}
6009
Marcel Holtmann2faade52014-06-29 19:44:03 +02006010static int remove_device(struct sock *sk, struct hci_dev *hdev,
6011 void *data, u16 len)
6012{
6013 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006014 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006015 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006016 int err;
6017
6018 BT_DBG("%s", hdev->name);
6019
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006020 hci_req_init(&req, hdev);
6021
Marcel Holtmann2faade52014-06-29 19:44:03 +02006022 hci_dev_lock(hdev);
6023
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006024 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6025 if (!cmd) {
6026 err = -ENOMEM;
6027 goto unlock;
6028 }
6029
6030 cmd->cmd_complete = addr_cmd_complete;
6031
Marcel Holtmann2faade52014-06-29 19:44:03 +02006032 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006033 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006034 u8 addr_type;
6035
Johan Hedberg66593582014-07-09 12:59:14 +03006036 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006037 err = cmd->cmd_complete(cmd,
6038 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006039 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006040 goto unlock;
6041 }
6042
Johan Hedberg66593582014-07-09 12:59:14 +03006043 if (cp->addr.type == BDADDR_BREDR) {
6044 err = hci_bdaddr_list_del(&hdev->whitelist,
6045 &cp->addr.bdaddr,
6046 cp->addr.type);
6047 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006048 err = cmd->cmd_complete(cmd,
6049 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006050 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006051 goto unlock;
6052 }
6053
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006054 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006055
Johan Hedberg66593582014-07-09 12:59:14 +03006056 device_removed(sk, hdev, &cp->addr.bdaddr,
6057 cp->addr.type);
6058 goto complete;
6059 }
6060
Marcel Holtmann2faade52014-06-29 19:44:03 +02006061 if (cp->addr.type == BDADDR_LE_PUBLIC)
6062 addr_type = ADDR_LE_DEV_PUBLIC;
6063 else
6064 addr_type = ADDR_LE_DEV_RANDOM;
6065
Johan Hedbergc71593d2014-07-02 17:37:28 +03006066 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6067 addr_type);
6068 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006069 err = cmd->cmd_complete(cmd,
6070 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006071 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006072 goto unlock;
6073 }
6074
6075 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006076 err = cmd->cmd_complete(cmd,
6077 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006078 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006079 goto unlock;
6080 }
6081
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006082 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006083 list_del(&params->list);
6084 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006085 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006086
6087 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006088 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006089 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006090 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006091
Marcel Holtmann2faade52014-06-29 19:44:03 +02006092 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006093 err = cmd->cmd_complete(cmd,
6094 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006095 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006096 goto unlock;
6097 }
6098
Johan Hedberg66593582014-07-09 12:59:14 +03006099 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6100 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6101 list_del(&b->list);
6102 kfree(b);
6103 }
6104
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006105 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006106
Johan Hedberg19de0822014-07-06 13:06:51 +03006107 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6108 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6109 continue;
6110 device_removed(sk, hdev, &p->addr, p->addr_type);
6111 list_del(&p->action);
6112 list_del(&p->list);
6113 kfree(p);
6114 }
6115
6116 BT_DBG("All LE connection parameters were removed");
6117
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006118 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006119 }
6120
Johan Hedberg66593582014-07-09 12:59:14 +03006121complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006122 err = hci_req_run(&req, remove_device_complete);
6123 if (err < 0) {
6124 /* ENODATA means no HCI commands were needed (e.g. if
6125 * the adapter is powered off).
6126 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006127 if (err == -ENODATA)
6128 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006129 mgmt_pending_remove(cmd);
6130 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006131
6132unlock:
6133 hci_dev_unlock(hdev);
6134 return err;
6135}
6136
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006137static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6138 u16 len)
6139{
6140 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006141 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6142 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006143 u16 param_count, expected_len;
6144 int i;
6145
6146 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006147 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6148 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006149
6150 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006151 if (param_count > max_param_count) {
6152 BT_ERR("load_conn_param: too big param_count value %u",
6153 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006154 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6155 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006156 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006157
6158 expected_len = sizeof(*cp) + param_count *
6159 sizeof(struct mgmt_conn_param);
6160 if (expected_len != len) {
6161 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6162 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006163 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6164 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006165 }
6166
6167 BT_DBG("%s param_count %u", hdev->name, param_count);
6168
6169 hci_dev_lock(hdev);
6170
6171 hci_conn_params_clear_disabled(hdev);
6172
6173 for (i = 0; i < param_count; i++) {
6174 struct mgmt_conn_param *param = &cp->params[i];
6175 struct hci_conn_params *hci_param;
6176 u16 min, max, latency, timeout;
6177 u8 addr_type;
6178
6179 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6180 param->addr.type);
6181
6182 if (param->addr.type == BDADDR_LE_PUBLIC) {
6183 addr_type = ADDR_LE_DEV_PUBLIC;
6184 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6185 addr_type = ADDR_LE_DEV_RANDOM;
6186 } else {
6187 BT_ERR("Ignoring invalid connection parameters");
6188 continue;
6189 }
6190
6191 min = le16_to_cpu(param->min_interval);
6192 max = le16_to_cpu(param->max_interval);
6193 latency = le16_to_cpu(param->latency);
6194 timeout = le16_to_cpu(param->timeout);
6195
6196 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6197 min, max, latency, timeout);
6198
6199 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6200 BT_ERR("Ignoring invalid connection parameters");
6201 continue;
6202 }
6203
6204 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6205 addr_type);
6206 if (!hci_param) {
6207 BT_ERR("Failed to add connection parameters");
6208 continue;
6209 }
6210
6211 hci_param->conn_min_interval = min;
6212 hci_param->conn_max_interval = max;
6213 hci_param->conn_latency = latency;
6214 hci_param->supervision_timeout = timeout;
6215 }
6216
6217 hci_dev_unlock(hdev);
6218
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006219 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6220 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006221}
6222
Marcel Holtmanndbece372014-07-04 18:11:55 +02006223static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6224 void *data, u16 len)
6225{
6226 struct mgmt_cp_set_external_config *cp = data;
6227 bool changed;
6228 int err;
6229
6230 BT_DBG("%s", hdev->name);
6231
6232 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006233 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6234 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006235
6236 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006237 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6238 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006239
6240 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006241 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6242 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006243
6244 hci_dev_lock(hdev);
6245
6246 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006247 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006248 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006249 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006250
6251 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6252 if (err < 0)
6253 goto unlock;
6254
6255 if (!changed)
6256 goto unlock;
6257
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006258 err = new_options(hdev, sk);
6259
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006260 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006261 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006262
Marcel Holtmann516018a2015-03-13 02:11:04 -07006263 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006264 hci_dev_set_flag(hdev, HCI_CONFIG);
6265 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006266
6267 queue_work(hdev->req_workqueue, &hdev->power_on);
6268 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006269 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006270 mgmt_index_added(hdev);
6271 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006272 }
6273
6274unlock:
6275 hci_dev_unlock(hdev);
6276 return err;
6277}
6278
Marcel Holtmann9713c172014-07-06 12:11:15 +02006279static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6280 void *data, u16 len)
6281{
6282 struct mgmt_cp_set_public_address *cp = data;
6283 bool changed;
6284 int err;
6285
6286 BT_DBG("%s", hdev->name);
6287
6288 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006289 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6290 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006291
6292 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006293 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6294 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006295
6296 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006297 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6298 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006299
6300 hci_dev_lock(hdev);
6301
6302 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6303 bacpy(&hdev->public_addr, &cp->bdaddr);
6304
6305 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6306 if (err < 0)
6307 goto unlock;
6308
6309 if (!changed)
6310 goto unlock;
6311
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006312 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006313 err = new_options(hdev, sk);
6314
6315 if (is_configured(hdev)) {
6316 mgmt_index_removed(hdev);
6317
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006318 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006319
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006320 hci_dev_set_flag(hdev, HCI_CONFIG);
6321 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006322
6323 queue_work(hdev->req_workqueue, &hdev->power_on);
6324 }
6325
6326unlock:
6327 hci_dev_unlock(hdev);
6328 return err;
6329}
6330
Marcel Holtmannbea41602015-03-14 22:43:17 -07006331static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6332 u8 data_len)
6333{
6334 eir[eir_len++] = sizeof(type) + data_len;
6335 eir[eir_len++] = type;
6336 memcpy(&eir[eir_len], data, data_len);
6337 eir_len += data_len;
6338
6339 return eir_len;
6340}
6341
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006342static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6343 void *data, u16 data_len)
6344{
6345 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6346 struct mgmt_rp_read_local_oob_ext_data *rp;
6347 size_t rp_len;
6348 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006349 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006350 int err;
6351
6352 BT_DBG("%s", hdev->name);
6353
6354 if (!hdev_is_powered(hdev))
6355 return mgmt_cmd_complete(sk, hdev->id,
6356 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6357 MGMT_STATUS_NOT_POWERED,
6358 &cp->type, sizeof(cp->type));
6359
6360 switch (cp->type) {
6361 case BIT(BDADDR_BREDR):
6362 status = mgmt_bredr_support(hdev);
6363 if (status)
6364 return mgmt_cmd_complete(sk, hdev->id,
6365 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6366 status, &cp->type,
6367 sizeof(cp->type));
6368 eir_len = 5;
6369 break;
6370 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6371 status = mgmt_le_support(hdev);
6372 if (status)
6373 return mgmt_cmd_complete(sk, hdev->id,
6374 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6375 status, &cp->type,
6376 sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006377 eir_len = 9 + 3 + 18 + 18 + 3;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006378 break;
6379 default:
6380 return mgmt_cmd_complete(sk, hdev->id,
6381 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6382 MGMT_STATUS_INVALID_PARAMS,
6383 &cp->type, sizeof(cp->type));
6384 }
6385
6386 hci_dev_lock(hdev);
6387
6388 rp_len = sizeof(*rp) + eir_len;
6389 rp = kmalloc(rp_len, GFP_ATOMIC);
6390 if (!rp) {
6391 hci_dev_unlock(hdev);
6392 return -ENOMEM;
6393 }
6394
6395 eir_len = 0;
6396 switch (cp->type) {
6397 case BIT(BDADDR_BREDR):
6398 eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
6399 hdev->dev_class, 3);
6400 break;
6401 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006402 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6403 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006404 hci_dev_unlock(hdev);
6405 err = mgmt_cmd_complete(sk, hdev->id,
Marcel Holtmann5082a592015-03-16 12:39:00 -07006406 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6407 MGMT_STATUS_FAILED,
6408 &cp->type, sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006409 goto done;
6410 }
6411
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006412 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
6413 memcpy(addr, &hdev->rpa, 6);
6414 addr[6] = 0x01;
6415 } else if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6416 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6417 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6418 bacmp(&hdev->static_addr, BDADDR_ANY))) {
6419 memcpy(addr, &hdev->static_addr, 6);
6420 addr[6] = 0x01;
6421 } else {
6422 memcpy(addr, &hdev->bdaddr, 6);
6423 addr[6] = 0x00;
6424 }
6425
6426 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6427 addr, sizeof(addr));
6428
6429 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6430 role = 0x02;
6431 else
6432 role = 0x01;
6433
6434 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6435 &role, sizeof(role));
6436
Marcel Holtmann5082a592015-03-16 12:39:00 -07006437 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6438 eir_len = eir_append_data(rp->eir, eir_len,
6439 EIR_LE_SC_CONFIRM,
6440 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006441
Marcel Holtmann5082a592015-03-16 12:39:00 -07006442 eir_len = eir_append_data(rp->eir, eir_len,
6443 EIR_LE_SC_RANDOM,
6444 rand, sizeof(rand));
6445 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006446
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006447 flags = get_adv_discov_flags(hdev);
6448
6449 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6450 flags |= LE_AD_NO_BREDR;
6451
6452 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6453 &flags, sizeof(flags));
6454 break;
6455 }
6456
6457 rp->type = cp->type;
6458 rp->eir_len = cpu_to_le16(eir_len);
6459
6460 hci_dev_unlock(hdev);
6461
Marcel Holtmann72000df2015-03-16 16:11:21 -07006462 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6463
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006464 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann5425f982015-03-16 16:05:44 -07006465 MGMT_STATUS_SUCCESS, rp, sizeof(*rp) + eir_len);
Marcel Holtmann72000df2015-03-16 16:11:21 -07006466 if (err < 0)
6467 goto done;
6468
6469 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6470 rp, sizeof(*rp) + eir_len,
6471 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006472
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006473done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006474 kfree(rp);
6475
6476 return err;
6477}
6478
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006479static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6480 void *data, u16 data_len)
6481{
6482 struct mgmt_rp_read_adv_features *rp;
6483 size_t rp_len;
6484 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006485 bool instance;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006486
6487 BT_DBG("%s", hdev->name);
6488
6489 hci_dev_lock(hdev);
6490
6491 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006492
6493 /* Currently only one instance is supported, so just add 1 to the
6494 * response length.
6495 */
6496 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6497 if (instance)
6498 rp_len++;
6499
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006500 rp = kmalloc(rp_len, GFP_ATOMIC);
6501 if (!rp) {
6502 hci_dev_unlock(hdev);
6503 return -ENOMEM;
6504 }
6505
6506 rp->supported_flags = cpu_to_le32(0);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006507 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6508 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006509 rp->max_instances = 1;
6510
6511 /* Currently only one instance is supported, so simply return the
6512 * current instance number.
6513 */
6514 if (instance) {
6515 rp->num_instances = 1;
6516 rp->instance[0] = 1;
6517 } else {
6518 rp->num_instances = 0;
6519 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006520
6521 hci_dev_unlock(hdev);
6522
6523 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6524 MGMT_STATUS_SUCCESS, rp, rp_len);
6525
6526 kfree(rp);
6527
6528 return err;
6529}
6530
Arman Uguray4117ed72015-03-23 15:57:14 -07006531static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
6532 u8 len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006533{
Arman Uguray4117ed72015-03-23 15:57:14 -07006534 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006535 int i, cur_len;
6536
Arman Uguray4117ed72015-03-23 15:57:14 -07006537 /* TODO: Correctly reduce len based on adv_flags. */
Arman Uguray24b4f382015-03-23 15:57:12 -07006538
Arman Uguray4117ed72015-03-23 15:57:14 -07006539 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006540 return false;
6541
Arman Uguray4117ed72015-03-23 15:57:14 -07006542 /* Make sure that the data is correctly formatted. */
6543 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6544 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006545
6546 /* If the current field length would exceed the total data
6547 * length, then it's invalid.
6548 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006549 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006550 return false;
6551 }
6552
6553 return true;
6554}
6555
Arman Uguray24b4f382015-03-23 15:57:12 -07006556static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6557 u16 opcode)
6558{
6559 struct mgmt_pending_cmd *cmd;
6560 struct mgmt_rp_add_advertising rp;
6561
6562 BT_DBG("status %d", status);
6563
6564 hci_dev_lock(hdev);
6565
6566 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6567
6568 if (status) {
6569 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6570 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6571 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6572 }
6573
6574 if (!cmd)
6575 goto unlock;
6576
6577 rp.instance = 0x01;
6578
6579 if (status)
6580 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6581 mgmt_status(status));
6582 else
6583 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6584 mgmt_status(status), &rp, sizeof(rp));
6585
6586 mgmt_pending_remove(cmd);
6587
6588unlock:
6589 hci_dev_unlock(hdev);
6590}
6591
Arman Uguray912098a2015-03-23 15:57:15 -07006592static void adv_timeout_expired(struct work_struct *work)
6593{
6594 struct hci_dev *hdev = container_of(work, struct hci_dev,
6595 adv_instance.timeout_exp.work);
6596
6597 hdev->adv_instance.timeout = 0;
6598
6599 hci_dev_lock(hdev);
6600 clear_adv_instance(hdev);
6601 hci_dev_unlock(hdev);
6602}
6603
Arman Uguray24b4f382015-03-23 15:57:12 -07006604static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6605 void *data, u16 data_len)
6606{
6607 struct mgmt_cp_add_advertising *cp = data;
6608 struct mgmt_rp_add_advertising rp;
6609 u32 flags;
6610 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006611 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006612 int err;
6613 struct mgmt_pending_cmd *cmd;
6614 struct hci_request req;
6615
6616 BT_DBG("%s", hdev->name);
6617
6618 status = mgmt_le_support(hdev);
6619 if (status)
6620 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6621 status);
6622
6623 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006624 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006625
6626 /* The current implementation only supports adding one instance and
6627 * doesn't support flags.
6628 */
6629 if (cp->instance != 0x01 || flags)
6630 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6631 MGMT_STATUS_INVALID_PARAMS);
6632
6633 hci_dev_lock(hdev);
6634
Arman Uguray912098a2015-03-23 15:57:15 -07006635 if (timeout && !hdev_is_powered(hdev)) {
6636 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6637 MGMT_STATUS_REJECTED);
6638 goto unlock;
6639 }
6640
Arman Uguray24b4f382015-03-23 15:57:12 -07006641 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006642 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006643 pending_find(MGMT_OP_SET_LE, hdev)) {
6644 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6645 MGMT_STATUS_BUSY);
6646 goto unlock;
6647 }
6648
Arman Uguray4117ed72015-03-23 15:57:14 -07006649 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len) ||
6650 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
6651 cp->scan_rsp_len)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006652 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6653 MGMT_STATUS_INVALID_PARAMS);
6654 goto unlock;
6655 }
6656
Arman Uguray912098a2015-03-23 15:57:15 -07006657 INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
6658
Arman Uguray24b4f382015-03-23 15:57:12 -07006659 hdev->adv_instance.flags = flags;
6660 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6661 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6662
6663 if (cp->adv_data_len)
6664 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6665
6666 if (cp->scan_rsp_len)
6667 memcpy(hdev->adv_instance.scan_rsp_data,
6668 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6669
Arman Uguray912098a2015-03-23 15:57:15 -07006670 if (hdev->adv_instance.timeout)
6671 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6672
6673 hdev->adv_instance.timeout = timeout;
6674
6675 if (timeout)
6676 queue_delayed_work(hdev->workqueue,
6677 &hdev->adv_instance.timeout_exp,
6678 msecs_to_jiffies(timeout * 1000));
6679
Arman Uguray24b4f382015-03-23 15:57:12 -07006680 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6681 advertising_added(sk, hdev, 1);
6682
6683 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6684 * we have no HCI communication to make. Simply return.
6685 */
6686 if (!hdev_is_powered(hdev) ||
6687 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6688 rp.instance = 0x01;
6689 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6690 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6691 goto unlock;
6692 }
6693
6694 /* We're good to go, update advertising data, parameters, and start
6695 * advertising.
6696 */
6697 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6698 data_len);
6699 if (!cmd) {
6700 err = -ENOMEM;
6701 goto unlock;
6702 }
6703
6704 hci_req_init(&req, hdev);
6705
6706 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07006707 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07006708 enable_advertising(&req);
6709
6710 err = hci_req_run(&req, add_advertising_complete);
6711 if (err < 0)
6712 mgmt_pending_remove(cmd);
6713
6714unlock:
6715 hci_dev_unlock(hdev);
6716
6717 return err;
6718}
6719
Arman Ugurayda9293352015-03-23 15:57:13 -07006720static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6721 u16 opcode)
6722{
6723 struct mgmt_pending_cmd *cmd;
6724 struct mgmt_rp_remove_advertising rp;
6725
6726 BT_DBG("status %d", status);
6727
6728 hci_dev_lock(hdev);
6729
6730 /* A failure status here only means that we failed to disable
6731 * advertising. Otherwise, the advertising instance has been removed,
6732 * so report success.
6733 */
6734 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6735 if (!cmd)
6736 goto unlock;
6737
6738 rp.instance = 1;
6739
6740 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6741 &rp, sizeof(rp));
6742 mgmt_pending_remove(cmd);
6743
6744unlock:
6745 hci_dev_unlock(hdev);
6746}
6747
6748static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6749 void *data, u16 data_len)
6750{
6751 struct mgmt_cp_remove_advertising *cp = data;
6752 struct mgmt_rp_remove_advertising rp;
6753 int err;
6754 struct mgmt_pending_cmd *cmd;
6755 struct hci_request req;
6756
6757 BT_DBG("%s", hdev->name);
6758
6759 /* The current implementation only allows modifying instance no 1. A
6760 * value of 0 indicates that all instances should be cleared.
6761 */
6762 if (cp->instance > 1)
6763 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6764 MGMT_STATUS_INVALID_PARAMS);
6765
6766 hci_dev_lock(hdev);
6767
6768 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
6769 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
6770 pending_find(MGMT_OP_SET_LE, hdev)) {
6771 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6772 MGMT_STATUS_BUSY);
6773 goto unlock;
6774 }
6775
6776 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
6777 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6778 MGMT_STATUS_INVALID_PARAMS);
6779 goto unlock;
6780 }
6781
Arman Uguray912098a2015-03-23 15:57:15 -07006782 if (hdev->adv_instance.timeout)
6783 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6784
Arman Ugurayda9293352015-03-23 15:57:13 -07006785 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6786
6787 advertising_removed(sk, hdev, 1);
6788
6789 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6790
6791 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6792 * we have no HCI communication to make. Simply return.
6793 */
6794 if (!hdev_is_powered(hdev) ||
6795 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6796 rp.instance = 1;
6797 err = mgmt_cmd_complete(sk, hdev->id,
6798 MGMT_OP_REMOVE_ADVERTISING,
6799 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6800 goto unlock;
6801 }
6802
6803 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
6804 data_len);
6805 if (!cmd) {
6806 err = -ENOMEM;
6807 goto unlock;
6808 }
6809
6810 hci_req_init(&req, hdev);
6811 disable_advertising(&req);
6812
6813 err = hci_req_run(&req, remove_advertising_complete);
6814 if (err < 0)
6815 mgmt_pending_remove(cmd);
6816
6817unlock:
6818 hci_dev_unlock(hdev);
6819
6820 return err;
6821}
6822
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006823static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006824 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006825 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006826 HCI_MGMT_NO_HDEV |
6827 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006828 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006829 HCI_MGMT_NO_HDEV |
6830 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006831 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006832 HCI_MGMT_NO_HDEV |
6833 HCI_MGMT_UNTRUSTED },
6834 { read_controller_info, MGMT_READ_INFO_SIZE,
6835 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006836 { set_powered, MGMT_SETTING_SIZE },
6837 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
6838 { set_connectable, MGMT_SETTING_SIZE },
6839 { set_fast_connectable, MGMT_SETTING_SIZE },
6840 { set_bondable, MGMT_SETTING_SIZE },
6841 { set_link_security, MGMT_SETTING_SIZE },
6842 { set_ssp, MGMT_SETTING_SIZE },
6843 { set_hs, MGMT_SETTING_SIZE },
6844 { set_le, MGMT_SETTING_SIZE },
6845 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
6846 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
6847 { add_uuid, MGMT_ADD_UUID_SIZE },
6848 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006849 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6850 HCI_MGMT_VAR_LEN },
6851 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6852 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006853 { disconnect, MGMT_DISCONNECT_SIZE },
6854 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
6855 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
6856 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6857 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
6858 { pair_device, MGMT_PAIR_DEVICE_SIZE },
6859 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6860 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
6861 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
6862 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6863 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
6864 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006865 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6866 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6867 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006868 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6869 { start_discovery, MGMT_START_DISCOVERY_SIZE },
6870 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
6871 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
6872 { block_device, MGMT_BLOCK_DEVICE_SIZE },
6873 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
6874 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
6875 { set_advertising, MGMT_SETTING_SIZE },
6876 { set_bredr, MGMT_SETTING_SIZE },
6877 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
6878 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
6879 { set_secure_conn, MGMT_SETTING_SIZE },
6880 { set_debug_keys, MGMT_SETTING_SIZE },
6881 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006882 { load_irks, MGMT_LOAD_IRKS_SIZE,
6883 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006884 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
6885 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
6886 { add_device, MGMT_ADD_DEVICE_SIZE },
6887 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006888 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6889 HCI_MGMT_VAR_LEN },
6890 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006891 HCI_MGMT_NO_HDEV |
6892 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006893 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006894 HCI_MGMT_UNCONFIGURED |
6895 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006896 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6897 HCI_MGMT_UNCONFIGURED },
6898 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6899 HCI_MGMT_UNCONFIGURED },
6900 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6901 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006902 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07006903 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006904 HCI_MGMT_NO_HDEV |
6905 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006906 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07006907 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
6908 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07006909 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006910};
6911
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006912void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006913{
Marcel Holtmannced85542015-03-14 19:27:56 -07006914 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006915
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006916 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6917 return;
6918
Marcel Holtmannf9207332015-03-14 19:27:55 -07006919 switch (hdev->dev_type) {
6920 case HCI_BREDR:
6921 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6922 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
6923 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006924 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006925 } else {
6926 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
6927 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006928 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006929 }
6930 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006931 case HCI_AMP:
6932 ev.type = 0x02;
6933 break;
6934 default:
6935 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006936 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006937
6938 ev.bus = hdev->bus;
6939
6940 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
6941 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006942}
6943
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006944void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006945{
Marcel Holtmannced85542015-03-14 19:27:56 -07006946 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02006947 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006948
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006949 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6950 return;
6951
Marcel Holtmannf9207332015-03-14 19:27:55 -07006952 switch (hdev->dev_type) {
6953 case HCI_BREDR:
6954 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006955
Marcel Holtmannf9207332015-03-14 19:27:55 -07006956 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6957 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
6958 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006959 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006960 } else {
6961 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
6962 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006963 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006964 }
6965 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006966 case HCI_AMP:
6967 ev.type = 0x02;
6968 break;
6969 default:
6970 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006971 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006972
6973 ev.bus = hdev->bus;
6974
6975 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
6976 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006977}
6978
Andre Guedes6046dc32014-02-26 20:21:51 -03006979/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006980static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006981{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006982 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006983 struct hci_conn_params *p;
6984
6985 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006986 /* Needed for AUTO_OFF case where might not "really"
6987 * have been powered off.
6988 */
6989 list_del_init(&p->action);
6990
6991 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006992 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006993 case HCI_AUTO_CONN_ALWAYS:
6994 list_add(&p->action, &hdev->pend_le_conns);
6995 break;
6996 case HCI_AUTO_CONN_REPORT:
6997 list_add(&p->action, &hdev->pend_le_reports);
6998 break;
6999 default:
7000 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007001 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007002 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007003
Johan Hedberg2cf22212014-12-19 22:26:00 +02007004 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007005}
7006
Marcel Holtmann1904a852015-01-11 13:50:44 -08007007static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007008{
7009 struct cmd_lookup match = { NULL, hdev };
7010
7011 BT_DBG("status 0x%02x", status);
7012
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007013 if (!status) {
7014 /* Register the available SMP channels (BR/EDR and LE) only
7015 * when successfully powering on the controller. This late
7016 * registration is required so that LE SMP can clearly
7017 * decide if the public address or static address is used.
7018 */
7019 smp_register(hdev);
7020 }
7021
Johan Hedberg229ab392013-03-15 17:06:53 -05007022 hci_dev_lock(hdev);
7023
7024 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7025
7026 new_settings(hdev, match.sk);
7027
7028 hci_dev_unlock(hdev);
7029
7030 if (match.sk)
7031 sock_put(match.sk);
7032}
7033
Johan Hedberg70da6242013-03-15 17:06:51 -05007034static int powered_update_hci(struct hci_dev *hdev)
7035{
Johan Hedberg890ea892013-03-15 17:06:52 -05007036 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007037 u8 link_sec;
7038
Johan Hedberg890ea892013-03-15 17:06:52 -05007039 hci_req_init(&req, hdev);
7040
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007041 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007042 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007043 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007044
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007045 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007046
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007047 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7048 u8 support = 0x01;
7049
7050 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7051 sizeof(support), &support);
7052 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007053 }
7054
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007055 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007056 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007057 struct hci_cp_write_le_host_supported cp;
7058
Marcel Holtmann32226e42014-07-24 20:04:16 +02007059 cp.le = 0x01;
7060 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007061
7062 /* Check first if we already have the right
7063 * host state (host features set)
7064 */
7065 if (cp.le != lmp_host_le_capable(hdev) ||
7066 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007067 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7068 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007069 }
7070
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007071 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007072 /* Make sure the controller has a good default for
7073 * advertising data. This also applies to the case
7074 * where BR/EDR was toggled during the AUTO_OFF phase.
7075 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007076 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007077 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007078 update_scan_rsp_data(&req);
7079 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007080
Arman Uguray24b4f382015-03-23 15:57:12 -07007081 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7082 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007083 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007084
7085 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007086 }
7087
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007088 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007089 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007090 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7091 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007092
7093 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007094 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007095 write_fast_connectable(&req, true);
7096 else
7097 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007098 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007099 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007100 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007101 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007102 }
7103
Johan Hedberg229ab392013-03-15 17:06:53 -05007104 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007105}
7106
Johan Hedberg744cf192011-11-08 20:40:14 +02007107int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007108{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007109 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007110 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007111 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007112
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007113 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007114 return 0;
7115
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007116 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007117 if (powered_update_hci(hdev) == 0)
7118 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007119
Johan Hedberg229ab392013-03-15 17:06:53 -05007120 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7121 &match);
7122 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007123 }
7124
Johan Hedberg229ab392013-03-15 17:06:53 -05007125 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007126
7127 /* If the power off is because of hdev unregistration let
7128 * use the appropriate INVALID_INDEX status. Otherwise use
7129 * NOT_POWERED. We cover both scenarios here since later in
7130 * mgmt_index_removed() any hci_conn callbacks will have already
7131 * been triggered, potentially causing misleading DISCONNECTED
7132 * status responses.
7133 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007134 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007135 status = MGMT_STATUS_INVALID_INDEX;
7136 else
7137 status = MGMT_STATUS_NOT_POWERED;
7138
7139 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007140
7141 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007142 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7143 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007144
7145new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007146 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007147
7148 if (match.sk)
7149 sock_put(match.sk);
7150
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007151 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007152}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007153
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007154void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007155{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007156 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007157 u8 status;
7158
Johan Hedberg333ae952015-03-17 13:48:47 +02007159 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007160 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007161 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007162
7163 if (err == -ERFKILL)
7164 status = MGMT_STATUS_RFKILLED;
7165 else
7166 status = MGMT_STATUS_FAILED;
7167
Johan Hedberga69e8372015-03-06 21:08:53 +02007168 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007169
7170 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007171}
7172
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007173void mgmt_discoverable_timeout(struct hci_dev *hdev)
7174{
7175 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007176
7177 hci_dev_lock(hdev);
7178
7179 /* When discoverable timeout triggers, then just make sure
7180 * the limited discoverable flag is cleared. Even in the case
7181 * of a timeout triggered from general discoverable, it is
7182 * safe to unconditionally clear the flag.
7183 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007184 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7185 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007186
7187 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007188 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007189 u8 scan = SCAN_PAGE;
7190 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7191 sizeof(scan), &scan);
7192 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007193 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007194
7195 /* Advertising instances don't use the global discoverable setting, so
7196 * only update AD if advertising was enabled using Set Advertising.
7197 */
7198 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7199 update_adv_data(&req);
7200
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007201 hci_req_run(&req, NULL);
7202
7203 hdev->discov_timeout = 0;
7204
Johan Hedberg9a43e252013-10-20 19:00:07 +03007205 new_settings(hdev, NULL);
7206
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007207 hci_dev_unlock(hdev);
7208}
7209
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007210void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7211 bool persistent)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02007212{
Johan Hedberg86742e12011-11-07 23:13:38 +02007213 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02007214
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007215 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02007216
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007217 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007218 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007219 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007220 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007221 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007222 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02007223
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007224 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02007225}
Johan Hedbergf7520542011-01-20 12:34:39 +02007226
Johan Hedbergd7b25452014-05-23 13:19:53 +03007227static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7228{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007229 switch (ltk->type) {
7230 case SMP_LTK:
7231 case SMP_LTK_SLAVE:
7232 if (ltk->authenticated)
7233 return MGMT_LTK_AUTHENTICATED;
7234 return MGMT_LTK_UNAUTHENTICATED;
7235 case SMP_LTK_P256:
7236 if (ltk->authenticated)
7237 return MGMT_LTK_P256_AUTH;
7238 return MGMT_LTK_P256_UNAUTH;
7239 case SMP_LTK_P256_DEBUG:
7240 return MGMT_LTK_P256_DEBUG;
7241 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007242
7243 return MGMT_LTK_UNAUTHENTICATED;
7244}
7245
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007246void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007247{
7248 struct mgmt_ev_new_long_term_key ev;
7249
7250 memset(&ev, 0, sizeof(ev));
7251
Marcel Holtmann5192d302014-02-19 17:11:58 -08007252 /* Devices using resolvable or non-resolvable random addresses
7253 * without providing an indentity resolving key don't require
7254 * to store long term keys. Their addresses will change the
7255 * next time around.
7256 *
7257 * Only when a remote device provides an identity address
7258 * make sure the long term key is stored. If the remote
7259 * identity is known, the long term keys are internally
7260 * mapped to the identity address. So allow static random
7261 * and public addresses here.
7262 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007263 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7264 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7265 ev.store_hint = 0x00;
7266 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007267 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007268
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007269 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007270 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007271 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007272 ev.key.enc_size = key->enc_size;
7273 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007274 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007275
Johan Hedberg2ceba532014-06-16 19:25:16 +03007276 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007277 ev.key.master = 1;
7278
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007279 memcpy(ev.key.val, key->val, sizeof(key->val));
7280
Marcel Holtmann083368f2013-10-15 14:26:29 -07007281 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007282}
7283
Johan Hedberg95fbac82014-02-19 15:18:31 +02007284void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7285{
7286 struct mgmt_ev_new_irk ev;
7287
7288 memset(&ev, 0, sizeof(ev));
7289
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007290 /* For identity resolving keys from devices that are already
7291 * using a public address or static random address, do not
7292 * ask for storing this key. The identity resolving key really
7293 * is only mandatory for devices using resovlable random
7294 * addresses.
7295 *
7296 * Storing all identity resolving keys has the downside that
7297 * they will be also loaded on next boot of they system. More
7298 * identity resolving keys, means more time during scanning is
7299 * needed to actually resolve these addresses.
7300 */
7301 if (bacmp(&irk->rpa, BDADDR_ANY))
7302 ev.store_hint = 0x01;
7303 else
7304 ev.store_hint = 0x00;
7305
Johan Hedberg95fbac82014-02-19 15:18:31 +02007306 bacpy(&ev.rpa, &irk->rpa);
7307 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7308 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7309 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7310
7311 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7312}
7313
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007314void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7315 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007316{
7317 struct mgmt_ev_new_csrk ev;
7318
7319 memset(&ev, 0, sizeof(ev));
7320
7321 /* Devices using resolvable or non-resolvable random addresses
7322 * without providing an indentity resolving key don't require
7323 * to store signature resolving keys. Their addresses will change
7324 * the next time around.
7325 *
7326 * Only when a remote device provides an identity address
7327 * make sure the signature resolving key is stored. So allow
7328 * static random and public addresses here.
7329 */
7330 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7331 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7332 ev.store_hint = 0x00;
7333 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007334 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007335
7336 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7337 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007338 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007339 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7340
7341 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7342}
7343
Andre Guedesffb5a8272014-07-01 18:10:11 -03007344void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007345 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7346 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007347{
7348 struct mgmt_ev_new_conn_param ev;
7349
Johan Hedbergc103aea2014-07-02 17:37:34 +03007350 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7351 return;
7352
Andre Guedesffb5a8272014-07-01 18:10:11 -03007353 memset(&ev, 0, sizeof(ev));
7354 bacpy(&ev.addr.bdaddr, bdaddr);
7355 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007356 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007357 ev.min_interval = cpu_to_le16(min_interval);
7358 ev.max_interval = cpu_to_le16(max_interval);
7359 ev.latency = cpu_to_le16(latency);
7360 ev.timeout = cpu_to_le16(timeout);
7361
7362 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7363}
7364
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007365void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7366 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007367{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007368 char buf[512];
7369 struct mgmt_ev_device_connected *ev = (void *) buf;
7370 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007371
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007372 bacpy(&ev->addr.bdaddr, &conn->dst);
7373 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007374
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007375 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007376
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007377 /* We must ensure that the EIR Data fields are ordered and
7378 * unique. Keep it simple for now and avoid the problem by not
7379 * adding any BR/EDR data to the LE adv.
7380 */
7381 if (conn->le_adv_data_len > 0) {
7382 memcpy(&ev->eir[eir_len],
7383 conn->le_adv_data, conn->le_adv_data_len);
7384 eir_len = conn->le_adv_data_len;
7385 } else {
7386 if (name_len > 0)
7387 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7388 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007389
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007390 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007391 eir_len = eir_append_data(ev->eir, eir_len,
7392 EIR_CLASS_OF_DEV,
7393 conn->dev_class, 3);
7394 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007395
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007396 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007397
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007398 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7399 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007400}
7401
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007402static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007403{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007404 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007405
Johan Hedbergf5818c22014-12-05 13:36:02 +02007406 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007407
7408 *sk = cmd->sk;
7409 sock_hold(*sk);
7410
Johan Hedberga664b5b2011-02-19 12:06:02 -03007411 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007412}
7413
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007414static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007415{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007416 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007417 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007418
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007419 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7420
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007421 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007422 mgmt_pending_remove(cmd);
7423}
7424
Johan Hedberg84c61d92014-08-01 11:13:30 +03007425bool mgmt_powering_down(struct hci_dev *hdev)
7426{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007427 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007428 struct mgmt_mode *cp;
7429
Johan Hedberg333ae952015-03-17 13:48:47 +02007430 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007431 if (!cmd)
7432 return false;
7433
7434 cp = cmd->param;
7435 if (!cp->val)
7436 return true;
7437
7438 return false;
7439}
7440
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007441void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007442 u8 link_type, u8 addr_type, u8 reason,
7443 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007444{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007445 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007446 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007447
Johan Hedberg84c61d92014-08-01 11:13:30 +03007448 /* The connection is still in hci_conn_hash so test for 1
7449 * instead of 0 to know if this is the last one.
7450 */
7451 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7452 cancel_delayed_work(&hdev->power_off);
7453 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007454 }
7455
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007456 if (!mgmt_connected)
7457 return;
7458
Andre Guedes57eb7762013-10-30 19:01:41 -03007459 if (link_type != ACL_LINK && link_type != LE_LINK)
7460 return;
7461
Johan Hedberg744cf192011-11-08 20:40:14 +02007462 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007463
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007464 bacpy(&ev.addr.bdaddr, bdaddr);
7465 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7466 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007467
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007468 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007469
7470 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007471 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007472
Johan Hedberg124f6e32012-02-09 13:50:12 +02007473 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007474 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007475}
7476
Marcel Holtmann78929242013-10-06 23:55:47 -07007477void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7478 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007479{
Andre Guedes3655bba2013-10-30 19:01:40 -03007480 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7481 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007482 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007483
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007484 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7485 hdev);
7486
Johan Hedberg333ae952015-03-17 13:48:47 +02007487 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007488 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007489 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007490
Andre Guedes3655bba2013-10-30 19:01:40 -03007491 cp = cmd->param;
7492
7493 if (bacmp(bdaddr, &cp->addr.bdaddr))
7494 return;
7495
7496 if (cp->addr.type != bdaddr_type)
7497 return;
7498
Johan Hedbergf5818c22014-12-05 13:36:02 +02007499 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007500 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007501}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007502
Marcel Holtmann445608d2013-10-06 23:55:48 -07007503void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7504 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007505{
7506 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007507
Johan Hedberg84c61d92014-08-01 11:13:30 +03007508 /* The connection is still in hci_conn_hash so test for 1
7509 * instead of 0 to know if this is the last one.
7510 */
7511 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7512 cancel_delayed_work(&hdev->power_off);
7513 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007514 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007515
Johan Hedberg4c659c32011-11-07 23:13:39 +02007516 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007517 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007518 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007519
Marcel Holtmann445608d2013-10-06 23:55:48 -07007520 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007521}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007522
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007523void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007524{
7525 struct mgmt_ev_pin_code_request ev;
7526
Johan Hedbergd8457692012-02-17 14:24:57 +02007527 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007528 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007529 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007530
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007531 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007532}
7533
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007534void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7535 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007536{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007537 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007538
Johan Hedberg333ae952015-03-17 13:48:47 +02007539 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007540 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007541 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007542
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007543 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007544 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007545}
7546
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007547void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7548 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007549{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007550 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007551
Johan Hedberg333ae952015-03-17 13:48:47 +02007552 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007553 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007554 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007555
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007556 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007557 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007558}
Johan Hedberga5c29682011-02-19 12:05:57 -03007559
Johan Hedberg744cf192011-11-08 20:40:14 +02007560int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007561 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007562 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007563{
7564 struct mgmt_ev_user_confirm_request ev;
7565
Johan Hedberg744cf192011-11-08 20:40:14 +02007566 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007567
Johan Hedberg272d90d2012-02-09 15:26:12 +02007568 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007569 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007570 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007571 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007572
Johan Hedberg744cf192011-11-08 20:40:14 +02007573 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007574 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007575}
7576
Johan Hedberg272d90d2012-02-09 15:26:12 +02007577int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007578 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007579{
7580 struct mgmt_ev_user_passkey_request ev;
7581
7582 BT_DBG("%s", hdev->name);
7583
Johan Hedberg272d90d2012-02-09 15:26:12 +02007584 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007585 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007586
7587 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007588 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007589}
7590
Brian Gix0df4c182011-11-16 13:53:13 -08007591static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007592 u8 link_type, u8 addr_type, u8 status,
7593 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007594{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007595 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007596
Johan Hedberg333ae952015-03-17 13:48:47 +02007597 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007598 if (!cmd)
7599 return -ENOENT;
7600
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007601 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007602 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007603
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007604 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007605}
7606
Johan Hedberg744cf192011-11-08 20:40:14 +02007607int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007608 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007609{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007610 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007611 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007612}
7613
Johan Hedberg272d90d2012-02-09 15:26:12 +02007614int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007615 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007616{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007617 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007618 status,
7619 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007620}
Johan Hedberg2a611692011-02-19 12:06:00 -03007621
Brian Gix604086b2011-11-23 08:28:33 -08007622int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007623 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007624{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007625 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007626 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007627}
7628
Johan Hedberg272d90d2012-02-09 15:26:12 +02007629int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007630 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007631{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007632 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007633 status,
7634 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007635}
7636
Johan Hedberg92a25252012-09-06 18:39:26 +03007637int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7638 u8 link_type, u8 addr_type, u32 passkey,
7639 u8 entered)
7640{
7641 struct mgmt_ev_passkey_notify ev;
7642
7643 BT_DBG("%s", hdev->name);
7644
7645 bacpy(&ev.addr.bdaddr, bdaddr);
7646 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7647 ev.passkey = __cpu_to_le32(passkey);
7648 ev.entered = entered;
7649
7650 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7651}
7652
Johan Hedberge1e930f2014-09-08 17:09:49 -07007653void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007654{
7655 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007656 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007657 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007658
Johan Hedberge1e930f2014-09-08 17:09:49 -07007659 bacpy(&ev.addr.bdaddr, &conn->dst);
7660 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7661 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007662
Johan Hedberge1e930f2014-09-08 17:09:49 -07007663 cmd = find_pairing(conn);
7664
7665 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7666 cmd ? cmd->sk : NULL);
7667
Johan Hedberga511b352014-12-11 21:45:45 +02007668 if (cmd) {
7669 cmd->cmd_complete(cmd, status);
7670 mgmt_pending_remove(cmd);
7671 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007672}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007673
Marcel Holtmann464996a2013-10-15 14:26:24 -07007674void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007675{
7676 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007677 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007678
7679 if (status) {
7680 u8 mgmt_err = mgmt_status(status);
7681 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007682 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007683 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007684 }
7685
Marcel Holtmann464996a2013-10-15 14:26:24 -07007686 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007687 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007688 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007689 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007690
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007691 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007692 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007693
Johan Hedberg47990ea2012-02-22 11:58:37 +02007694 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007695 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007696
7697 if (match.sk)
7698 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007699}
7700
Johan Hedberg890ea892013-03-15 17:06:52 -05007701static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007702{
Johan Hedberg890ea892013-03-15 17:06:52 -05007703 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007704 struct hci_cp_write_eir cp;
7705
Johan Hedberg976eb202012-10-24 21:12:01 +03007706 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007707 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007708
Johan Hedbergc80da272012-02-22 15:38:48 +02007709 memset(hdev->eir, 0, sizeof(hdev->eir));
7710
Johan Hedbergcacaf522012-02-21 00:52:42 +02007711 memset(&cp, 0, sizeof(cp));
7712
Johan Hedberg890ea892013-03-15 17:06:52 -05007713 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007714}
7715
Marcel Holtmann3e248562013-10-15 14:26:25 -07007716void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007717{
7718 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007719 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007720 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007721
7722 if (status) {
7723 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007724
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007725 if (enable && hci_dev_test_and_clear_flag(hdev,
7726 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007727 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007728 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007729 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007730
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007731 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7732 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007733 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007734 }
7735
7736 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007737 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007738 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007739 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007740 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007741 changed = hci_dev_test_and_clear_flag(hdev,
7742 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007743 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007744 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007745 }
7746
7747 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7748
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007749 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007750 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007751
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007752 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007753 sock_put(match.sk);
7754
Johan Hedberg890ea892013-03-15 17:06:52 -05007755 hci_req_init(&req, hdev);
7756
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007757 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7758 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007759 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7760 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007761 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007762 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007763 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007764 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007765
7766 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007767}
7768
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007769static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007770{
7771 struct cmd_lookup *match = data;
7772
Johan Hedberg90e70452012-02-23 23:09:40 +02007773 if (match->sk == NULL) {
7774 match->sk = cmd->sk;
7775 sock_hold(match->sk);
7776 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007777}
7778
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007779void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7780 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007781{
Johan Hedberg90e70452012-02-23 23:09:40 +02007782 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007783
Johan Hedberg92da6092013-03-15 17:06:55 -05007784 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7785 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7786 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007787
7788 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007789 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7790 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007791
7792 if (match.sk)
7793 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007794}
7795
Marcel Holtmann7667da32013-10-15 14:26:27 -07007796void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007797{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007798 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007799 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007800
Johan Hedberg13928972013-03-15 17:07:00 -05007801 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007802 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007803
7804 memset(&ev, 0, sizeof(ev));
7805 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007806 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007807
Johan Hedberg333ae952015-03-17 13:48:47 +02007808 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007809 if (!cmd) {
7810 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007811
Johan Hedberg13928972013-03-15 17:07:00 -05007812 /* If this is a HCI command related to powering on the
7813 * HCI dev don't send any mgmt signals.
7814 */
Johan Hedberg333ae952015-03-17 13:48:47 +02007815 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007816 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007817 }
7818
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007819 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7820 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007821}
Szymon Jancc35938b2011-03-22 13:12:21 +01007822
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007823void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007824 u8 *rand192, u8 *hash256, u8 *rand256,
7825 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007826{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007827 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007828
Johan Hedberg744cf192011-11-08 20:40:14 +02007829 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007830
Johan Hedberg333ae952015-03-17 13:48:47 +02007831 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007832 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007833 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007834
7835 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007836 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7837 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007838 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007839 struct mgmt_rp_read_local_oob_data rp;
7840 size_t rp_size = sizeof(rp);
7841
7842 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7843 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7844
Johan Hedberg710f11c2014-05-26 11:21:22 +03007845 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007846 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007847 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007848 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007849 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007850 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007851
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007852 mgmt_cmd_complete(cmd->sk, hdev->id,
7853 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7854 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007855 }
7856
7857 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007858}
Johan Hedberge17acd42011-03-30 23:57:16 +03007859
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007860static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7861{
7862 int i;
7863
7864 for (i = 0; i < uuid_count; i++) {
7865 if (!memcmp(uuid, uuids[i], 16))
7866 return true;
7867 }
7868
7869 return false;
7870}
7871
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007872static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7873{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007874 u16 parsed = 0;
7875
7876 while (parsed < eir_len) {
7877 u8 field_len = eir[0];
7878 u8 uuid[16];
7879 int i;
7880
7881 if (field_len == 0)
7882 break;
7883
7884 if (eir_len - parsed < field_len + 1)
7885 break;
7886
7887 switch (eir[1]) {
7888 case EIR_UUID16_ALL:
7889 case EIR_UUID16_SOME:
7890 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007891 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007892 uuid[13] = eir[i + 3];
7893 uuid[12] = eir[i + 2];
7894 if (has_uuid(uuid, uuid_count, uuids))
7895 return true;
7896 }
7897 break;
7898 case EIR_UUID32_ALL:
7899 case EIR_UUID32_SOME:
7900 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007901 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007902 uuid[15] = eir[i + 5];
7903 uuid[14] = eir[i + 4];
7904 uuid[13] = eir[i + 3];
7905 uuid[12] = eir[i + 2];
7906 if (has_uuid(uuid, uuid_count, uuids))
7907 return true;
7908 }
7909 break;
7910 case EIR_UUID128_ALL:
7911 case EIR_UUID128_SOME:
7912 for (i = 0; i + 17 <= field_len; i += 16) {
7913 memcpy(uuid, eir + i + 2, 16);
7914 if (has_uuid(uuid, uuid_count, uuids))
7915 return true;
7916 }
7917 break;
7918 }
7919
7920 parsed += field_len + 1;
7921 eir += field_len + 1;
7922 }
7923
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007924 return false;
7925}
7926
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007927static void restart_le_scan(struct hci_dev *hdev)
7928{
7929 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007930 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007931 return;
7932
7933 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7934 hdev->discovery.scan_start +
7935 hdev->discovery.scan_duration))
7936 return;
7937
7938 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7939 DISCOV_LE_RESTART_DELAY);
7940}
7941
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007942static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7943 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7944{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007945 /* If a RSSI threshold has been specified, and
7946 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7947 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7948 * is set, let it through for further processing, as we might need to
7949 * restart the scan.
7950 *
7951 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7952 * the results are also dropped.
7953 */
7954 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7955 (rssi == HCI_RSSI_INVALID ||
7956 (rssi < hdev->discovery.rssi &&
7957 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7958 return false;
7959
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007960 if (hdev->discovery.uuid_count != 0) {
7961 /* If a list of UUIDs is provided in filter, results with no
7962 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007963 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007964 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7965 hdev->discovery.uuids) &&
7966 !eir_has_uuids(scan_rsp, scan_rsp_len,
7967 hdev->discovery.uuid_count,
7968 hdev->discovery.uuids))
7969 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007970 }
7971
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007972 /* If duplicate filtering does not report RSSI changes, then restart
7973 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007974 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007975 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7976 restart_le_scan(hdev);
7977
7978 /* Validate RSSI value against the RSSI threshold once more. */
7979 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7980 rssi < hdev->discovery.rssi)
7981 return false;
7982 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007983
7984 return true;
7985}
7986
Marcel Holtmann901801b2013-10-06 23:55:51 -07007987void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007988 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7989 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007990{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007991 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007992 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007993 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007994
Johan Hedberg75ce2082014-07-02 22:42:01 +03007995 /* Don't send events for a non-kernel initiated discovery. With
7996 * LE one exception is if we have pend_le_reports > 0 in which
7997 * case we're doing passive scanning and want these events.
7998 */
7999 if (!hci_discovery_active(hdev)) {
8000 if (link_type == ACL_LINK)
8001 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008002 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008003 return;
8004 }
Andre Guedes12602d02013-04-30 15:29:40 -03008005
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008006 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008007 /* We are using service discovery */
8008 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8009 scan_rsp_len))
8010 return;
8011 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008012
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008013 /* Make sure that the buffer is big enough. The 5 extra bytes
8014 * are for the potential CoD field.
8015 */
8016 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008017 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008018
Johan Hedberg1dc06092012-01-15 21:01:23 +02008019 memset(buf, 0, sizeof(buf));
8020
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008021 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8022 * RSSI value was reported as 0 when not available. This behavior
8023 * is kept when using device discovery. This is required for full
8024 * backwards compatibility with the API.
8025 *
8026 * However when using service discovery, the value 127 will be
8027 * returned when the RSSI is not available.
8028 */
Szymon Janc91200e92015-01-22 16:57:05 +01008029 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8030 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008031 rssi = 0;
8032
Johan Hedberg841c5642014-07-07 12:45:54 +03008033 bacpy(&ev->addr.bdaddr, bdaddr);
8034 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008035 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008036 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008037
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008038 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008039 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008040 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008041
Johan Hedberg1dc06092012-01-15 21:01:23 +02008042 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8043 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008044 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008045
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008046 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008047 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008048 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008049
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008050 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8051 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008052
Marcel Holtmann901801b2013-10-06 23:55:51 -07008053 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008054}
Johan Hedberga88a9652011-03-30 13:18:12 +03008055
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008056void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8057 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008058{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008059 struct mgmt_ev_device_found *ev;
8060 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8061 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008062
Johan Hedbergb644ba32012-01-17 21:48:47 +02008063 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008064
Johan Hedbergb644ba32012-01-17 21:48:47 +02008065 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008066
Johan Hedbergb644ba32012-01-17 21:48:47 +02008067 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008068 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008069 ev->rssi = rssi;
8070
8071 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008072 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008073
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008074 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008075
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008076 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008077}
Johan Hedberg314b2382011-04-27 10:29:57 -04008078
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008079void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008080{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008081 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008082
Andre Guedes343fb142011-11-22 17:14:19 -03008083 BT_DBG("%s discovering %u", hdev->name, discovering);
8084
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008085 memset(&ev, 0, sizeof(ev));
8086 ev.type = hdev->discovery.type;
8087 ev.discovering = discovering;
8088
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008089 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008090}
Antti Julku5e762442011-08-25 16:48:02 +03008091
Marcel Holtmann1904a852015-01-11 13:50:44 -08008092static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008093{
8094 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008095}
8096
8097void mgmt_reenable_advertising(struct hci_dev *hdev)
8098{
8099 struct hci_request req;
8100
Arman Uguray24b4f382015-03-23 15:57:12 -07008101 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8102 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008103 return;
8104
8105 hci_req_init(&req, hdev);
8106 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008107 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008108}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008109
8110static struct hci_mgmt_chan chan = {
8111 .channel = HCI_CHANNEL_CONTROL,
8112 .handler_count = ARRAY_SIZE(mgmt_handlers),
8113 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008114 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008115};
8116
8117int mgmt_init(void)
8118{
8119 return hci_mgmt_chan_register(&chan);
8120}
8121
8122void mgmt_exit(void)
8123{
8124 hci_mgmt_chan_unregister(&chan);
8125}