blob: 797cf6cf958f00a877cf580bd77ad1a62ca31d71 [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
Marcel Holtmann08dc0e92015-03-25 18:32:13 -0700696 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800697 * address is actually used decides if the flag is set or not.
698 *
699 * For single mode LE only controllers and dual-mode controllers
700 * with BR/EDR disabled, the existence of the static address will
701 * be evaluated.
702 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700703 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700704 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
706 if (bacmp(&hdev->static_addr, BDADDR_ANY))
707 settings |= MGMT_SETTING_STATIC_ADDRESS;
708 }
709
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200710 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200711}
712
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300713#define PNP_INFO_SVCLASS_ID 0x1200
714
Johan Hedberg213202e2013-01-27 00:31:33 +0200715static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 4)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 u16 uuid16;
725
726 if (uuid->size != 16)
727 continue;
728
729 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
730 if (uuid16 < 0x1100)
731 continue;
732
733 if (uuid16 == PNP_INFO_SVCLASS_ID)
734 continue;
735
736 if (!uuids_start) {
737 uuids_start = ptr;
738 uuids_start[0] = 1;
739 uuids_start[1] = EIR_UUID16_ALL;
740 ptr += 2;
741 }
742
743 /* Stop if not enough space to put next UUID */
744 if ((ptr - data) + sizeof(u16) > len) {
745 uuids_start[1] = EIR_UUID16_SOME;
746 break;
747 }
748
749 *ptr++ = (uuid16 & 0x00ff);
750 *ptr++ = (uuid16 & 0xff00) >> 8;
751 uuids_start[0] += sizeof(uuid16);
752 }
753
754 return ptr;
755}
756
Johan Hedbergcdf19632013-01-27 00:31:34 +0200757static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
758{
759 u8 *ptr = data, *uuids_start = NULL;
760 struct bt_uuid *uuid;
761
762 if (len < 6)
763 return ptr;
764
765 list_for_each_entry(uuid, &hdev->uuids, list) {
766 if (uuid->size != 32)
767 continue;
768
769 if (!uuids_start) {
770 uuids_start = ptr;
771 uuids_start[0] = 1;
772 uuids_start[1] = EIR_UUID32_ALL;
773 ptr += 2;
774 }
775
776 /* Stop if not enough space to put next UUID */
777 if ((ptr - data) + sizeof(u32) > len) {
778 uuids_start[1] = EIR_UUID32_SOME;
779 break;
780 }
781
782 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
783 ptr += sizeof(u32);
784 uuids_start[0] += sizeof(u32);
785 }
786
787 return ptr;
788}
789
Johan Hedbergc00d5752013-01-27 00:31:35 +0200790static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
791{
792 u8 *ptr = data, *uuids_start = NULL;
793 struct bt_uuid *uuid;
794
795 if (len < 18)
796 return ptr;
797
798 list_for_each_entry(uuid, &hdev->uuids, list) {
799 if (uuid->size != 128)
800 continue;
801
802 if (!uuids_start) {
803 uuids_start = ptr;
804 uuids_start[0] = 1;
805 uuids_start[1] = EIR_UUID128_ALL;
806 ptr += 2;
807 }
808
809 /* Stop if not enough space to put next UUID */
810 if ((ptr - data) + 16 > len) {
811 uuids_start[1] = EIR_UUID128_SOME;
812 break;
813 }
814
815 memcpy(ptr, uuid->uuid, 16);
816 ptr += 16;
817 uuids_start[0] += 16;
818 }
819
820 return ptr;
821}
822
Johan Hedberg333ae952015-03-17 13:48:47 +0200823static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
824{
825 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
826}
827
Johan Hedberg333ae952015-03-17 13:48:47 +0200828static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
829 struct hci_dev *hdev,
830 const void *data)
831{
832 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
833}
834
Arman Uguray4117ed72015-03-23 15:57:14 -0700835static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700836{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700837 u8 ad_len = 0;
838 size_t name_len;
839
840 name_len = strlen(hdev->dev_name);
841 if (name_len > 0) {
842 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
843
844 if (name_len > max_len) {
845 name_len = max_len;
846 ptr[1] = EIR_NAME_SHORT;
847 } else
848 ptr[1] = EIR_NAME_COMPLETE;
849
850 ptr[0] = name_len + 1;
851
852 memcpy(ptr + 2, hdev->dev_name, name_len);
853
854 ad_len += (name_len + 2);
855 ptr += (name_len + 2);
856 }
857
858 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700859}
860
Arman Uguray4117ed72015-03-23 15:57:14 -0700861static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
862{
863 /* TODO: Set the appropriate entries based on advertising instance flags
864 * here once flags other than 0 are supported.
865 */
866 memcpy(ptr, hdev->adv_instance.scan_rsp_data,
867 hdev->adv_instance.scan_rsp_len);
868
869 return hdev->adv_instance.scan_rsp_len;
870}
871
872static void update_scan_rsp_data_for_instance(struct hci_request *req,
873 u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700874{
875 struct hci_dev *hdev = req->hdev;
876 struct hci_cp_le_set_scan_rsp_data cp;
877 u8 len;
878
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700880 return;
881
882 memset(&cp, 0, sizeof(cp));
883
Arman Uguray4117ed72015-03-23 15:57:14 -0700884 if (instance)
885 len = create_instance_scan_rsp_data(hdev, cp.data);
886 else
887 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700888
Johan Hedbergeb438b52013-10-16 15:31:07 +0300889 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700890 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700891 return;
892
Johan Hedbergeb438b52013-10-16 15:31:07 +0300893 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
894 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700895
896 cp.length = len;
897
898 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
899}
900
Arman Uguray4117ed72015-03-23 15:57:14 -0700901static void update_scan_rsp_data(struct hci_request *req)
902{
903 struct hci_dev *hdev = req->hdev;
904 u8 instance;
905
906 /* The "Set Advertising" setting supersedes the "Add Advertising"
907 * setting. Here we set the scan response data based on which
908 * setting was set. When neither apply, default to the global settings,
909 * represented by instance "0".
910 */
911 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
912 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
913 instance = 0x01;
914 else
915 instance = 0x00;
916
917 update_scan_rsp_data_for_instance(req, instance);
918}
919
Johan Hedberg9a43e252013-10-20 19:00:07 +0300920static u8 get_adv_discov_flags(struct hci_dev *hdev)
921{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200922 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300923
924 /* If there's a pending mgmt command the flags will not yet have
925 * their final values, so check for this first.
926 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200927 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300928 if (cmd) {
929 struct mgmt_mode *cp = cmd->param;
930 if (cp->val == 0x01)
931 return LE_AD_GENERAL;
932 else if (cp->val == 0x02)
933 return LE_AD_LIMITED;
934 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700935 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300936 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700937 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300938 return LE_AD_GENERAL;
939 }
940
941 return 0;
942}
943
Arman Uguray24b4f382015-03-23 15:57:12 -0700944static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700945{
946 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700947
Johan Hedberg9a43e252013-10-20 19:00:07 +0300948 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700949
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700950 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700951 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700952
953 if (flags) {
954 BT_DBG("adv flags 0x%02x", flags);
955
956 ptr[0] = 2;
957 ptr[1] = EIR_FLAGS;
958 ptr[2] = flags;
959
960 ad_len += 3;
961 ptr += 3;
962 }
963
964 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
965 ptr[0] = 2;
966 ptr[1] = EIR_TX_POWER;
967 ptr[2] = (u8) hdev->adv_tx_power;
968
969 ad_len += 3;
970 ptr += 3;
971 }
972
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700973 return ad_len;
974}
975
Arman Uguray24b4f382015-03-23 15:57:12 -0700976static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
977{
Arman Ugurayb44133f2015-03-25 18:53:41 -0700978 u8 ad_len = 0, flags = 0;
979
Arman Uguray807ec772015-03-25 18:53:42 -0700980 /* The Add Advertising command allows userspace to set both the general
981 * and limited discoverable flags.
982 */
Arman Ugurayb44133f2015-03-25 18:53:41 -0700983 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV)
984 flags |= LE_AD_GENERAL;
985
Arman Uguray807ec772015-03-25 18:53:42 -0700986 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
987 flags |= LE_AD_LIMITED;
988
Arman Ugurayb44133f2015-03-25 18:53:41 -0700989 if (flags) {
990 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
991 flags |= LE_AD_NO_BREDR;
992
993 ptr[0] = 0x02;
994 ptr[1] = EIR_FLAGS;
995 ptr[2] = flags;
996
997 ad_len += 3;
998 ptr += 3;
999 }
1000
Arman Uguray24b4f382015-03-23 15:57:12 -07001001 memcpy(ptr, hdev->adv_instance.adv_data,
1002 hdev->adv_instance.adv_data_len);
Arman Ugurayb44133f2015-03-25 18:53:41 -07001003 ad_len += hdev->adv_instance.adv_data_len;
Arman Uguray24b4f382015-03-23 15:57:12 -07001004
Arman Ugurayb44133f2015-03-25 18:53:41 -07001005 return ad_len;
Arman Uguray24b4f382015-03-23 15:57:12 -07001006}
1007
1008static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001009{
1010 struct hci_dev *hdev = req->hdev;
1011 struct hci_cp_le_set_adv_data cp;
1012 u8 len;
1013
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001014 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001015 return;
1016
1017 memset(&cp, 0, sizeof(cp));
1018
Arman Uguray24b4f382015-03-23 15:57:12 -07001019 if (instance)
1020 len = create_instance_adv_data(hdev, cp.data);
1021 else
1022 len = create_default_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001023
Arman Uguray24b4f382015-03-23 15:57:12 -07001024 /* There's nothing to do if the data hasn't changed */
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001025 if (hdev->adv_data_len == len &&
1026 memcmp(cp.data, hdev->adv_data, len) == 0)
1027 return;
1028
1029 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1030 hdev->adv_data_len = len;
1031
1032 cp.length = len;
1033
1034 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1035}
1036
Arman Uguraye7a685d2015-03-25 18:53:40 -07001037static u8 get_current_adv_instance(struct hci_dev *hdev)
Arman Uguray24b4f382015-03-23 15:57:12 -07001038{
Arman Uguray24b4f382015-03-23 15:57:12 -07001039 /* The "Set Advertising" setting supersedes the "Add Advertising"
1040 * setting. Here we set the advertising data based on which
1041 * setting was set. When neither apply, default to the global settings,
1042 * represented by instance "0".
1043 */
1044 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
1045 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Arman Uguraye7a685d2015-03-25 18:53:40 -07001046 return 0x01;
1047
1048 return 0x00;
1049}
1050
1051static bool get_connectable(struct hci_dev *hdev)
1052{
1053 struct mgmt_pending_cmd *cmd;
1054
1055 /* If there's a pending mgmt command the flag will not yet have
1056 * it's final value, so check for this first.
1057 */
1058 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1059 if (cmd) {
1060 struct mgmt_mode *cp = cmd->param;
1061
1062 return cp->val;
1063 }
1064
1065 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
1066}
1067
1068static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
1069{
1070 u32 flags;
1071
1072 if (instance > 0x01)
1073 return 0;
1074
1075 if (instance == 1)
1076 return hdev->adv_instance.flags;
1077
1078 flags = 0;
1079
1080 /* For instance 0, assemble the flags from global settings */
1081 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) ||
1082 get_connectable(hdev))
1083 flags |= MGMT_ADV_FLAG_CONNECTABLE;
1084
1085 /* TODO: Add the rest of the flags */
1086
1087 return flags;
1088}
1089
1090static void update_adv_data(struct hci_request *req)
1091{
1092 struct hci_dev *hdev = req->hdev;
1093 u8 instance = get_current_adv_instance(hdev);
Arman Uguray24b4f382015-03-23 15:57:12 -07001094
1095 update_adv_data_for_instance(req, instance);
1096}
1097
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001098int mgmt_update_adv_data(struct hci_dev *hdev)
1099{
1100 struct hci_request req;
1101
1102 hci_req_init(&req, hdev);
1103 update_adv_data(&req);
1104
1105 return hci_req_run(&req, NULL);
1106}
1107
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001108static void create_eir(struct hci_dev *hdev, u8 *data)
1109{
1110 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001111 size_t name_len;
1112
1113 name_len = strlen(hdev->dev_name);
1114
1115 if (name_len > 0) {
1116 /* EIR Data type */
1117 if (name_len > 48) {
1118 name_len = 48;
1119 ptr[1] = EIR_NAME_SHORT;
1120 } else
1121 ptr[1] = EIR_NAME_COMPLETE;
1122
1123 /* EIR Data length */
1124 ptr[0] = name_len + 1;
1125
1126 memcpy(ptr + 2, hdev->dev_name, name_len);
1127
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001128 ptr += (name_len + 2);
1129 }
1130
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001131 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001132 ptr[0] = 2;
1133 ptr[1] = EIR_TX_POWER;
1134 ptr[2] = (u8) hdev->inq_tx_power;
1135
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001136 ptr += 3;
1137 }
1138
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001139 if (hdev->devid_source > 0) {
1140 ptr[0] = 9;
1141 ptr[1] = EIR_DEVICE_ID;
1142
1143 put_unaligned_le16(hdev->devid_source, ptr + 2);
1144 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1145 put_unaligned_le16(hdev->devid_product, ptr + 6);
1146 put_unaligned_le16(hdev->devid_version, ptr + 8);
1147
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001148 ptr += 10;
1149 }
1150
Johan Hedberg213202e2013-01-27 00:31:33 +02001151 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001152 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001153 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001154}
1155
Johan Hedberg890ea892013-03-15 17:06:52 -05001156static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001157{
Johan Hedberg890ea892013-03-15 17:06:52 -05001158 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001159 struct hci_cp_write_eir cp;
1160
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001161 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001162 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001163
Johan Hedberg976eb202012-10-24 21:12:01 +03001164 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001165 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001166
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001167 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001168 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001169
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001170 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001171 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001172
1173 memset(&cp, 0, sizeof(cp));
1174
1175 create_eir(hdev, cp.data);
1176
1177 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001178 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001179
1180 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1181
Johan Hedberg890ea892013-03-15 17:06:52 -05001182 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001183}
1184
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001185static u8 get_service_classes(struct hci_dev *hdev)
1186{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001187 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001188 u8 val = 0;
1189
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001190 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001191 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001192
1193 return val;
1194}
1195
Johan Hedberg890ea892013-03-15 17:06:52 -05001196static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001197{
Johan Hedberg890ea892013-03-15 17:06:52 -05001198 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001199 u8 cod[3];
1200
1201 BT_DBG("%s", hdev->name);
1202
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001203 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001204 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001205
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001206 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001207 return;
1208
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001209 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001210 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001211
1212 cod[0] = hdev->minor_class;
1213 cod[1] = hdev->major_class;
1214 cod[2] = get_service_classes(hdev);
1215
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001216 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001217 cod[1] |= 0x20;
1218
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001219 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001220 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001221
Johan Hedberg890ea892013-03-15 17:06:52 -05001222 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001223}
1224
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001225static void disable_advertising(struct hci_request *req)
1226{
1227 u8 enable = 0x00;
1228
1229 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1230}
1231
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001232static void enable_advertising(struct hci_request *req)
1233{
1234 struct hci_dev *hdev = req->hdev;
1235 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001236 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001237 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001238 u8 instance;
1239 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001240
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001241 if (hci_conn_num(hdev, LE_LINK) > 0)
1242 return;
1243
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001244 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001245 disable_advertising(req);
1246
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001247 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001248 * hci_update_random_address knows that it's safe to go ahead
1249 * and write a new random address. The flag will be set back on
1250 * as soon as the SET_ADV_ENABLE HCI command completes.
1251 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001252 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001253
Arman Uguraye7a685d2015-03-25 18:53:40 -07001254 instance = get_current_adv_instance(hdev);
1255 flags = get_adv_instance_flags(hdev, instance);
1256 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001257
Johan Hedberga4858cb2014-02-25 19:56:31 +02001258 /* Set require_privacy to true only when non-connectable
1259 * advertising is used. In that case it is fine to use a
1260 * non-resolvable private address.
1261 */
1262 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001263 return;
1264
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001265 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001266 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1267 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001268 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001269 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001270 cp.channel_map = hdev->le_adv_channel_map;
1271
1272 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1273
1274 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1275}
1276
Johan Hedberg7d785252011-12-15 00:47:39 +02001277static void service_cache_off(struct work_struct *work)
1278{
1279 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001280 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001281 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001282
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001283 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001284 return;
1285
Johan Hedberg890ea892013-03-15 17:06:52 -05001286 hci_req_init(&req, hdev);
1287
Johan Hedberg7d785252011-12-15 00:47:39 +02001288 hci_dev_lock(hdev);
1289
Johan Hedberg890ea892013-03-15 17:06:52 -05001290 update_eir(&req);
1291 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001292
1293 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001294
1295 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001296}
1297
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001298static void rpa_expired(struct work_struct *work)
1299{
1300 struct hci_dev *hdev = container_of(work, struct hci_dev,
1301 rpa_expired.work);
1302 struct hci_request req;
1303
1304 BT_DBG("");
1305
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001306 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001307
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001308 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001309 return;
1310
1311 /* The generation of a new RPA and programming it into the
1312 * controller happens in the enable_advertising() function.
1313 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001314 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001315 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001316 hci_req_run(&req, NULL);
1317}
1318
Johan Hedberg6a919082012-02-28 06:17:26 +02001319static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001320{
Marcel Holtmann238be782015-03-13 02:11:06 -07001321 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001322 return;
1323
Johan Hedberg4f87da82012-03-02 19:55:56 +02001324 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001325 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001326
Johan Hedberg4f87da82012-03-02 19:55:56 +02001327 /* Non-mgmt controlled devices get this bit set
1328 * implicitly so that pairing works for them, however
1329 * for mgmt we require user-space to explicitly enable
1330 * it
1331 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001332 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001333}
1334
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001335static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001336 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001337{
1338 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001339
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001340 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001341
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001342 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001343
Johan Hedberg03811012010-12-08 00:21:06 +02001344 memset(&rp, 0, sizeof(rp));
1345
Johan Hedberg03811012010-12-08 00:21:06 +02001346 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001347
1348 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001349 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001350
1351 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1352 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1353
1354 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001355
1356 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001357 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001358
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001359 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001360
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001361 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1362 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001363}
1364
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001365static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001366{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001367 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001368
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001369 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1370 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001371}
1372
Marcel Holtmann1904a852015-01-11 13:50:44 -08001373static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001374{
1375 BT_DBG("%s status 0x%02x", hdev->name, status);
1376
Johan Hedberga3172b72014-02-28 09:33:44 +02001377 if (hci_conn_count(hdev) == 0) {
1378 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001379 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001380 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001381}
1382
Johan Hedberg23a48092014-07-08 16:05:06 +03001383static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001384{
1385 struct hci_dev *hdev = req->hdev;
1386 struct hci_cp_remote_name_req_cancel cp;
1387 struct inquiry_entry *e;
1388
1389 switch (hdev->discovery.state) {
1390 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001391 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001392 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001393
1394 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001395 cancel_delayed_work(&hdev->le_scan_disable);
1396 hci_req_add_le_scan_disable(req);
1397 }
1398
Johan Hedberg23a48092014-07-08 16:05:06 +03001399 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001400
1401 case DISCOVERY_RESOLVING:
1402 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1403 NAME_PENDING);
1404 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001405 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001406
1407 bacpy(&cp.bdaddr, &e->data.bdaddr);
1408 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1409 &cp);
1410
Johan Hedberg23a48092014-07-08 16:05:06 +03001411 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001412
1413 default:
1414 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001415 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001416 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001417 return true;
1418 }
1419
Johan Hedberg21a60d32014-06-10 14:05:58 +03001420 break;
1421 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001422
1423 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001424}
1425
Arman Uguray912098a2015-03-23 15:57:15 -07001426static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1427 u8 instance)
1428{
1429 struct mgmt_ev_advertising_added ev;
1430
1431 ev.instance = instance;
1432
1433 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1434}
1435
1436static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1437 u8 instance)
1438{
1439 struct mgmt_ev_advertising_removed ev;
1440
1441 ev.instance = instance;
1442
1443 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1444}
1445
1446static void clear_adv_instance(struct hci_dev *hdev)
1447{
1448 struct hci_request req;
1449
1450 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1451 return;
1452
1453 if (hdev->adv_instance.timeout)
1454 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
1455
1456 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1457 advertising_removed(NULL, hdev, 1);
1458 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1459
1460 if (!hdev_is_powered(hdev) ||
1461 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1462 return;
1463
1464 hci_req_init(&req, hdev);
1465 disable_advertising(&req);
1466 hci_req_run(&req, NULL);
1467}
1468
Johan Hedberg8b064a32014-02-24 14:52:22 +02001469static int clean_up_hci_state(struct hci_dev *hdev)
1470{
1471 struct hci_request req;
1472 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001473 bool discov_stopped;
1474 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001475
1476 hci_req_init(&req, hdev);
1477
1478 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1479 test_bit(HCI_PSCAN, &hdev->flags)) {
1480 u8 scan = 0x00;
1481 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1482 }
1483
Arman Uguray912098a2015-03-23 15:57:15 -07001484 if (hdev->adv_instance.timeout)
1485 clear_adv_instance(hdev);
1486
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001487 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001488 disable_advertising(&req);
1489
Johan Hedberg23a48092014-07-08 16:05:06 +03001490 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001491
1492 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1493 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001494 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001495
Johan Hedbergc9910d02014-02-27 14:35:12 +02001496 switch (conn->state) {
1497 case BT_CONNECTED:
1498 case BT_CONFIG:
1499 dc.handle = cpu_to_le16(conn->handle);
1500 dc.reason = 0x15; /* Terminated due to Power Off */
1501 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1502 break;
1503 case BT_CONNECT:
1504 if (conn->type == LE_LINK)
1505 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1506 0, NULL);
1507 else if (conn->type == ACL_LINK)
1508 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1509 6, &conn->dst);
1510 break;
1511 case BT_CONNECT2:
1512 bacpy(&rej.bdaddr, &conn->dst);
1513 rej.reason = 0x15; /* Terminated due to Power Off */
1514 if (conn->type == ACL_LINK)
1515 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1516 sizeof(rej), &rej);
1517 else if (conn->type == SCO_LINK)
1518 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1519 sizeof(rej), &rej);
1520 break;
1521 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001522 }
1523
Johan Hedberg23a48092014-07-08 16:05:06 +03001524 err = hci_req_run(&req, clean_up_hci_complete);
1525 if (!err && discov_stopped)
1526 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1527
1528 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001529}
1530
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001531static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001532 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001533{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001534 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001535 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001536 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001537
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001538 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001539
Johan Hedberga7e80f22013-01-09 16:05:19 +02001540 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001541 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1542 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001543
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001544 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001545
Johan Hedberg333ae952015-03-17 13:48:47 +02001546 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001547 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1548 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001549 goto failed;
1550 }
1551
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001552 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001553 cancel_delayed_work(&hdev->power_off);
1554
1555 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001556 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1557 data, len);
1558 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001559 goto failed;
1560 }
1561 }
1562
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001563 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001564 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001565 goto failed;
1566 }
1567
Johan Hedberg03811012010-12-08 00:21:06 +02001568 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1569 if (!cmd) {
1570 err = -ENOMEM;
1571 goto failed;
1572 }
1573
Johan Hedberg8b064a32014-02-24 14:52:22 +02001574 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001575 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001576 err = 0;
1577 } else {
1578 /* Disconnect connections, stop scans, etc */
1579 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001580 if (!err)
1581 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1582 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001583
Johan Hedberg8b064a32014-02-24 14:52:22 +02001584 /* ENODATA means there were no HCI commands queued */
1585 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001586 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001587 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1588 err = 0;
1589 }
1590 }
Johan Hedberg03811012010-12-08 00:21:06 +02001591
1592failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001593 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001594 return err;
1595}
1596
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001597static int new_settings(struct hci_dev *hdev, struct sock *skip)
1598{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001599 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001600
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001601 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1602 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001603}
1604
Johan Hedberg91a668b2014-07-09 13:28:26 +03001605int mgmt_new_settings(struct hci_dev *hdev)
1606{
1607 return new_settings(hdev, NULL);
1608}
1609
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001610struct cmd_lookup {
1611 struct sock *sk;
1612 struct hci_dev *hdev;
1613 u8 mgmt_status;
1614};
1615
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001616static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001617{
1618 struct cmd_lookup *match = data;
1619
1620 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1621
1622 list_del(&cmd->list);
1623
1624 if (match->sk == NULL) {
1625 match->sk = cmd->sk;
1626 sock_hold(match->sk);
1627 }
1628
1629 mgmt_pending_free(cmd);
1630}
1631
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001632static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001633{
1634 u8 *status = data;
1635
Johan Hedberga69e8372015-03-06 21:08:53 +02001636 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001637 mgmt_pending_remove(cmd);
1638}
1639
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001640static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001641{
1642 if (cmd->cmd_complete) {
1643 u8 *status = data;
1644
1645 cmd->cmd_complete(cmd, *status);
1646 mgmt_pending_remove(cmd);
1647
1648 return;
1649 }
1650
1651 cmd_status_rsp(cmd, data);
1652}
1653
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001654static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001655{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001656 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1657 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001658}
1659
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001660static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001661{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001662 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1663 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001664}
1665
Johan Hedberge6fe7982013-10-02 15:45:22 +03001666static u8 mgmt_bredr_support(struct hci_dev *hdev)
1667{
1668 if (!lmp_bredr_capable(hdev))
1669 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001670 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001671 return MGMT_STATUS_REJECTED;
1672 else
1673 return MGMT_STATUS_SUCCESS;
1674}
1675
1676static u8 mgmt_le_support(struct hci_dev *hdev)
1677{
1678 if (!lmp_le_capable(hdev))
1679 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001680 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001681 return MGMT_STATUS_REJECTED;
1682 else
1683 return MGMT_STATUS_SUCCESS;
1684}
1685
Marcel Holtmann1904a852015-01-11 13:50:44 -08001686static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1687 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001688{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001689 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001690 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001691 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001692 bool changed;
1693
1694 BT_DBG("status 0x%02x", status);
1695
1696 hci_dev_lock(hdev);
1697
Johan Hedberg333ae952015-03-17 13:48:47 +02001698 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001699 if (!cmd)
1700 goto unlock;
1701
1702 if (status) {
1703 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001704 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001705 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001706 goto remove_cmd;
1707 }
1708
1709 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001710 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001711 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001712
1713 if (hdev->discov_timeout > 0) {
1714 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1715 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1716 to);
1717 }
1718 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001719 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001720 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001721
1722 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1723
1724 if (changed)
1725 new_settings(hdev, cmd->sk);
1726
Marcel Holtmann970ba522013-10-15 06:33:57 -07001727 /* When the discoverable mode gets changed, make sure
1728 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001729 * bit correctly set. Also update page scan based on whitelist
1730 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001731 */
1732 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001733 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001734 update_class(&req);
1735 hci_req_run(&req, NULL);
1736
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737remove_cmd:
1738 mgmt_pending_remove(cmd);
1739
1740unlock:
1741 hci_dev_unlock(hdev);
1742}
1743
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001744static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001745 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001746{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001747 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001748 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001749 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001750 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001751 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001752 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001753
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001754 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001755
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001756 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1757 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001758 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1759 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001760
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001761 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001762 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1763 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001764
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001765 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001766
1767 /* Disabling discoverable requires that no timeout is set,
1768 * and enabling limited discoverable requires a timeout.
1769 */
1770 if ((cp->val == 0x00 && timeout > 0) ||
1771 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001772 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1773 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001774
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001775 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001776
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001777 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001778 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1779 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001780 goto failed;
1781 }
1782
Johan Hedberg333ae952015-03-17 13:48:47 +02001783 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1784 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001785 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1786 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001787 goto failed;
1788 }
1789
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001790 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001791 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1792 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001793 goto failed;
1794 }
1795
1796 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001797 bool changed = false;
1798
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001799 /* Setting limited discoverable when powered off is
1800 * not a valid operation since it requires a timeout
1801 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1802 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001803 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001804 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001805 changed = true;
1806 }
1807
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001808 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001809 if (err < 0)
1810 goto failed;
1811
1812 if (changed)
1813 err = new_settings(hdev, sk);
1814
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001815 goto failed;
1816 }
1817
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001818 /* If the current mode is the same, then just update the timeout
1819 * value with the new value. And if only the timeout gets updated,
1820 * then no need for any HCI transactions.
1821 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001822 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1823 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1824 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001825 cancel_delayed_work(&hdev->discov_off);
1826 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001827
Marcel Holtmann36261542013-10-15 08:28:51 -07001828 if (cp->val && hdev->discov_timeout > 0) {
1829 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001830 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001831 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001832 }
1833
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001834 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001835 goto failed;
1836 }
1837
1838 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1839 if (!cmd) {
1840 err = -ENOMEM;
1841 goto failed;
1842 }
1843
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001844 /* Cancel any potential discoverable timeout that might be
1845 * still active and store new timeout value. The arming of
1846 * the timeout happens in the complete handler.
1847 */
1848 cancel_delayed_work(&hdev->discov_off);
1849 hdev->discov_timeout = timeout;
1850
Johan Hedbergb456f872013-10-19 23:38:22 +03001851 /* Limited discoverable mode */
1852 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001853 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001854 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001855 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001856
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001857 hci_req_init(&req, hdev);
1858
Johan Hedberg9a43e252013-10-20 19:00:07 +03001859 /* The procedure for LE-only controllers is much simpler - just
1860 * update the advertising data.
1861 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001862 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001863 goto update_ad;
1864
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001865 scan = SCAN_PAGE;
1866
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001867 if (cp->val) {
1868 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001869
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001870 if (cp->val == 0x02) {
1871 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001872 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001873 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1874 hci_cp.iac_lap[1] = 0x8b;
1875 hci_cp.iac_lap[2] = 0x9e;
1876 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1877 hci_cp.iac_lap[4] = 0x8b;
1878 hci_cp.iac_lap[5] = 0x9e;
1879 } else {
1880 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001881 hci_cp.num_iac = 1;
1882 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1883 hci_cp.iac_lap[1] = 0x8b;
1884 hci_cp.iac_lap[2] = 0x9e;
1885 }
1886
1887 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1888 (hci_cp.num_iac * 3) + 1, &hci_cp);
1889
1890 scan |= SCAN_INQUIRY;
1891 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001892 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001893 }
1894
1895 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001896
Johan Hedberg9a43e252013-10-20 19:00:07 +03001897update_ad:
1898 update_adv_data(&req);
1899
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001900 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001901 if (err < 0)
1902 mgmt_pending_remove(cmd);
1903
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001904failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001905 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001906 return err;
1907}
1908
Johan Hedberg406d7802013-03-15 17:07:09 -05001909static void write_fast_connectable(struct hci_request *req, bool enable)
1910{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001911 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001912 struct hci_cp_write_page_scan_activity acp;
1913 u8 type;
1914
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001915 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001916 return;
1917
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001918 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1919 return;
1920
Johan Hedberg406d7802013-03-15 17:07:09 -05001921 if (enable) {
1922 type = PAGE_SCAN_TYPE_INTERLACED;
1923
1924 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001925 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001926 } else {
1927 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1928
1929 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001930 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001931 }
1932
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001933 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001934
Johan Hedbergbd98b992013-03-15 17:07:13 -05001935 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1936 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1937 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1938 sizeof(acp), &acp);
1939
1940 if (hdev->page_scan_type != type)
1941 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001942}
1943
Marcel Holtmann1904a852015-01-11 13:50:44 -08001944static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1945 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001946{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001947 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001948 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001949 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001950
1951 BT_DBG("status 0x%02x", status);
1952
1953 hci_dev_lock(hdev);
1954
Johan Hedberg333ae952015-03-17 13:48:47 +02001955 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001956 if (!cmd)
1957 goto unlock;
1958
Johan Hedberg37438c12013-10-14 16:20:05 +03001959 if (status) {
1960 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001961 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001962 goto remove_cmd;
1963 }
1964
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001965 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001966 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001967 conn_changed = !hci_dev_test_and_set_flag(hdev,
1968 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001969 discov_changed = false;
1970 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001971 conn_changed = hci_dev_test_and_clear_flag(hdev,
1972 HCI_CONNECTABLE);
1973 discov_changed = hci_dev_test_and_clear_flag(hdev,
1974 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001975 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001976
Johan Hedberg2b76f452013-03-15 17:07:04 -05001977 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1978
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001979 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001980 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001981 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001982 if (discov_changed)
1983 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001984 hci_update_background_scan(hdev);
1985 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001986
Johan Hedberg37438c12013-10-14 16:20:05 +03001987remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001988 mgmt_pending_remove(cmd);
1989
1990unlock:
1991 hci_dev_unlock(hdev);
1992}
1993
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001994static int set_connectable_update_settings(struct hci_dev *hdev,
1995 struct sock *sk, u8 val)
1996{
1997 bool changed = false;
1998 int err;
1999
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002000 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002001 changed = true;
2002
2003 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002004 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002005 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002006 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2007 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002008 }
2009
2010 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2011 if (err < 0)
2012 return err;
2013
Johan Hedberg562064e2014-07-08 16:35:34 +03002014 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002015 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002016 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002017 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002018 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002019
2020 return 0;
2021}
2022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002023static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002024 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002025{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002026 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002027 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002028 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002029 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002030 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002031
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002032 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002033
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002034 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2035 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002036 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2037 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002038
Johan Hedberga7e80f22013-01-09 16:05:19 +02002039 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002040 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2041 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002042
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002043 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002044
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002045 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002046 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002047 goto failed;
2048 }
2049
Johan Hedberg333ae952015-03-17 13:48:47 +02002050 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2051 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002052 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2053 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002054 goto failed;
2055 }
2056
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002057 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2058 if (!cmd) {
2059 err = -ENOMEM;
2060 goto failed;
2061 }
2062
Johan Hedberg2b76f452013-03-15 17:07:04 -05002063 hci_req_init(&req, hdev);
2064
Johan Hedberg9a43e252013-10-20 19:00:07 +03002065 /* If BR/EDR is not enabled and we disable advertising as a
2066 * by-product of disabling connectable, we need to update the
2067 * advertising flags.
2068 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002069 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002070 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002071 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2072 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002073 }
2074 update_adv_data(&req);
2075 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002076 if (cp->val) {
2077 scan = SCAN_PAGE;
2078 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002079 /* If we don't have any whitelist entries just
2080 * disable all scanning. If there are entries
2081 * and we had both page and inquiry scanning
2082 * enabled then fall back to only page scanning.
2083 * Otherwise no changes are needed.
2084 */
2085 if (list_empty(&hdev->whitelist))
2086 scan = SCAN_DISABLED;
2087 else if (test_bit(HCI_ISCAN, &hdev->flags))
2088 scan = SCAN_PAGE;
2089 else
2090 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002091
2092 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002093 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002094 cancel_delayed_work(&hdev->discov_off);
2095 }
2096
2097 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2098 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002099
Johan Hedberg3bd27242014-07-28 20:53:58 +03002100no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002101 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002102 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002103 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002104
Johan Hedberg2b76f452013-03-15 17:07:04 -05002105 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002106 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002107 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002108 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002109 err = set_connectable_update_settings(hdev, sk,
2110 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002111 goto failed;
2112 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002113
2114failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002115 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002116 return err;
2117}
2118
Johan Hedbergb2939472014-07-30 09:22:23 +03002119static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002120 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002121{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002122 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002123 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002124 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002125
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002126 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002127
Johan Hedberga7e80f22013-01-09 16:05:19 +02002128 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002129 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2130 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002131
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002132 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002133
2134 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002135 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002136 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002137 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002138
Johan Hedbergb2939472014-07-30 09:22:23 +03002139 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002140 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002141 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002142
Marcel Holtmann55594352013-10-06 16:11:57 -07002143 if (changed)
2144 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002145
Marcel Holtmann55594352013-10-06 16:11:57 -07002146unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002147 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002148 return err;
2149}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002150
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002151static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2152 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002153{
2154 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002155 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002157 int err;
2158
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002159 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002160
Johan Hedberge6fe7982013-10-02 15:45:22 +03002161 status = mgmt_bredr_support(hdev);
2162 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002163 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2164 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002165
Johan Hedberga7e80f22013-01-09 16:05:19 +02002166 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002167 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2168 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002169
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002170 hci_dev_lock(hdev);
2171
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002172 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002173 bool changed = false;
2174
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002175 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002176 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002177 changed = true;
2178 }
2179
2180 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2181 if (err < 0)
2182 goto failed;
2183
2184 if (changed)
2185 err = new_settings(hdev, sk);
2186
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002187 goto failed;
2188 }
2189
Johan Hedberg333ae952015-03-17 13:48:47 +02002190 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002191 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2192 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002193 goto failed;
2194 }
2195
2196 val = !!cp->val;
2197
2198 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2199 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2200 goto failed;
2201 }
2202
2203 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2204 if (!cmd) {
2205 err = -ENOMEM;
2206 goto failed;
2207 }
2208
2209 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2210 if (err < 0) {
2211 mgmt_pending_remove(cmd);
2212 goto failed;
2213 }
2214
2215failed:
2216 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002217 return err;
2218}
2219
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002220static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002221{
2222 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002223 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002224 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002225 int err;
2226
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002227 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002228
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002229 status = mgmt_bredr_support(hdev);
2230 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002231 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002232
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002233 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002234 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2235 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002236
Johan Hedberga7e80f22013-01-09 16:05:19 +02002237 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002238 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2239 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002240
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002241 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002242
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002243 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002244 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002245
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002246 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002247 changed = !hci_dev_test_and_set_flag(hdev,
2248 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002249 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002250 changed = hci_dev_test_and_clear_flag(hdev,
2251 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002252 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002253 changed = hci_dev_test_and_clear_flag(hdev,
2254 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002255 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002256 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002257 }
2258
2259 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2260 if (err < 0)
2261 goto failed;
2262
2263 if (changed)
2264 err = new_settings(hdev, sk);
2265
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002266 goto failed;
2267 }
2268
Johan Hedberg333ae952015-03-17 13:48:47 +02002269 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002270 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2271 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002272 goto failed;
2273 }
2274
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002275 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002276 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2277 goto failed;
2278 }
2279
2280 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2281 if (!cmd) {
2282 err = -ENOMEM;
2283 goto failed;
2284 }
2285
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002286 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002287 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2288 sizeof(cp->val), &cp->val);
2289
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002290 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002291 if (err < 0) {
2292 mgmt_pending_remove(cmd);
2293 goto failed;
2294 }
2295
2296failed:
2297 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002298 return err;
2299}
2300
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002301static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002302{
2303 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002304 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002305 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002306 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002307
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002308 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002309
Johan Hedberge6fe7982013-10-02 15:45:22 +03002310 status = mgmt_bredr_support(hdev);
2311 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002312 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002313
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002314 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002315 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2316 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002317
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002318 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002319 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2320 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002321
Johan Hedberga7e80f22013-01-09 16:05:19 +02002322 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002323 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2324 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002325
Marcel Holtmannee392692013-10-01 22:59:23 -07002326 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002327
Johan Hedberg333ae952015-03-17 13:48:47 +02002328 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002329 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2330 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002331 goto unlock;
2332 }
2333
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002334 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002335 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002336 } else {
2337 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002338 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2339 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002340 goto unlock;
2341 }
2342
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002343 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002344 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002345
2346 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2347 if (err < 0)
2348 goto unlock;
2349
2350 if (changed)
2351 err = new_settings(hdev, sk);
2352
2353unlock:
2354 hci_dev_unlock(hdev);
2355 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002356}
2357
Marcel Holtmann1904a852015-01-11 13:50:44 -08002358static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002359{
2360 struct cmd_lookup match = { NULL, hdev };
2361
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302362 hci_dev_lock(hdev);
2363
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002364 if (status) {
2365 u8 mgmt_err = mgmt_status(status);
2366
2367 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2368 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302369 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002370 }
2371
2372 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2373
2374 new_settings(hdev, match.sk);
2375
2376 if (match.sk)
2377 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002378
2379 /* Make sure the controller has a good default for
2380 * advertising data. Restrict the update to when LE
2381 * has actually been enabled. During power on, the
2382 * update in powered_update_hci will take care of it.
2383 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002384 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002385 struct hci_request req;
2386
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002387 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002388 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002389 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002390 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002391 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002392 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302393
2394unlock:
2395 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002396}
2397
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002398static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002399{
2400 struct mgmt_mode *cp = data;
2401 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002402 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002403 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002404 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002405 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002406
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002407 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002408
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002409 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002410 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2411 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002412
Johan Hedberga7e80f22013-01-09 16:05:19 +02002413 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002414 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2415 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002416
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002417 /* Bluetooth single mode LE only controllers or dual-mode
2418 * controllers configured as LE only devices, do not allow
2419 * switching LE off. These have either LE enabled explicitly
2420 * or BR/EDR has been previously switched off.
2421 *
2422 * When trying to enable an already enabled LE, then gracefully
2423 * send a positive response. Trying to disable it however will
2424 * result into rejection.
2425 */
2426 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2427 if (cp->val == 0x01)
2428 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2429
Johan Hedberga69e8372015-03-06 21:08:53 +02002430 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2431 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002432 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002433
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002434 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002435
2436 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002437 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002438
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002439 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002440 bool changed = false;
2441
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002442 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002443 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002444 changed = true;
2445 }
2446
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002447 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002448 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002449 changed = true;
2450 }
2451
Johan Hedberg06199cf2012-02-22 16:37:11 +02002452 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2453 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002454 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002455
2456 if (changed)
2457 err = new_settings(hdev, sk);
2458
Johan Hedberg1de028c2012-02-29 19:55:35 -08002459 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002460 }
2461
Johan Hedberg333ae952015-03-17 13:48:47 +02002462 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2463 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002464 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2465 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002466 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002467 }
2468
2469 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2470 if (!cmd) {
2471 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002472 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002473 }
2474
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002475 hci_req_init(&req, hdev);
2476
Johan Hedberg06199cf2012-02-22 16:37:11 +02002477 memset(&hci_cp, 0, sizeof(hci_cp));
2478
2479 if (val) {
2480 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002481 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002482 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002483 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002484 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002485 }
2486
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002487 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2488 &hci_cp);
2489
2490 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302491 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002492 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002493
Johan Hedberg1de028c2012-02-29 19:55:35 -08002494unlock:
2495 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002496 return err;
2497}
2498
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002499/* This is a helper function to test for pending mgmt commands that can
2500 * cause CoD or EIR HCI commands. We can only allow one such pending
2501 * mgmt command at a time since otherwise we cannot easily track what
2502 * the current values are, will be, and based on that calculate if a new
2503 * HCI command needs to be sent and if yes with what value.
2504 */
2505static bool pending_eir_or_class(struct hci_dev *hdev)
2506{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002507 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002508
2509 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2510 switch (cmd->opcode) {
2511 case MGMT_OP_ADD_UUID:
2512 case MGMT_OP_REMOVE_UUID:
2513 case MGMT_OP_SET_DEV_CLASS:
2514 case MGMT_OP_SET_POWERED:
2515 return true;
2516 }
2517 }
2518
2519 return false;
2520}
2521
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002522static const u8 bluetooth_base_uuid[] = {
2523 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2524 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2525};
2526
2527static u8 get_uuid_size(const u8 *uuid)
2528{
2529 u32 val;
2530
2531 if (memcmp(uuid, bluetooth_base_uuid, 12))
2532 return 128;
2533
2534 val = get_unaligned_le32(&uuid[12]);
2535 if (val > 0xffff)
2536 return 32;
2537
2538 return 16;
2539}
2540
Johan Hedberg92da6092013-03-15 17:06:55 -05002541static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2542{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002543 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002544
2545 hci_dev_lock(hdev);
2546
Johan Hedberg333ae952015-03-17 13:48:47 +02002547 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002548 if (!cmd)
2549 goto unlock;
2550
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002551 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2552 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002553
2554 mgmt_pending_remove(cmd);
2555
2556unlock:
2557 hci_dev_unlock(hdev);
2558}
2559
Marcel Holtmann1904a852015-01-11 13:50:44 -08002560static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002561{
2562 BT_DBG("status 0x%02x", status);
2563
2564 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2565}
2566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002567static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002568{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002569 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002570 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002571 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002572 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002573 int err;
2574
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002575 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002576
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002577 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002578
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002579 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002580 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2581 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002582 goto failed;
2583 }
2584
Andre Guedes92c4c202012-06-07 19:05:44 -03002585 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002586 if (!uuid) {
2587 err = -ENOMEM;
2588 goto failed;
2589 }
2590
2591 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002592 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002593 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002594
Johan Hedbergde66aa62013-01-27 00:31:27 +02002595 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002596
Johan Hedberg890ea892013-03-15 17:06:52 -05002597 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002598
Johan Hedberg890ea892013-03-15 17:06:52 -05002599 update_class(&req);
2600 update_eir(&req);
2601
Johan Hedberg92da6092013-03-15 17:06:55 -05002602 err = hci_req_run(&req, add_uuid_complete);
2603 if (err < 0) {
2604 if (err != -ENODATA)
2605 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002606
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002607 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2608 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002609 goto failed;
2610 }
2611
2612 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002613 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002614 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002615 goto failed;
2616 }
2617
2618 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002619
2620failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002621 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002622 return err;
2623}
2624
Johan Hedberg24b78d02012-02-23 23:24:30 +02002625static bool enable_service_cache(struct hci_dev *hdev)
2626{
2627 if (!hdev_is_powered(hdev))
2628 return false;
2629
Marcel Holtmann238be782015-03-13 02:11:06 -07002630 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002631 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2632 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002633 return true;
2634 }
2635
2636 return false;
2637}
2638
Marcel Holtmann1904a852015-01-11 13:50:44 -08002639static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002640{
2641 BT_DBG("status 0x%02x", status);
2642
2643 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2644}
2645
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002646static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002647 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002648{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002649 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002650 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002651 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002652 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 -05002653 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002654 int err, found;
2655
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002656 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002657
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002658 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002659
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002660 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002661 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2662 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002663 goto unlock;
2664 }
2665
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002666 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002667 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002668
Johan Hedberg24b78d02012-02-23 23:24:30 +02002669 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002670 err = mgmt_cmd_complete(sk, hdev->id,
2671 MGMT_OP_REMOVE_UUID,
2672 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002673 goto unlock;
2674 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002675
Johan Hedberg9246a862012-02-23 21:33:16 +02002676 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002677 }
2678
2679 found = 0;
2680
Johan Hedberg056341c2013-01-27 00:31:30 +02002681 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002682 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2683 continue;
2684
2685 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002686 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002687 found++;
2688 }
2689
2690 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002691 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2692 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002693 goto unlock;
2694 }
2695
Johan Hedberg9246a862012-02-23 21:33:16 +02002696update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002697 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002698
Johan Hedberg890ea892013-03-15 17:06:52 -05002699 update_class(&req);
2700 update_eir(&req);
2701
Johan Hedberg92da6092013-03-15 17:06:55 -05002702 err = hci_req_run(&req, remove_uuid_complete);
2703 if (err < 0) {
2704 if (err != -ENODATA)
2705 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002706
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002707 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2708 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002709 goto unlock;
2710 }
2711
2712 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002713 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002714 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002715 goto unlock;
2716 }
2717
2718 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002719
2720unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002721 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002722 return err;
2723}
2724
Marcel Holtmann1904a852015-01-11 13:50:44 -08002725static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002726{
2727 BT_DBG("status 0x%02x", status);
2728
2729 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2730}
2731
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002732static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002733 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002734{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002735 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002736 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002737 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002738 int err;
2739
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002740 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002741
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002742 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002743 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2744 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002745
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002746 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002747
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002748 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002749 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2750 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002751 goto unlock;
2752 }
2753
2754 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002755 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2756 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002757 goto unlock;
2758 }
2759
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002760 hdev->major_class = cp->major;
2761 hdev->minor_class = cp->minor;
2762
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002763 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002764 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2765 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002766 goto unlock;
2767 }
2768
Johan Hedberg890ea892013-03-15 17:06:52 -05002769 hci_req_init(&req, hdev);
2770
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002771 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002772 hci_dev_unlock(hdev);
2773 cancel_delayed_work_sync(&hdev->service_cache);
2774 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002775 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002776 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002777
Johan Hedberg890ea892013-03-15 17:06:52 -05002778 update_class(&req);
2779
Johan Hedberg92da6092013-03-15 17:06:55 -05002780 err = hci_req_run(&req, set_class_complete);
2781 if (err < 0) {
2782 if (err != -ENODATA)
2783 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002784
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002785 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2786 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002787 goto unlock;
2788 }
2789
2790 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002791 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002792 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002793 goto unlock;
2794 }
2795
2796 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002797
Johan Hedbergb5235a62012-02-21 14:32:24 +02002798unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002799 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002800 return err;
2801}
2802
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002803static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002804 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002805{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002806 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002807 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2808 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002809 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002810 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002811 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002812
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002813 BT_DBG("request for %s", hdev->name);
2814
2815 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002816 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2817 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002818
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002819 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002820 if (key_count > max_key_count) {
2821 BT_ERR("load_link_keys: too big key_count value %u",
2822 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002823 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2824 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002825 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002826
Johan Hedberg86742e12011-11-07 23:13:38 +02002827 expected_len = sizeof(*cp) + key_count *
2828 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002829 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002830 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002831 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002832 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2833 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002834 }
2835
Johan Hedberg4ae14302013-01-20 14:27:13 +02002836 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002837 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2838 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002839
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002840 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002841 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002842
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002843 for (i = 0; i < key_count; i++) {
2844 struct mgmt_link_key_info *key = &cp->keys[i];
2845
Marcel Holtmann8e991132014-01-10 02:07:25 -08002846 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002847 return mgmt_cmd_status(sk, hdev->id,
2848 MGMT_OP_LOAD_LINK_KEYS,
2849 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002850 }
2851
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002852 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002853
2854 hci_link_keys_clear(hdev);
2855
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002856 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002857 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002858 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002859 changed = hci_dev_test_and_clear_flag(hdev,
2860 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002861
2862 if (changed)
2863 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002864
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002865 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002866 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002867
Johan Hedberg58e92932014-06-24 14:00:26 +03002868 /* Always ignore debug keys and require a new pairing if
2869 * the user wants to use them.
2870 */
2871 if (key->type == HCI_LK_DEBUG_COMBINATION)
2872 continue;
2873
Johan Hedberg7652ff62014-06-24 13:15:49 +03002874 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2875 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002876 }
2877
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002878 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002879
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002880 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002881
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002882 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002883}
2884
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002885static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002886 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002887{
2888 struct mgmt_ev_device_unpaired ev;
2889
2890 bacpy(&ev.addr.bdaddr, bdaddr);
2891 ev.addr.type = addr_type;
2892
2893 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002894 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002895}
2896
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002897static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002898 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002899{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002900 struct mgmt_cp_unpair_device *cp = data;
2901 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002902 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002903 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002904 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002905 int err;
2906
Johan Hedberga8a1d192011-11-10 15:54:38 +02002907 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002908 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2909 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002910
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002911 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002912 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2913 MGMT_STATUS_INVALID_PARAMS,
2914 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002915
Johan Hedberg118da702013-01-20 14:27:20 +02002916 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002917 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2918 MGMT_STATUS_INVALID_PARAMS,
2919 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002920
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002921 hci_dev_lock(hdev);
2922
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002923 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002924 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2925 MGMT_STATUS_NOT_POWERED, &rp,
2926 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002927 goto unlock;
2928 }
2929
Johan Hedberge0b2b272014-02-18 17:14:31 +02002930 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002931 /* If disconnection is requested, then look up the
2932 * connection. If the remote device is connected, it
2933 * will be later used to terminate the link.
2934 *
2935 * Setting it to NULL explicitly will cause no
2936 * termination of the link.
2937 */
2938 if (cp->disconnect)
2939 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2940 &cp->addr.bdaddr);
2941 else
2942 conn = NULL;
2943
Johan Hedberg124f6e32012-02-09 13:50:12 +02002944 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002945 } else {
2946 u8 addr_type;
2947
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002948 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2949 &cp->addr.bdaddr);
2950 if (conn) {
2951 /* Defer clearing up the connection parameters
2952 * until closing to give a chance of keeping
2953 * them if a repairing happens.
2954 */
2955 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2956
2957 /* If disconnection is not requested, then
2958 * clear the connection variable so that the
2959 * link is not terminated.
2960 */
2961 if (!cp->disconnect)
2962 conn = NULL;
2963 }
2964
Johan Hedberge0b2b272014-02-18 17:14:31 +02002965 if (cp->addr.type == BDADDR_LE_PUBLIC)
2966 addr_type = ADDR_LE_DEV_PUBLIC;
2967 else
2968 addr_type = ADDR_LE_DEV_RANDOM;
2969
Johan Hedberga7ec7332014-02-18 17:14:35 +02002970 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2971
Johan Hedberge0b2b272014-02-18 17:14:31 +02002972 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2973 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002974
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002975 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002976 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2977 MGMT_STATUS_NOT_PAIRED, &rp,
2978 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002979 goto unlock;
2980 }
2981
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002982 /* If the connection variable is set, then termination of the
2983 * link is requested.
2984 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002985 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002986 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2987 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002988 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002989 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002990 }
2991
Johan Hedberg124f6e32012-02-09 13:50:12 +02002992 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002993 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002994 if (!cmd) {
2995 err = -ENOMEM;
2996 goto unlock;
2997 }
2998
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002999 cmd->cmd_complete = addr_cmd_complete;
3000
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003001 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003002 dc.reason = 0x13; /* Remote User Terminated Connection */
3003 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3004 if (err < 0)
3005 mgmt_pending_remove(cmd);
3006
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003007unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003008 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003009 return err;
3010}
3011
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003012static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003013 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003014{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003015 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003016 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003017 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003018 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003019 int err;
3020
3021 BT_DBG("");
3022
Johan Hedberg06a63b12013-01-20 14:27:21 +02003023 memset(&rp, 0, sizeof(rp));
3024 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3025 rp.addr.type = cp->addr.type;
3026
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003027 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003028 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3029 MGMT_STATUS_INVALID_PARAMS,
3030 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003031
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003032 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003033
3034 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003035 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3036 MGMT_STATUS_NOT_POWERED, &rp,
3037 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003038 goto failed;
3039 }
3040
Johan Hedberg333ae952015-03-17 13:48:47 +02003041 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003042 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3043 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003044 goto failed;
3045 }
3046
Andre Guedes591f47f2012-04-24 21:02:49 -03003047 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003048 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3049 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003050 else
3051 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003052
Vishal Agarwalf9607272012-06-13 05:32:43 +05303053 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003054 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3055 MGMT_STATUS_NOT_CONNECTED, &rp,
3056 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003057 goto failed;
3058 }
3059
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003060 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003061 if (!cmd) {
3062 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003063 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003064 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003065
Johan Hedbergf5818c22014-12-05 13:36:02 +02003066 cmd->cmd_complete = generic_cmd_complete;
3067
Johan Hedberge3f2f922014-08-18 20:33:33 +03003068 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003069 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003070 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003071
3072failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003073 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003074 return err;
3075}
3076
Andre Guedes57c14772012-04-24 21:02:50 -03003077static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003078{
3079 switch (link_type) {
3080 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003081 switch (addr_type) {
3082 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003083 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003084
Johan Hedberg48264f02011-11-09 13:58:58 +02003085 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003086 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003087 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003088 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003089
Johan Hedberg4c659c32011-11-07 23:13:39 +02003090 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003091 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003092 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003093 }
3094}
3095
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003096static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3097 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003098{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003099 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003100 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003101 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003102 int err;
3103 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003104
3105 BT_DBG("");
3106
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003107 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003108
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003109 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003110 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3111 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003112 goto unlock;
3113 }
3114
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003115 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003116 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3117 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003118 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003119 }
3120
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003121 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003122 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003123 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003124 err = -ENOMEM;
3125 goto unlock;
3126 }
3127
Johan Hedberg2784eb42011-01-21 13:56:35 +02003128 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003129 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003130 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3131 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003132 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003133 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003134 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003135 continue;
3136 i++;
3137 }
3138
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003139 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003140
Johan Hedberg4c659c32011-11-07 23:13:39 +02003141 /* Recalculate length in case of filtered SCO connections, etc */
3142 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003143
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003144 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3145 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003146
Johan Hedberga38528f2011-01-22 06:46:43 +02003147 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003148
3149unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003150 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003151 return err;
3152}
3153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003154static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003155 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003156{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003157 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003158 int err;
3159
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003160 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003161 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003162 if (!cmd)
3163 return -ENOMEM;
3164
Johan Hedbergd8457692012-02-17 14:24:57 +02003165 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003166 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003167 if (err < 0)
3168 mgmt_pending_remove(cmd);
3169
3170 return err;
3171}
3172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003173static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003174 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003175{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003176 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003177 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003178 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003179 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003180 int err;
3181
3182 BT_DBG("");
3183
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003184 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003185
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003186 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003187 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3188 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003189 goto failed;
3190 }
3191
Johan Hedbergd8457692012-02-17 14:24:57 +02003192 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003193 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003194 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3195 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003196 goto failed;
3197 }
3198
3199 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003200 struct mgmt_cp_pin_code_neg_reply ncp;
3201
3202 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003203
3204 BT_ERR("PIN code is not 16 bytes long");
3205
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003206 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003207 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003208 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3209 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003210
3211 goto failed;
3212 }
3213
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003214 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003215 if (!cmd) {
3216 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003217 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003218 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003219
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003220 cmd->cmd_complete = addr_cmd_complete;
3221
Johan Hedbergd8457692012-02-17 14:24:57 +02003222 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003223 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003224 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003225
3226 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3227 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003228 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003229
3230failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003231 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003232 return err;
3233}
3234
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003235static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3236 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003237{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003238 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003239
3240 BT_DBG("");
3241
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003242 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003243 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3244 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003245
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003246 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003247
3248 hdev->io_capability = cp->io_capability;
3249
3250 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003251 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003252
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003253 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003254
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003255 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3256 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003257}
3258
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003259static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003260{
3261 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003262 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003263
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003264 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003265 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3266 continue;
3267
Johan Hedberge9a416b2011-02-19 12:05:56 -03003268 if (cmd->user_data != conn)
3269 continue;
3270
3271 return cmd;
3272 }
3273
3274 return NULL;
3275}
3276
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003277static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003278{
3279 struct mgmt_rp_pair_device rp;
3280 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003281 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003283 bacpy(&rp.addr.bdaddr, &conn->dst);
3284 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003285
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003286 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3287 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003288
3289 /* So we don't get further callbacks for this connection */
3290 conn->connect_cfm_cb = NULL;
3291 conn->security_cfm_cb = NULL;
3292 conn->disconn_cfm_cb = NULL;
3293
David Herrmann76a68ba2013-04-06 20:28:37 +02003294 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003295
3296 /* The device is paired so there is no need to remove
3297 * its connection parameters anymore.
3298 */
3299 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003300
3301 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003302
3303 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003304}
3305
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003306void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3307{
3308 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003309 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003310
3311 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003312 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003313 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003314 mgmt_pending_remove(cmd);
3315 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003316}
3317
Johan Hedberge9a416b2011-02-19 12:05:56 -03003318static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3319{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003320 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003321
3322 BT_DBG("status %u", status);
3323
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003324 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003325 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003326 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003327 return;
3328 }
3329
3330 cmd->cmd_complete(cmd, mgmt_status(status));
3331 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003332}
3333
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003334static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303335{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003336 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303337
3338 BT_DBG("status %u", status);
3339
3340 if (!status)
3341 return;
3342
3343 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003344 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303345 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003346 return;
3347 }
3348
3349 cmd->cmd_complete(cmd, mgmt_status(status));
3350 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303351}
3352
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003353static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003354 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003355{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003356 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003357 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003358 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003359 u8 sec_level, auth_type;
3360 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003361 int err;
3362
3363 BT_DBG("");
3364
Szymon Jancf950a30e2013-01-18 12:48:07 +01003365 memset(&rp, 0, sizeof(rp));
3366 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3367 rp.addr.type = cp->addr.type;
3368
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003369 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003370 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3371 MGMT_STATUS_INVALID_PARAMS,
3372 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003373
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003374 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003375 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3376 MGMT_STATUS_INVALID_PARAMS,
3377 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003378
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003379 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003380
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003381 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003382 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3383 MGMT_STATUS_NOT_POWERED, &rp,
3384 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003385 goto unlock;
3386 }
3387
Johan Hedberg55e76b32015-03-10 22:34:40 +02003388 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3389 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3390 MGMT_STATUS_ALREADY_PAIRED, &rp,
3391 sizeof(rp));
3392 goto unlock;
3393 }
3394
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003395 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003396 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003397
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003398 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003399 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3400 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003401 } else {
3402 u8 addr_type;
3403
3404 /* Convert from L2CAP channel address type to HCI address type
3405 */
3406 if (cp->addr.type == BDADDR_LE_PUBLIC)
3407 addr_type = ADDR_LE_DEV_PUBLIC;
3408 else
3409 addr_type = ADDR_LE_DEV_RANDOM;
3410
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003411 /* When pairing a new device, it is expected to remember
3412 * this device for future connections. Adding the connection
3413 * parameter information ahead of time allows tracking
3414 * of the slave preferred values and will speed up any
3415 * further connection establishment.
3416 *
3417 * If connection parameters already exist, then they
3418 * will be kept and this function does nothing.
3419 */
3420 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3421
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003422 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003423 sec_level, HCI_LE_CONN_TIMEOUT,
3424 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003425 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003426
Ville Tervo30e76272011-02-22 16:10:53 -03003427 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003428 int status;
3429
3430 if (PTR_ERR(conn) == -EBUSY)
3431 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003432 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3433 status = MGMT_STATUS_NOT_SUPPORTED;
3434 else if (PTR_ERR(conn) == -ECONNREFUSED)
3435 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003436 else
3437 status = MGMT_STATUS_CONNECT_FAILED;
3438
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003439 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3440 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003441 goto unlock;
3442 }
3443
3444 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003445 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003446 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3447 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003448 goto unlock;
3449 }
3450
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003451 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003452 if (!cmd) {
3453 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003454 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003455 goto unlock;
3456 }
3457
Johan Hedberg04ab2742014-12-05 13:36:04 +02003458 cmd->cmd_complete = pairing_complete;
3459
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003460 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003461 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003462 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003463 conn->security_cfm_cb = pairing_complete_cb;
3464 conn->disconn_cfm_cb = pairing_complete_cb;
3465 } else {
3466 conn->connect_cfm_cb = le_pairing_complete_cb;
3467 conn->security_cfm_cb = le_pairing_complete_cb;
3468 conn->disconn_cfm_cb = le_pairing_complete_cb;
3469 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003470
Johan Hedberge9a416b2011-02-19 12:05:56 -03003471 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003472 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003473
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003474 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003475 hci_conn_security(conn, sec_level, auth_type, true)) {
3476 cmd->cmd_complete(cmd, 0);
3477 mgmt_pending_remove(cmd);
3478 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003479
3480 err = 0;
3481
3482unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003483 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003484 return err;
3485}
3486
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003487static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3488 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003489{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003490 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003491 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003492 struct hci_conn *conn;
3493 int err;
3494
3495 BT_DBG("");
3496
Johan Hedberg28424702012-02-02 04:02:29 +02003497 hci_dev_lock(hdev);
3498
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003499 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003500 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3501 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003502 goto unlock;
3503 }
3504
Johan Hedberg333ae952015-03-17 13:48:47 +02003505 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003506 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003507 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3508 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003509 goto unlock;
3510 }
3511
3512 conn = cmd->user_data;
3513
3514 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003515 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3516 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003517 goto unlock;
3518 }
3519
Johan Hedberga511b352014-12-11 21:45:45 +02003520 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3521 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003522
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003523 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3524 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003525unlock:
3526 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003527 return err;
3528}
3529
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003530static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003531 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003532 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003533{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003534 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003535 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003536 int err;
3537
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003538 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003539
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003540 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003541 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3542 MGMT_STATUS_NOT_POWERED, addr,
3543 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003544 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003545 }
3546
Johan Hedberg1707c602013-03-15 17:07:15 -05003547 if (addr->type == BDADDR_BREDR)
3548 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003549 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003550 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003551
Johan Hedberg272d90d2012-02-09 15:26:12 +02003552 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003553 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3554 MGMT_STATUS_NOT_CONNECTED, addr,
3555 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003556 goto done;
3557 }
3558
Johan Hedberg1707c602013-03-15 17:07:15 -05003559 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003560 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003561 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003562 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3563 MGMT_STATUS_SUCCESS, addr,
3564 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003565 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003566 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3567 MGMT_STATUS_FAILED, addr,
3568 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003569
Brian Gix47c15e22011-11-16 13:53:14 -08003570 goto done;
3571 }
3572
Johan Hedberg1707c602013-03-15 17:07:15 -05003573 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003574 if (!cmd) {
3575 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003576 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003577 }
3578
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003579 cmd->cmd_complete = addr_cmd_complete;
3580
Brian Gix0df4c182011-11-16 13:53:13 -08003581 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003582 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3583 struct hci_cp_user_passkey_reply cp;
3584
Johan Hedberg1707c602013-03-15 17:07:15 -05003585 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003586 cp.passkey = passkey;
3587 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3588 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003589 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3590 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003591
Johan Hedberga664b5b2011-02-19 12:06:02 -03003592 if (err < 0)
3593 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003594
Brian Gix0df4c182011-11-16 13:53:13 -08003595done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003596 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003597 return err;
3598}
3599
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303600static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3601 void *data, u16 len)
3602{
3603 struct mgmt_cp_pin_code_neg_reply *cp = data;
3604
3605 BT_DBG("");
3606
Johan Hedberg1707c602013-03-15 17:07:15 -05003607 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303608 MGMT_OP_PIN_CODE_NEG_REPLY,
3609 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3610}
3611
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003612static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3613 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003614{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003615 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003616
3617 BT_DBG("");
3618
3619 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003620 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3621 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003622
Johan Hedberg1707c602013-03-15 17:07:15 -05003623 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003624 MGMT_OP_USER_CONFIRM_REPLY,
3625 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003626}
3627
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003628static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003629 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003630{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003631 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003632
3633 BT_DBG("");
3634
Johan Hedberg1707c602013-03-15 17:07:15 -05003635 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003636 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3637 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003638}
3639
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003640static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3641 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003642{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003643 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003644
3645 BT_DBG("");
3646
Johan Hedberg1707c602013-03-15 17:07:15 -05003647 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003648 MGMT_OP_USER_PASSKEY_REPLY,
3649 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003650}
3651
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003652static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003653 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003654{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003655 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003656
3657 BT_DBG("");
3658
Johan Hedberg1707c602013-03-15 17:07:15 -05003659 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003660 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3661 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003662}
3663
Johan Hedberg13928972013-03-15 17:07:00 -05003664static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003665{
Johan Hedberg13928972013-03-15 17:07:00 -05003666 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003667 struct hci_cp_write_local_name cp;
3668
Johan Hedberg13928972013-03-15 17:07:00 -05003669 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003670
Johan Hedberg890ea892013-03-15 17:06:52 -05003671 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003672}
3673
Marcel Holtmann1904a852015-01-11 13:50:44 -08003674static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003675{
3676 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003677 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003678
3679 BT_DBG("status 0x%02x", status);
3680
3681 hci_dev_lock(hdev);
3682
Johan Hedberg333ae952015-03-17 13:48:47 +02003683 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003684 if (!cmd)
3685 goto unlock;
3686
3687 cp = cmd->param;
3688
3689 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003690 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3691 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003692 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003693 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3694 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003695
3696 mgmt_pending_remove(cmd);
3697
3698unlock:
3699 hci_dev_unlock(hdev);
3700}
3701
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003702static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003703 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003704{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003705 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003706 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003707 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003708 int err;
3709
3710 BT_DBG("");
3711
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003712 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003713
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003714 /* If the old values are the same as the new ones just return a
3715 * direct command complete event.
3716 */
3717 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3718 !memcmp(hdev->short_name, cp->short_name,
3719 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003720 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3721 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003722 goto failed;
3723 }
3724
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003725 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003726
Johan Hedbergb5235a62012-02-21 14:32:24 +02003727 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003728 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003729
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003730 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3731 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003732 if (err < 0)
3733 goto failed;
3734
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003735 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3736 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003737
Johan Hedbergb5235a62012-02-21 14:32:24 +02003738 goto failed;
3739 }
3740
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003741 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003742 if (!cmd) {
3743 err = -ENOMEM;
3744 goto failed;
3745 }
3746
Johan Hedberg13928972013-03-15 17:07:00 -05003747 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3748
Johan Hedberg890ea892013-03-15 17:06:52 -05003749 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003750
3751 if (lmp_bredr_capable(hdev)) {
3752 update_name(&req);
3753 update_eir(&req);
3754 }
3755
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003756 /* The name is stored in the scan response data and so
3757 * no need to udpate the advertising data here.
3758 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003759 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003760 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003761
Johan Hedberg13928972013-03-15 17:07:00 -05003762 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003763 if (err < 0)
3764 mgmt_pending_remove(cmd);
3765
3766failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003767 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003768 return err;
3769}
3770
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003771static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003772 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003773{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003774 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003775 int err;
3776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003777 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003778
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003779 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003780
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003781 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003782 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3783 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003784 goto unlock;
3785 }
3786
Andre Guedes9a1a1992012-07-24 15:03:48 -03003787 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003788 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3789 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003790 goto unlock;
3791 }
3792
Johan Hedberg333ae952015-03-17 13:48:47 +02003793 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003794 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3795 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003796 goto unlock;
3797 }
3798
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003799 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003800 if (!cmd) {
3801 err = -ENOMEM;
3802 goto unlock;
3803 }
3804
Johan Hedberg710f11c2014-05-26 11:21:22 +03003805 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003806 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3807 0, NULL);
3808 else
3809 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3810
Szymon Jancc35938b2011-03-22 13:12:21 +01003811 if (err < 0)
3812 mgmt_pending_remove(cmd);
3813
3814unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003815 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003816 return err;
3817}
3818
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003819static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003820 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003821{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003822 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003823 int err;
3824
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003825 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003826
Johan Hedberg5d57e792015-01-23 10:10:38 +02003827 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003828 return mgmt_cmd_complete(sk, hdev->id,
3829 MGMT_OP_ADD_REMOTE_OOB_DATA,
3830 MGMT_STATUS_INVALID_PARAMS,
3831 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003832
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003833 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003834
Marcel Holtmannec109112014-01-10 02:07:30 -08003835 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3836 struct mgmt_cp_add_remote_oob_data *cp = data;
3837 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003838
Johan Hedbergc19a4952014-11-17 20:52:19 +02003839 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003840 err = mgmt_cmd_complete(sk, hdev->id,
3841 MGMT_OP_ADD_REMOTE_OOB_DATA,
3842 MGMT_STATUS_INVALID_PARAMS,
3843 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003844 goto unlock;
3845 }
3846
Marcel Holtmannec109112014-01-10 02:07:30 -08003847 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003848 cp->addr.type, cp->hash,
3849 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003850 if (err < 0)
3851 status = MGMT_STATUS_FAILED;
3852 else
3853 status = MGMT_STATUS_SUCCESS;
3854
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003855 err = mgmt_cmd_complete(sk, hdev->id,
3856 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3857 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003858 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3859 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003860 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003861 u8 status;
3862
Johan Hedberg86df9202014-10-26 20:52:27 +01003863 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003864 /* Enforce zero-valued 192-bit parameters as
3865 * long as legacy SMP OOB isn't implemented.
3866 */
3867 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3868 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003869 err = mgmt_cmd_complete(sk, hdev->id,
3870 MGMT_OP_ADD_REMOTE_OOB_DATA,
3871 MGMT_STATUS_INVALID_PARAMS,
3872 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003873 goto unlock;
3874 }
3875
Johan Hedberg86df9202014-10-26 20:52:27 +01003876 rand192 = NULL;
3877 hash192 = NULL;
3878 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003879 /* In case one of the P-192 values is set to zero,
3880 * then just disable OOB data for P-192.
3881 */
3882 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3883 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3884 rand192 = NULL;
3885 hash192 = NULL;
3886 } else {
3887 rand192 = cp->rand192;
3888 hash192 = cp->hash192;
3889 }
3890 }
3891
3892 /* In case one of the P-256 values is set to zero, then just
3893 * disable OOB data for P-256.
3894 */
3895 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3896 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3897 rand256 = NULL;
3898 hash256 = NULL;
3899 } else {
3900 rand256 = cp->rand256;
3901 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003902 }
3903
Johan Hedberg81328d52014-10-26 20:33:47 +01003904 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003905 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003906 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003907 if (err < 0)
3908 status = MGMT_STATUS_FAILED;
3909 else
3910 status = MGMT_STATUS_SUCCESS;
3911
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003912 err = mgmt_cmd_complete(sk, hdev->id,
3913 MGMT_OP_ADD_REMOTE_OOB_DATA,
3914 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003915 } else {
3916 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003917 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3918 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003919 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003920
Johan Hedbergc19a4952014-11-17 20:52:19 +02003921unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003922 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003923 return err;
3924}
3925
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003926static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003927 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003928{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003929 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003930 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003931 int err;
3932
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003933 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003934
Johan Hedbergc19a4952014-11-17 20:52:19 +02003935 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003936 return mgmt_cmd_complete(sk, hdev->id,
3937 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3938 MGMT_STATUS_INVALID_PARAMS,
3939 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003940
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003941 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003942
Johan Hedbergeedbd582014-11-15 09:34:23 +02003943 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3944 hci_remote_oob_data_clear(hdev);
3945 status = MGMT_STATUS_SUCCESS;
3946 goto done;
3947 }
3948
Johan Hedberg6928a922014-10-26 20:46:09 +01003949 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003950 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003951 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003952 else
Szymon Janca6785be2012-12-13 15:11:21 +01003953 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003954
Johan Hedbergeedbd582014-11-15 09:34:23 +02003955done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003956 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3957 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003958
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003959 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003960 return err;
3961}
3962
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003963static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
3964{
3965 struct hci_dev *hdev = req->hdev;
3966 struct hci_cp_inquiry cp;
3967 /* General inquiry access code (GIAC) */
3968 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3969
3970 *status = mgmt_bredr_support(hdev);
3971 if (*status)
3972 return false;
3973
3974 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
3975 *status = MGMT_STATUS_BUSY;
3976 return false;
3977 }
3978
3979 hci_inquiry_cache_flush(hdev);
3980
3981 memset(&cp, 0, sizeof(cp));
3982 memcpy(&cp.lap, lap, sizeof(cp.lap));
3983 cp.length = DISCOV_BREDR_INQUIRY_LEN;
3984
3985 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
3986
3987 return true;
3988}
3989
3990static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003991{
Marcel Holtmann80190442014-12-04 11:36:36 +01003992 struct hci_dev *hdev = req->hdev;
3993 struct hci_cp_le_set_scan_param param_cp;
3994 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01003995 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003996 int err;
3997
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003998 *status = mgmt_le_support(hdev);
3999 if (*status)
4000 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004001
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004002 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4003 /* Don't let discovery abort an outgoing connection attempt
4004 * that's using directed advertising.
4005 */
4006 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4007 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004008 return false;
4009 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004010
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004011 disable_advertising(req);
4012 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004013
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004014 /* If controller is scanning, it means the background scanning is
4015 * running. Thus, we should temporarily stop it in order to set the
4016 * discovery scanning parameters.
4017 */
4018 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4019 hci_req_add_le_scan_disable(req);
4020
4021 /* All active scans will be done with either a resolvable private
4022 * address (when privacy feature has been enabled) or non-resolvable
4023 * private address.
4024 */
4025 err = hci_update_random_address(req, true, &own_addr_type);
4026 if (err < 0) {
4027 *status = MGMT_STATUS_FAILED;
4028 return false;
4029 }
4030
4031 memset(&param_cp, 0, sizeof(param_cp));
4032 param_cp.type = LE_SCAN_ACTIVE;
4033 param_cp.interval = cpu_to_le16(interval);
4034 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4035 param_cp.own_address_type = own_addr_type;
4036
4037 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4038 &param_cp);
4039
4040 memset(&enable_cp, 0, sizeof(enable_cp));
4041 enable_cp.enable = LE_SCAN_ENABLE;
4042 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4043
4044 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4045 &enable_cp);
4046
4047 return true;
4048}
4049
4050static bool trigger_discovery(struct hci_request *req, u8 *status)
4051{
4052 struct hci_dev *hdev = req->hdev;
4053
4054 switch (hdev->discovery.type) {
4055 case DISCOV_TYPE_BREDR:
4056 if (!trigger_bredr_inquiry(req, status))
4057 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004058 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004059
Marcel Holtmann80190442014-12-04 11:36:36 +01004060 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004061 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4062 &hdev->quirks)) {
4063 /* During simultaneous discovery, we double LE scan
4064 * interval. We must leave some time for the controller
4065 * to do BR/EDR inquiry.
4066 */
4067 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4068 status))
4069 return false;
4070
4071 if (!trigger_bredr_inquiry(req, status))
4072 return false;
4073
4074 return true;
4075 }
4076
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004077 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004078 *status = MGMT_STATUS_NOT_SUPPORTED;
4079 return false;
4080 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004081 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004082
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004083 case DISCOV_TYPE_LE:
4084 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004085 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004086 break;
4087
4088 default:
4089 *status = MGMT_STATUS_INVALID_PARAMS;
4090 return false;
4091 }
4092
4093 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004094}
4095
Marcel Holtmann1904a852015-01-11 13:50:44 -08004096static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4097 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004098{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004099 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004100 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004101
Andre Guedes7c307722013-04-30 15:29:28 -03004102 BT_DBG("status %d", status);
4103
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004104 hci_dev_lock(hdev);
4105
Johan Hedberg333ae952015-03-17 13:48:47 +02004106 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004107 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004108 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004109
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004110 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004111 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004112 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004113 }
4114
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004115 if (status) {
4116 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4117 goto unlock;
4118 }
4119
Andre Guedes7c307722013-04-30 15:29:28 -03004120 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004121
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004122 /* If the scan involves LE scan, pick proper timeout to schedule
4123 * hdev->le_scan_disable that will stop it.
4124 */
Andre Guedes7c307722013-04-30 15:29:28 -03004125 switch (hdev->discovery.type) {
4126 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004127 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004128 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004129 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004130 /* When running simultaneous discovery, the LE scanning time
4131 * should occupy the whole discovery time sine BR/EDR inquiry
4132 * and LE scanning are scheduled by the controller.
4133 *
4134 * For interleaving discovery in comparison, BR/EDR inquiry
4135 * and LE scanning are done sequentially with separate
4136 * timeouts.
4137 */
4138 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4139 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4140 else
4141 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004142 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004143 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004144 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004145 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004146 default:
4147 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004148 timeout = 0;
4149 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004150 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004151
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004152 if (timeout) {
4153 /* When service discovery is used and the controller has
4154 * a strict duplicate filter, it is important to remember
4155 * the start and duration of the scan. This is required
4156 * for restarting scanning during the discovery phase.
4157 */
4158 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4159 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004160 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004161 hdev->discovery.scan_start = jiffies;
4162 hdev->discovery.scan_duration = timeout;
4163 }
4164
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004165 queue_delayed_work(hdev->workqueue,
4166 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004167 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004168
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004169unlock:
4170 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004171}
4172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004173static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004174 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004175{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004176 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004177 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004178 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004179 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004180 int err;
4181
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004182 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004183
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004184 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004185
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004186 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004187 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4188 MGMT_STATUS_NOT_POWERED,
4189 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004190 goto failed;
4191 }
4192
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004193 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004194 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004195 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4196 MGMT_STATUS_BUSY, &cp->type,
4197 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004198 goto failed;
4199 }
4200
Johan Hedberg2922a942014-12-05 13:36:06 +02004201 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004202 if (!cmd) {
4203 err = -ENOMEM;
4204 goto failed;
4205 }
4206
Johan Hedberg2922a942014-12-05 13:36:06 +02004207 cmd->cmd_complete = generic_cmd_complete;
4208
Marcel Holtmann22078802014-12-05 11:45:22 +01004209 /* Clear the discovery filter first to free any previously
4210 * allocated memory for the UUID list.
4211 */
4212 hci_discovery_filter_clear(hdev);
4213
Andre Guedes4aab14e2012-02-17 20:39:36 -03004214 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004215 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004216
Andre Guedes7c307722013-04-30 15:29:28 -03004217 hci_req_init(&req, hdev);
4218
Marcel Holtmann80190442014-12-04 11:36:36 +01004219 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004220 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4221 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004222 mgmt_pending_remove(cmd);
4223 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004224 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004225
Andre Guedes7c307722013-04-30 15:29:28 -03004226 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004227 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004228 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004229 goto failed;
4230 }
4231
4232 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004233
4234failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004235 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004236 return err;
4237}
4238
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004239static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4240 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004241{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004242 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4243 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004244}
4245
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004246static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4247 void *data, u16 len)
4248{
4249 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004250 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004251 struct hci_request req;
4252 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4253 u16 uuid_count, expected_len;
4254 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004255 int err;
4256
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004257 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004258
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004259 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004260
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004261 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004262 err = mgmt_cmd_complete(sk, hdev->id,
4263 MGMT_OP_START_SERVICE_DISCOVERY,
4264 MGMT_STATUS_NOT_POWERED,
4265 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004266 goto failed;
4267 }
4268
4269 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004270 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004271 err = mgmt_cmd_complete(sk, hdev->id,
4272 MGMT_OP_START_SERVICE_DISCOVERY,
4273 MGMT_STATUS_BUSY, &cp->type,
4274 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004275 goto failed;
4276 }
4277
4278 uuid_count = __le16_to_cpu(cp->uuid_count);
4279 if (uuid_count > max_uuid_count) {
4280 BT_ERR("service_discovery: too big uuid_count value %u",
4281 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004282 err = mgmt_cmd_complete(sk, hdev->id,
4283 MGMT_OP_START_SERVICE_DISCOVERY,
4284 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4285 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004286 goto failed;
4287 }
4288
4289 expected_len = sizeof(*cp) + uuid_count * 16;
4290 if (expected_len != len) {
4291 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4292 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004293 err = mgmt_cmd_complete(sk, hdev->id,
4294 MGMT_OP_START_SERVICE_DISCOVERY,
4295 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4296 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004297 goto failed;
4298 }
4299
4300 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004301 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004302 if (!cmd) {
4303 err = -ENOMEM;
4304 goto failed;
4305 }
4306
Johan Hedberg2922a942014-12-05 13:36:06 +02004307 cmd->cmd_complete = service_discovery_cmd_complete;
4308
Marcel Holtmann22078802014-12-05 11:45:22 +01004309 /* Clear the discovery filter first to free any previously
4310 * allocated memory for the UUID list.
4311 */
4312 hci_discovery_filter_clear(hdev);
4313
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004314 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004315 hdev->discovery.type = cp->type;
4316 hdev->discovery.rssi = cp->rssi;
4317 hdev->discovery.uuid_count = uuid_count;
4318
4319 if (uuid_count > 0) {
4320 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4321 GFP_KERNEL);
4322 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004323 err = mgmt_cmd_complete(sk, hdev->id,
4324 MGMT_OP_START_SERVICE_DISCOVERY,
4325 MGMT_STATUS_FAILED,
4326 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004327 mgmt_pending_remove(cmd);
4328 goto failed;
4329 }
4330 }
4331
4332 hci_req_init(&req, hdev);
4333
4334 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004335 err = mgmt_cmd_complete(sk, hdev->id,
4336 MGMT_OP_START_SERVICE_DISCOVERY,
4337 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004338 mgmt_pending_remove(cmd);
4339 goto failed;
4340 }
4341
4342 err = hci_req_run(&req, start_discovery_complete);
4343 if (err < 0) {
4344 mgmt_pending_remove(cmd);
4345 goto failed;
4346 }
4347
4348 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4349
4350failed:
4351 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004352 return err;
4353}
4354
Marcel Holtmann1904a852015-01-11 13:50:44 -08004355static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004356{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004357 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004358
Andre Guedes0e05bba2013-04-30 15:29:33 -03004359 BT_DBG("status %d", status);
4360
4361 hci_dev_lock(hdev);
4362
Johan Hedberg333ae952015-03-17 13:48:47 +02004363 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004364 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004365 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004366 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004367 }
4368
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004369 if (!status)
4370 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004371
Andre Guedes0e05bba2013-04-30 15:29:33 -03004372 hci_dev_unlock(hdev);
4373}
4374
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004375static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004376 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004377{
Johan Hedbergd9306502012-02-20 23:25:18 +02004378 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004379 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004380 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004381 int err;
4382
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004383 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004384
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004385 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004386
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004387 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004388 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4389 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4390 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004391 goto unlock;
4392 }
4393
4394 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004395 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4396 MGMT_STATUS_INVALID_PARAMS,
4397 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004398 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004399 }
4400
Johan Hedberg2922a942014-12-05 13:36:06 +02004401 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004402 if (!cmd) {
4403 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004404 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004405 }
4406
Johan Hedberg2922a942014-12-05 13:36:06 +02004407 cmd->cmd_complete = generic_cmd_complete;
4408
Andre Guedes0e05bba2013-04-30 15:29:33 -03004409 hci_req_init(&req, hdev);
4410
Johan Hedberg21a60d32014-06-10 14:05:58 +03004411 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004412
Johan Hedberg21a60d32014-06-10 14:05:58 +03004413 err = hci_req_run(&req, stop_discovery_complete);
4414 if (!err) {
4415 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004416 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004417 }
4418
Johan Hedberg21a60d32014-06-10 14:05:58 +03004419 mgmt_pending_remove(cmd);
4420
4421 /* If no HCI commands were sent we're done */
4422 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004423 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4424 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004425 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4426 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004427
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004428unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004429 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004430 return err;
4431}
4432
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004433static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004434 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004435{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004436 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004437 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004438 int err;
4439
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004440 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004441
Johan Hedberg561aafb2012-01-04 13:31:59 +02004442 hci_dev_lock(hdev);
4443
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004444 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004445 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4446 MGMT_STATUS_FAILED, &cp->addr,
4447 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004448 goto failed;
4449 }
4450
Johan Hedberga198e7b2012-02-17 14:27:06 +02004451 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004452 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004453 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4454 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4455 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004456 goto failed;
4457 }
4458
4459 if (cp->name_known) {
4460 e->name_state = NAME_KNOWN;
4461 list_del(&e->list);
4462 } else {
4463 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004464 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004465 }
4466
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004467 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4468 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004469
4470failed:
4471 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004472 return err;
4473}
4474
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004475static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004476 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004477{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004478 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004479 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004480 int err;
4481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004482 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004483
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004484 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004485 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4486 MGMT_STATUS_INVALID_PARAMS,
4487 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004488
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004489 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004490
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004491 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4492 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004493 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004494 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004495 goto done;
4496 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004497
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004498 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4499 sk);
4500 status = MGMT_STATUS_SUCCESS;
4501
4502done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004503 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4504 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004505
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004506 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004507
4508 return err;
4509}
4510
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004511static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004512 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004513{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004514 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004515 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004516 int err;
4517
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004518 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004519
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004520 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004521 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4522 MGMT_STATUS_INVALID_PARAMS,
4523 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004524
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004525 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004526
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004527 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4528 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004529 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004530 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004531 goto done;
4532 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004533
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004534 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4535 sk);
4536 status = MGMT_STATUS_SUCCESS;
4537
4538done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004539 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4540 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004541
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004542 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004543
4544 return err;
4545}
4546
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004547static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4548 u16 len)
4549{
4550 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004551 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004552 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004553 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004554
4555 BT_DBG("%s", hdev->name);
4556
Szymon Jancc72d4b82012-03-16 16:02:57 +01004557 source = __le16_to_cpu(cp->source);
4558
4559 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004560 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4561 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004562
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004563 hci_dev_lock(hdev);
4564
Szymon Jancc72d4b82012-03-16 16:02:57 +01004565 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004566 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4567 hdev->devid_product = __le16_to_cpu(cp->product);
4568 hdev->devid_version = __le16_to_cpu(cp->version);
4569
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004570 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4571 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004572
Johan Hedberg890ea892013-03-15 17:06:52 -05004573 hci_req_init(&req, hdev);
4574 update_eir(&req);
4575 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004576
4577 hci_dev_unlock(hdev);
4578
4579 return err;
4580}
4581
Arman Uguray24b4f382015-03-23 15:57:12 -07004582static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4583 u16 opcode)
4584{
4585 BT_DBG("status %d", status);
4586}
4587
Marcel Holtmann1904a852015-01-11 13:50:44 -08004588static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4589 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004590{
4591 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004592 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004593
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304594 hci_dev_lock(hdev);
4595
Johan Hedberg4375f102013-09-25 13:26:10 +03004596 if (status) {
4597 u8 mgmt_err = mgmt_status(status);
4598
4599 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4600 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304601 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004602 }
4603
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004604 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004605 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004606 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004607 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004608
Johan Hedberg4375f102013-09-25 13:26:10 +03004609 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4610 &match);
4611
4612 new_settings(hdev, match.sk);
4613
4614 if (match.sk)
4615 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304616
Arman Uguray24b4f382015-03-23 15:57:12 -07004617 /* If "Set Advertising" was just disabled and instance advertising was
4618 * set up earlier, then enable the advertising instance.
4619 */
4620 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4621 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4622 goto unlock;
4623
4624 hci_req_init(&req, hdev);
4625
4626 update_adv_data(&req);
4627 enable_advertising(&req);
4628
4629 if (hci_req_run(&req, enable_advertising_instance) < 0)
4630 BT_ERR("Failed to re-configure advertising");
4631
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304632unlock:
4633 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004634}
4635
Marcel Holtmann21b51872013-10-10 09:47:53 -07004636static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4637 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004638{
4639 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004640 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004641 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004642 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004643 int err;
4644
4645 BT_DBG("request for %s", hdev->name);
4646
Johan Hedberge6fe7982013-10-02 15:45:22 +03004647 status = mgmt_le_support(hdev);
4648 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004649 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4650 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004651
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004652 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004653 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4654 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004655
4656 hci_dev_lock(hdev);
4657
4658 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004659
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004660 /* The following conditions are ones which mean that we should
4661 * not do any HCI communication but directly send a mgmt
4662 * response to user space (after toggling the flag if
4663 * necessary).
4664 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004665 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004666 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4667 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004668 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004669 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004670 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004671 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004672
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004673 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004674 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004675 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004676 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004677 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004678 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004679 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004680 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004681 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004682 }
4683
4684 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4685 if (err < 0)
4686 goto unlock;
4687
4688 if (changed)
4689 err = new_settings(hdev, sk);
4690
4691 goto unlock;
4692 }
4693
Johan Hedberg333ae952015-03-17 13:48:47 +02004694 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4695 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004696 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4697 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004698 goto unlock;
4699 }
4700
4701 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4702 if (!cmd) {
4703 err = -ENOMEM;
4704 goto unlock;
4705 }
4706
4707 hci_req_init(&req, hdev);
4708
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004709 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004710 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004711 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004712 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004713
Arman Uguray24b4f382015-03-23 15:57:12 -07004714 if (val) {
4715 /* Switch to instance "0" for the Set Advertising setting. */
4716 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004717 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004718 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004719 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004720 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004721 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004722
4723 err = hci_req_run(&req, set_advertising_complete);
4724 if (err < 0)
4725 mgmt_pending_remove(cmd);
4726
4727unlock:
4728 hci_dev_unlock(hdev);
4729 return err;
4730}
4731
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004732static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4733 void *data, u16 len)
4734{
4735 struct mgmt_cp_set_static_address *cp = data;
4736 int err;
4737
4738 BT_DBG("%s", hdev->name);
4739
Marcel Holtmann62af4442013-10-02 22:10:32 -07004740 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004741 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4742 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004743
4744 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004745 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4746 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004747
4748 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4749 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004750 return mgmt_cmd_status(sk, hdev->id,
4751 MGMT_OP_SET_STATIC_ADDRESS,
4752 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004753
4754 /* Two most significant bits shall be set */
4755 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004756 return mgmt_cmd_status(sk, hdev->id,
4757 MGMT_OP_SET_STATIC_ADDRESS,
4758 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004759 }
4760
4761 hci_dev_lock(hdev);
4762
4763 bacpy(&hdev->static_addr, &cp->bdaddr);
4764
Marcel Holtmann93690c22015-03-06 10:11:21 -08004765 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4766 if (err < 0)
4767 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004768
Marcel Holtmann93690c22015-03-06 10:11:21 -08004769 err = new_settings(hdev, sk);
4770
4771unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004772 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004773 return err;
4774}
4775
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004776static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4777 void *data, u16 len)
4778{
4779 struct mgmt_cp_set_scan_params *cp = data;
4780 __u16 interval, window;
4781 int err;
4782
4783 BT_DBG("%s", hdev->name);
4784
4785 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004786 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4787 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004788
4789 interval = __le16_to_cpu(cp->interval);
4790
4791 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004792 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4793 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004794
4795 window = __le16_to_cpu(cp->window);
4796
4797 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004798 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4799 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004800
Marcel Holtmann899e1072013-10-14 09:55:32 -07004801 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004802 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4803 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004804
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004805 hci_dev_lock(hdev);
4806
4807 hdev->le_scan_interval = interval;
4808 hdev->le_scan_window = window;
4809
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004810 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4811 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004812
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004813 /* If background scan is running, restart it so new parameters are
4814 * loaded.
4815 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004816 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004817 hdev->discovery.state == DISCOVERY_STOPPED) {
4818 struct hci_request req;
4819
4820 hci_req_init(&req, hdev);
4821
4822 hci_req_add_le_scan_disable(&req);
4823 hci_req_add_le_passive_scan(&req);
4824
4825 hci_req_run(&req, NULL);
4826 }
4827
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004828 hci_dev_unlock(hdev);
4829
4830 return err;
4831}
4832
Marcel Holtmann1904a852015-01-11 13:50:44 -08004833static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4834 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004835{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004836 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004837
4838 BT_DBG("status 0x%02x", status);
4839
4840 hci_dev_lock(hdev);
4841
Johan Hedberg333ae952015-03-17 13:48:47 +02004842 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004843 if (!cmd)
4844 goto unlock;
4845
4846 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004847 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4848 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004849 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004850 struct mgmt_mode *cp = cmd->param;
4851
4852 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004853 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004854 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004855 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004856
Johan Hedberg33e38b32013-03-15 17:07:05 -05004857 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4858 new_settings(hdev, cmd->sk);
4859 }
4860
4861 mgmt_pending_remove(cmd);
4862
4863unlock:
4864 hci_dev_unlock(hdev);
4865}
4866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004867static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004868 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004869{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004870 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004871 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004872 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004873 int err;
4874
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004875 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004876
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004877 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004878 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004879 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4880 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004881
Johan Hedberga7e80f22013-01-09 16:05:19 +02004882 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004883 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4884 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004885
Antti Julkuf6422ec2011-06-22 13:11:56 +03004886 hci_dev_lock(hdev);
4887
Johan Hedberg333ae952015-03-17 13:48:47 +02004888 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004889 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4890 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004891 goto unlock;
4892 }
4893
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004894 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004895 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4896 hdev);
4897 goto unlock;
4898 }
4899
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004900 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004901 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004902 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4903 hdev);
4904 new_settings(hdev, sk);
4905 goto unlock;
4906 }
4907
Johan Hedberg33e38b32013-03-15 17:07:05 -05004908 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4909 data, len);
4910 if (!cmd) {
4911 err = -ENOMEM;
4912 goto unlock;
4913 }
4914
4915 hci_req_init(&req, hdev);
4916
Johan Hedberg406d7802013-03-15 17:07:09 -05004917 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004918
4919 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004920 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004921 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4922 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004923 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004924 }
4925
Johan Hedberg33e38b32013-03-15 17:07:05 -05004926unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004927 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004928
Antti Julkuf6422ec2011-06-22 13:11:56 +03004929 return err;
4930}
4931
Marcel Holtmann1904a852015-01-11 13:50:44 -08004932static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004933{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004934 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004935
4936 BT_DBG("status 0x%02x", status);
4937
4938 hci_dev_lock(hdev);
4939
Johan Hedberg333ae952015-03-17 13:48:47 +02004940 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004941 if (!cmd)
4942 goto unlock;
4943
4944 if (status) {
4945 u8 mgmt_err = mgmt_status(status);
4946
4947 /* We need to restore the flag if related HCI commands
4948 * failed.
4949 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004950 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004951
Johan Hedberga69e8372015-03-06 21:08:53 +02004952 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004953 } else {
4954 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4955 new_settings(hdev, cmd->sk);
4956 }
4957
4958 mgmt_pending_remove(cmd);
4959
4960unlock:
4961 hci_dev_unlock(hdev);
4962}
4963
4964static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4965{
4966 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004967 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004968 struct hci_request req;
4969 int err;
4970
4971 BT_DBG("request for %s", hdev->name);
4972
4973 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004974 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4975 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004976
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004977 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004978 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4979 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004980
4981 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004982 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4983 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004984
4985 hci_dev_lock(hdev);
4986
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004987 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004988 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4989 goto unlock;
4990 }
4991
4992 if (!hdev_is_powered(hdev)) {
4993 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004994 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4995 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4996 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4997 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4998 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004999 }
5000
Marcel Holtmannce05d602015-03-13 02:11:03 -07005001 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005002
5003 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5004 if (err < 0)
5005 goto unlock;
5006
5007 err = new_settings(hdev, sk);
5008 goto unlock;
5009 }
5010
5011 /* Reject disabling when powered on */
5012 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005013 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5014 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005015 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005016 } else {
5017 /* When configuring a dual-mode controller to operate
5018 * with LE only and using a static address, then switching
5019 * BR/EDR back on is not allowed.
5020 *
5021 * Dual-mode controllers shall operate with the public
5022 * address as its identity address for BR/EDR and LE. So
5023 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005024 *
5025 * The same restrictions applies when secure connections
5026 * has been enabled. For BR/EDR this is a controller feature
5027 * while for LE it is a host stack feature. This means that
5028 * switching BR/EDR back on when secure connections has been
5029 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005030 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005031 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005032 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005033 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005034 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5035 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005036 goto unlock;
5037 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005038 }
5039
Johan Hedberg333ae952015-03-17 13:48:47 +02005040 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005041 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5042 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005043 goto unlock;
5044 }
5045
5046 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5047 if (!cmd) {
5048 err = -ENOMEM;
5049 goto unlock;
5050 }
5051
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005052 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005053 * generates the correct flags.
5054 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005055 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005056
5057 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005058
Johan Hedberg432df052014-08-01 11:13:31 +03005059 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005060 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005061
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005062 /* Since only the advertising data flags will change, there
5063 * is no need to update the scan response data.
5064 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005065 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005066
Johan Hedberg0663ca22013-10-02 13:43:14 +03005067 err = hci_req_run(&req, set_bredr_complete);
5068 if (err < 0)
5069 mgmt_pending_remove(cmd);
5070
5071unlock:
5072 hci_dev_unlock(hdev);
5073 return err;
5074}
5075
Johan Hedberga1443f52015-01-23 15:42:46 +02005076static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5077{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005078 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005079 struct mgmt_mode *cp;
5080
5081 BT_DBG("%s status %u", hdev->name, status);
5082
5083 hci_dev_lock(hdev);
5084
Johan Hedberg333ae952015-03-17 13:48:47 +02005085 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005086 if (!cmd)
5087 goto unlock;
5088
5089 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005090 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5091 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005092 goto remove;
5093 }
5094
5095 cp = cmd->param;
5096
5097 switch (cp->val) {
5098 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005099 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5100 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005101 break;
5102 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005103 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005104 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005105 break;
5106 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005107 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5108 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005109 break;
5110 }
5111
5112 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5113 new_settings(hdev, cmd->sk);
5114
5115remove:
5116 mgmt_pending_remove(cmd);
5117unlock:
5118 hci_dev_unlock(hdev);
5119}
5120
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005121static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5122 void *data, u16 len)
5123{
5124 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005125 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005126 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005127 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005128 int err;
5129
5130 BT_DBG("request for %s", hdev->name);
5131
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005132 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005133 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005134 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5135 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005136
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005137 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005138 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005139 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005140 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5141 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005142
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005143 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005144 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005145 MGMT_STATUS_INVALID_PARAMS);
5146
5147 hci_dev_lock(hdev);
5148
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005149 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005150 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005151 bool changed;
5152
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005153 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005154 changed = !hci_dev_test_and_set_flag(hdev,
5155 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005156 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005157 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005158 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005159 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005160 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005161 changed = hci_dev_test_and_clear_flag(hdev,
5162 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005163 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005164 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005165
5166 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5167 if (err < 0)
5168 goto failed;
5169
5170 if (changed)
5171 err = new_settings(hdev, sk);
5172
5173 goto failed;
5174 }
5175
Johan Hedberg333ae952015-03-17 13:48:47 +02005176 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005177 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5178 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005179 goto failed;
5180 }
5181
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005182 val = !!cp->val;
5183
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005184 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5185 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005186 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5187 goto failed;
5188 }
5189
5190 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5191 if (!cmd) {
5192 err = -ENOMEM;
5193 goto failed;
5194 }
5195
Johan Hedberga1443f52015-01-23 15:42:46 +02005196 hci_req_init(&req, hdev);
5197 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5198 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005199 if (err < 0) {
5200 mgmt_pending_remove(cmd);
5201 goto failed;
5202 }
5203
5204failed:
5205 hci_dev_unlock(hdev);
5206 return err;
5207}
5208
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005209static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5210 void *data, u16 len)
5211{
5212 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005213 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005214 int err;
5215
5216 BT_DBG("request for %s", hdev->name);
5217
Johan Hedbergb97109792014-06-24 14:00:28 +03005218 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005219 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5220 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005221
5222 hci_dev_lock(hdev);
5223
5224 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005225 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005226 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005227 changed = hci_dev_test_and_clear_flag(hdev,
5228 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005229
Johan Hedbergb97109792014-06-24 14:00:28 +03005230 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005231 use_changed = !hci_dev_test_and_set_flag(hdev,
5232 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005233 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005234 use_changed = hci_dev_test_and_clear_flag(hdev,
5235 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005236
5237 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005238 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005239 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5240 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5241 sizeof(mode), &mode);
5242 }
5243
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005244 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5245 if (err < 0)
5246 goto unlock;
5247
5248 if (changed)
5249 err = new_settings(hdev, sk);
5250
5251unlock:
5252 hci_dev_unlock(hdev);
5253 return err;
5254}
5255
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005256static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5257 u16 len)
5258{
5259 struct mgmt_cp_set_privacy *cp = cp_data;
5260 bool changed;
5261 int err;
5262
5263 BT_DBG("request for %s", hdev->name);
5264
5265 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005266 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5267 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005268
5269 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005270 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5271 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005272
5273 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005274 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5275 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005276
5277 hci_dev_lock(hdev);
5278
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005279 /* If user space supports this command it is also expected to
5280 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5281 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005282 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005283
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005284 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005285 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005286 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005287 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005288 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005289 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005290 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005291 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005292 }
5293
5294 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5295 if (err < 0)
5296 goto unlock;
5297
5298 if (changed)
5299 err = new_settings(hdev, sk);
5300
5301unlock:
5302 hci_dev_unlock(hdev);
5303 return err;
5304}
5305
Johan Hedberg41edf162014-02-18 10:19:35 +02005306static bool irk_is_valid(struct mgmt_irk_info *irk)
5307{
5308 switch (irk->addr.type) {
5309 case BDADDR_LE_PUBLIC:
5310 return true;
5311
5312 case BDADDR_LE_RANDOM:
5313 /* Two most significant bits shall be set */
5314 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5315 return false;
5316 return true;
5317 }
5318
5319 return false;
5320}
5321
5322static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5323 u16 len)
5324{
5325 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005326 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5327 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005328 u16 irk_count, expected_len;
5329 int i, err;
5330
5331 BT_DBG("request for %s", hdev->name);
5332
5333 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005334 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5335 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005336
5337 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005338 if (irk_count > max_irk_count) {
5339 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005340 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5341 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005342 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005343
5344 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5345 if (expected_len != len) {
5346 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005347 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005348 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5349 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005350 }
5351
5352 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5353
5354 for (i = 0; i < irk_count; i++) {
5355 struct mgmt_irk_info *key = &cp->irks[i];
5356
5357 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005358 return mgmt_cmd_status(sk, hdev->id,
5359 MGMT_OP_LOAD_IRKS,
5360 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005361 }
5362
5363 hci_dev_lock(hdev);
5364
5365 hci_smp_irks_clear(hdev);
5366
5367 for (i = 0; i < irk_count; i++) {
5368 struct mgmt_irk_info *irk = &cp->irks[i];
5369 u8 addr_type;
5370
5371 if (irk->addr.type == BDADDR_LE_PUBLIC)
5372 addr_type = ADDR_LE_DEV_PUBLIC;
5373 else
5374 addr_type = ADDR_LE_DEV_RANDOM;
5375
5376 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5377 BDADDR_ANY);
5378 }
5379
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005380 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005381
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005382 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005383
5384 hci_dev_unlock(hdev);
5385
5386 return err;
5387}
5388
Johan Hedberg3f706b72013-01-20 14:27:16 +02005389static bool ltk_is_valid(struct mgmt_ltk_info *key)
5390{
5391 if (key->master != 0x00 && key->master != 0x01)
5392 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005393
5394 switch (key->addr.type) {
5395 case BDADDR_LE_PUBLIC:
5396 return true;
5397
5398 case BDADDR_LE_RANDOM:
5399 /* Two most significant bits shall be set */
5400 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5401 return false;
5402 return true;
5403 }
5404
5405 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005406}
5407
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005408static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005409 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005410{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005411 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005412 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5413 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005414 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005415 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005416
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005417 BT_DBG("request for %s", hdev->name);
5418
5419 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005420 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5421 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005422
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005423 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005424 if (key_count > max_key_count) {
5425 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005426 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5427 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005428 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005429
5430 expected_len = sizeof(*cp) + key_count *
5431 sizeof(struct mgmt_ltk_info);
5432 if (expected_len != len) {
5433 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005434 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005435 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5436 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005437 }
5438
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005439 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005440
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005441 for (i = 0; i < key_count; i++) {
5442 struct mgmt_ltk_info *key = &cp->keys[i];
5443
Johan Hedberg3f706b72013-01-20 14:27:16 +02005444 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005445 return mgmt_cmd_status(sk, hdev->id,
5446 MGMT_OP_LOAD_LONG_TERM_KEYS,
5447 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005448 }
5449
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005450 hci_dev_lock(hdev);
5451
5452 hci_smp_ltks_clear(hdev);
5453
5454 for (i = 0; i < key_count; i++) {
5455 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005456 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005457
5458 if (key->addr.type == BDADDR_LE_PUBLIC)
5459 addr_type = ADDR_LE_DEV_PUBLIC;
5460 else
5461 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005462
Johan Hedberg61b43352014-05-29 19:36:53 +03005463 switch (key->type) {
5464 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005465 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005466 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005467 break;
5468 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005469 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005470 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005471 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005472 case MGMT_LTK_P256_UNAUTH:
5473 authenticated = 0x00;
5474 type = SMP_LTK_P256;
5475 break;
5476 case MGMT_LTK_P256_AUTH:
5477 authenticated = 0x01;
5478 type = SMP_LTK_P256;
5479 break;
5480 case MGMT_LTK_P256_DEBUG:
5481 authenticated = 0x00;
5482 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005483 default:
5484 continue;
5485 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005486
Johan Hedberg35d70272014-02-19 14:57:47 +02005487 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005488 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005489 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005490 }
5491
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005492 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005493 NULL, 0);
5494
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005495 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005496
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005497 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005498}
5499
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005500static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005501{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005502 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005503 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005504 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005505
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005506 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005507
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005508 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005509 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005510 rp.tx_power = conn->tx_power;
5511 rp.max_tx_power = conn->max_tx_power;
5512 } else {
5513 rp.rssi = HCI_RSSI_INVALID;
5514 rp.tx_power = HCI_TX_POWER_INVALID;
5515 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005516 }
5517
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005518 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5519 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005520
5521 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005522 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005523
5524 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005525}
5526
Marcel Holtmann1904a852015-01-11 13:50:44 -08005527static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5528 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005529{
5530 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005531 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005532 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005533 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005534 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005535
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005536 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005537
5538 hci_dev_lock(hdev);
5539
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005540 /* Commands sent in request are either Read RSSI or Read Transmit Power
5541 * Level so we check which one was last sent to retrieve connection
5542 * handle. Both commands have handle as first parameter so it's safe to
5543 * cast data on the same command struct.
5544 *
5545 * First command sent is always Read RSSI and we fail only if it fails.
5546 * In other case we simply override error to indicate success as we
5547 * already remembered if TX power value is actually valid.
5548 */
5549 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5550 if (!cp) {
5551 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005552 status = MGMT_STATUS_SUCCESS;
5553 } else {
5554 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005555 }
5556
5557 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005558 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005559 goto unlock;
5560 }
5561
5562 handle = __le16_to_cpu(cp->handle);
5563 conn = hci_conn_hash_lookup_handle(hdev, handle);
5564 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005565 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005566 goto unlock;
5567 }
5568
Johan Hedberg333ae952015-03-17 13:48:47 +02005569 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005570 if (!cmd)
5571 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005572
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005573 cmd->cmd_complete(cmd, status);
5574 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005575
5576unlock:
5577 hci_dev_unlock(hdev);
5578}
5579
5580static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5581 u16 len)
5582{
5583 struct mgmt_cp_get_conn_info *cp = data;
5584 struct mgmt_rp_get_conn_info rp;
5585 struct hci_conn *conn;
5586 unsigned long conn_info_age;
5587 int err = 0;
5588
5589 BT_DBG("%s", hdev->name);
5590
5591 memset(&rp, 0, sizeof(rp));
5592 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5593 rp.addr.type = cp->addr.type;
5594
5595 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005596 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5597 MGMT_STATUS_INVALID_PARAMS,
5598 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005599
5600 hci_dev_lock(hdev);
5601
5602 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005603 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5604 MGMT_STATUS_NOT_POWERED, &rp,
5605 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005606 goto unlock;
5607 }
5608
5609 if (cp->addr.type == BDADDR_BREDR)
5610 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5611 &cp->addr.bdaddr);
5612 else
5613 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5614
5615 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005616 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5617 MGMT_STATUS_NOT_CONNECTED, &rp,
5618 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005619 goto unlock;
5620 }
5621
Johan Hedberg333ae952015-03-17 13:48:47 +02005622 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005623 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5624 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005625 goto unlock;
5626 }
5627
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005628 /* To avoid client trying to guess when to poll again for information we
5629 * calculate conn info age as random value between min/max set in hdev.
5630 */
5631 conn_info_age = hdev->conn_info_min_age +
5632 prandom_u32_max(hdev->conn_info_max_age -
5633 hdev->conn_info_min_age);
5634
5635 /* Query controller to refresh cached values if they are too old or were
5636 * never read.
5637 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005638 if (time_after(jiffies, conn->conn_info_timestamp +
5639 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005640 !conn->conn_info_timestamp) {
5641 struct hci_request req;
5642 struct hci_cp_read_tx_power req_txp_cp;
5643 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005644 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005645
5646 hci_req_init(&req, hdev);
5647 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5648 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5649 &req_rssi_cp);
5650
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005651 /* For LE links TX power does not change thus we don't need to
5652 * query for it once value is known.
5653 */
5654 if (!bdaddr_type_is_le(cp->addr.type) ||
5655 conn->tx_power == HCI_TX_POWER_INVALID) {
5656 req_txp_cp.handle = cpu_to_le16(conn->handle);
5657 req_txp_cp.type = 0x00;
5658 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5659 sizeof(req_txp_cp), &req_txp_cp);
5660 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005661
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005662 /* Max TX power needs to be read only once per connection */
5663 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5664 req_txp_cp.handle = cpu_to_le16(conn->handle);
5665 req_txp_cp.type = 0x01;
5666 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5667 sizeof(req_txp_cp), &req_txp_cp);
5668 }
5669
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005670 err = hci_req_run(&req, conn_info_refresh_complete);
5671 if (err < 0)
5672 goto unlock;
5673
5674 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5675 data, len);
5676 if (!cmd) {
5677 err = -ENOMEM;
5678 goto unlock;
5679 }
5680
5681 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005682 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005683 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005684
5685 conn->conn_info_timestamp = jiffies;
5686 } else {
5687 /* Cache is valid, just reply with values cached in hci_conn */
5688 rp.rssi = conn->rssi;
5689 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005690 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005691
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005692 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5693 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005694 }
5695
5696unlock:
5697 hci_dev_unlock(hdev);
5698 return err;
5699}
5700
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005701static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005702{
5703 struct hci_conn *conn = cmd->user_data;
5704 struct mgmt_rp_get_clock_info rp;
5705 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005706 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005707
5708 memset(&rp, 0, sizeof(rp));
5709 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5710
5711 if (status)
5712 goto complete;
5713
5714 hdev = hci_dev_get(cmd->index);
5715 if (hdev) {
5716 rp.local_clock = cpu_to_le32(hdev->clock);
5717 hci_dev_put(hdev);
5718 }
5719
5720 if (conn) {
5721 rp.piconet_clock = cpu_to_le32(conn->clock);
5722 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5723 }
5724
5725complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005726 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5727 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005728
5729 if (conn) {
5730 hci_conn_drop(conn);
5731 hci_conn_put(conn);
5732 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005733
5734 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005735}
5736
Marcel Holtmann1904a852015-01-11 13:50:44 -08005737static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005738{
Johan Hedberg95868422014-06-28 17:54:07 +03005739 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005740 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005741 struct hci_conn *conn;
5742
5743 BT_DBG("%s status %u", hdev->name, status);
5744
5745 hci_dev_lock(hdev);
5746
5747 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5748 if (!hci_cp)
5749 goto unlock;
5750
5751 if (hci_cp->which) {
5752 u16 handle = __le16_to_cpu(hci_cp->handle);
5753 conn = hci_conn_hash_lookup_handle(hdev, handle);
5754 } else {
5755 conn = NULL;
5756 }
5757
Johan Hedberg333ae952015-03-17 13:48:47 +02005758 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005759 if (!cmd)
5760 goto unlock;
5761
Johan Hedberg69487372014-12-05 13:36:07 +02005762 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005763 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005764
5765unlock:
5766 hci_dev_unlock(hdev);
5767}
5768
5769static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5770 u16 len)
5771{
5772 struct mgmt_cp_get_clock_info *cp = data;
5773 struct mgmt_rp_get_clock_info rp;
5774 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005775 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005776 struct hci_request req;
5777 struct hci_conn *conn;
5778 int err;
5779
5780 BT_DBG("%s", hdev->name);
5781
5782 memset(&rp, 0, sizeof(rp));
5783 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5784 rp.addr.type = cp->addr.type;
5785
5786 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005787 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5788 MGMT_STATUS_INVALID_PARAMS,
5789 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005790
5791 hci_dev_lock(hdev);
5792
5793 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005794 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5795 MGMT_STATUS_NOT_POWERED, &rp,
5796 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005797 goto unlock;
5798 }
5799
5800 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5801 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5802 &cp->addr.bdaddr);
5803 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005804 err = mgmt_cmd_complete(sk, hdev->id,
5805 MGMT_OP_GET_CLOCK_INFO,
5806 MGMT_STATUS_NOT_CONNECTED,
5807 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005808 goto unlock;
5809 }
5810 } else {
5811 conn = NULL;
5812 }
5813
5814 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5815 if (!cmd) {
5816 err = -ENOMEM;
5817 goto unlock;
5818 }
5819
Johan Hedberg69487372014-12-05 13:36:07 +02005820 cmd->cmd_complete = clock_info_cmd_complete;
5821
Johan Hedberg95868422014-06-28 17:54:07 +03005822 hci_req_init(&req, hdev);
5823
5824 memset(&hci_cp, 0, sizeof(hci_cp));
5825 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5826
5827 if (conn) {
5828 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005829 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005830
5831 hci_cp.handle = cpu_to_le16(conn->handle);
5832 hci_cp.which = 0x01; /* Piconet clock */
5833 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5834 }
5835
5836 err = hci_req_run(&req, get_clock_info_complete);
5837 if (err < 0)
5838 mgmt_pending_remove(cmd);
5839
5840unlock:
5841 hci_dev_unlock(hdev);
5842 return err;
5843}
5844
Johan Hedberg5a154e62014-12-19 22:26:02 +02005845static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5846{
5847 struct hci_conn *conn;
5848
5849 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5850 if (!conn)
5851 return false;
5852
5853 if (conn->dst_type != type)
5854 return false;
5855
5856 if (conn->state != BT_CONNECTED)
5857 return false;
5858
5859 return true;
5860}
5861
5862/* This function requires the caller holds hdev->lock */
5863static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5864 u8 addr_type, u8 auto_connect)
5865{
5866 struct hci_dev *hdev = req->hdev;
5867 struct hci_conn_params *params;
5868
5869 params = hci_conn_params_add(hdev, addr, addr_type);
5870 if (!params)
5871 return -EIO;
5872
5873 if (params->auto_connect == auto_connect)
5874 return 0;
5875
5876 list_del_init(&params->action);
5877
5878 switch (auto_connect) {
5879 case HCI_AUTO_CONN_DISABLED:
5880 case HCI_AUTO_CONN_LINK_LOSS:
5881 __hci_update_background_scan(req);
5882 break;
5883 case HCI_AUTO_CONN_REPORT:
5884 list_add(&params->action, &hdev->pend_le_reports);
5885 __hci_update_background_scan(req);
5886 break;
5887 case HCI_AUTO_CONN_DIRECT:
5888 case HCI_AUTO_CONN_ALWAYS:
5889 if (!is_connected(hdev, addr, addr_type)) {
5890 list_add(&params->action, &hdev->pend_le_conns);
5891 __hci_update_background_scan(req);
5892 }
5893 break;
5894 }
5895
5896 params->auto_connect = auto_connect;
5897
5898 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5899 auto_connect);
5900
5901 return 0;
5902}
5903
Marcel Holtmann8afef092014-06-29 22:28:34 +02005904static void device_added(struct sock *sk, struct hci_dev *hdev,
5905 bdaddr_t *bdaddr, u8 type, u8 action)
5906{
5907 struct mgmt_ev_device_added ev;
5908
5909 bacpy(&ev.addr.bdaddr, bdaddr);
5910 ev.addr.type = type;
5911 ev.action = action;
5912
5913 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5914}
5915
Marcel Holtmann1904a852015-01-11 13:50:44 -08005916static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005917{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005918 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005919
5920 BT_DBG("status 0x%02x", status);
5921
5922 hci_dev_lock(hdev);
5923
Johan Hedberg333ae952015-03-17 13:48:47 +02005924 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005925 if (!cmd)
5926 goto unlock;
5927
5928 cmd->cmd_complete(cmd, mgmt_status(status));
5929 mgmt_pending_remove(cmd);
5930
5931unlock:
5932 hci_dev_unlock(hdev);
5933}
5934
Marcel Holtmann2faade52014-06-29 19:44:03 +02005935static int add_device(struct sock *sk, struct hci_dev *hdev,
5936 void *data, u16 len)
5937{
5938 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005939 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005940 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005941 u8 auto_conn, addr_type;
5942 int err;
5943
5944 BT_DBG("%s", hdev->name);
5945
Johan Hedberg66593582014-07-09 12:59:14 +03005946 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005947 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005948 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5949 MGMT_STATUS_INVALID_PARAMS,
5950 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005951
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005952 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005953 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5954 MGMT_STATUS_INVALID_PARAMS,
5955 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005956
Johan Hedberg5a154e62014-12-19 22:26:02 +02005957 hci_req_init(&req, hdev);
5958
Marcel Holtmann2faade52014-06-29 19:44:03 +02005959 hci_dev_lock(hdev);
5960
Johan Hedberg5a154e62014-12-19 22:26:02 +02005961 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5962 if (!cmd) {
5963 err = -ENOMEM;
5964 goto unlock;
5965 }
5966
5967 cmd->cmd_complete = addr_cmd_complete;
5968
Johan Hedberg66593582014-07-09 12:59:14 +03005969 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005970 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005971 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005972 err = cmd->cmd_complete(cmd,
5973 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005974 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005975 goto unlock;
5976 }
5977
5978 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5979 cp->addr.type);
5980 if (err)
5981 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005982
Johan Hedberg5a154e62014-12-19 22:26:02 +02005983 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005984
Johan Hedberg66593582014-07-09 12:59:14 +03005985 goto added;
5986 }
5987
Marcel Holtmann2faade52014-06-29 19:44:03 +02005988 if (cp->addr.type == BDADDR_LE_PUBLIC)
5989 addr_type = ADDR_LE_DEV_PUBLIC;
5990 else
5991 addr_type = ADDR_LE_DEV_RANDOM;
5992
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005993 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005994 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005995 else if (cp->action == 0x01)
5996 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005997 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005998 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005999
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006000 /* If the connection parameters don't exist for this device,
6001 * they will be created and configured with defaults.
6002 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006003 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006004 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006005 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006006 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006007 goto unlock;
6008 }
6009
Johan Hedberg66593582014-07-09 12:59:14 +03006010added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006011 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6012
Johan Hedberg5a154e62014-12-19 22:26:02 +02006013 err = hci_req_run(&req, add_device_complete);
6014 if (err < 0) {
6015 /* ENODATA means no HCI commands were needed (e.g. if
6016 * the adapter is powered off).
6017 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006018 if (err == -ENODATA)
6019 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006020 mgmt_pending_remove(cmd);
6021 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006022
6023unlock:
6024 hci_dev_unlock(hdev);
6025 return err;
6026}
6027
Marcel Holtmann8afef092014-06-29 22:28:34 +02006028static void device_removed(struct sock *sk, struct hci_dev *hdev,
6029 bdaddr_t *bdaddr, u8 type)
6030{
6031 struct mgmt_ev_device_removed ev;
6032
6033 bacpy(&ev.addr.bdaddr, bdaddr);
6034 ev.addr.type = type;
6035
6036 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6037}
6038
Marcel Holtmann1904a852015-01-11 13:50:44 -08006039static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006040{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006041 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006042
6043 BT_DBG("status 0x%02x", status);
6044
6045 hci_dev_lock(hdev);
6046
Johan Hedberg333ae952015-03-17 13:48:47 +02006047 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006048 if (!cmd)
6049 goto unlock;
6050
6051 cmd->cmd_complete(cmd, mgmt_status(status));
6052 mgmt_pending_remove(cmd);
6053
6054unlock:
6055 hci_dev_unlock(hdev);
6056}
6057
Marcel Holtmann2faade52014-06-29 19:44:03 +02006058static int remove_device(struct sock *sk, struct hci_dev *hdev,
6059 void *data, u16 len)
6060{
6061 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006062 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006063 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006064 int err;
6065
6066 BT_DBG("%s", hdev->name);
6067
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006068 hci_req_init(&req, hdev);
6069
Marcel Holtmann2faade52014-06-29 19:44:03 +02006070 hci_dev_lock(hdev);
6071
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006072 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6073 if (!cmd) {
6074 err = -ENOMEM;
6075 goto unlock;
6076 }
6077
6078 cmd->cmd_complete = addr_cmd_complete;
6079
Marcel Holtmann2faade52014-06-29 19:44:03 +02006080 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006081 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006082 u8 addr_type;
6083
Johan Hedberg66593582014-07-09 12:59:14 +03006084 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006085 err = cmd->cmd_complete(cmd,
6086 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006087 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006088 goto unlock;
6089 }
6090
Johan Hedberg66593582014-07-09 12:59:14 +03006091 if (cp->addr.type == BDADDR_BREDR) {
6092 err = hci_bdaddr_list_del(&hdev->whitelist,
6093 &cp->addr.bdaddr,
6094 cp->addr.type);
6095 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006096 err = cmd->cmd_complete(cmd,
6097 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006098 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006099 goto unlock;
6100 }
6101
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006102 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006103
Johan Hedberg66593582014-07-09 12:59:14 +03006104 device_removed(sk, hdev, &cp->addr.bdaddr,
6105 cp->addr.type);
6106 goto complete;
6107 }
6108
Marcel Holtmann2faade52014-06-29 19:44:03 +02006109 if (cp->addr.type == BDADDR_LE_PUBLIC)
6110 addr_type = ADDR_LE_DEV_PUBLIC;
6111 else
6112 addr_type = ADDR_LE_DEV_RANDOM;
6113
Johan Hedbergc71593d2014-07-02 17:37:28 +03006114 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6115 addr_type);
6116 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006117 err = cmd->cmd_complete(cmd,
6118 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006119 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006120 goto unlock;
6121 }
6122
6123 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006124 err = cmd->cmd_complete(cmd,
6125 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006126 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006127 goto unlock;
6128 }
6129
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006130 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006131 list_del(&params->list);
6132 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006133 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006134
6135 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006136 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006137 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006138 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006139
Marcel Holtmann2faade52014-06-29 19:44:03 +02006140 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006141 err = cmd->cmd_complete(cmd,
6142 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006143 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006144 goto unlock;
6145 }
6146
Johan Hedberg66593582014-07-09 12:59:14 +03006147 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6148 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6149 list_del(&b->list);
6150 kfree(b);
6151 }
6152
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006153 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006154
Johan Hedberg19de0822014-07-06 13:06:51 +03006155 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6156 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6157 continue;
6158 device_removed(sk, hdev, &p->addr, p->addr_type);
6159 list_del(&p->action);
6160 list_del(&p->list);
6161 kfree(p);
6162 }
6163
6164 BT_DBG("All LE connection parameters were removed");
6165
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006166 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006167 }
6168
Johan Hedberg66593582014-07-09 12:59:14 +03006169complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006170 err = hci_req_run(&req, remove_device_complete);
6171 if (err < 0) {
6172 /* ENODATA means no HCI commands were needed (e.g. if
6173 * the adapter is powered off).
6174 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006175 if (err == -ENODATA)
6176 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006177 mgmt_pending_remove(cmd);
6178 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006179
6180unlock:
6181 hci_dev_unlock(hdev);
6182 return err;
6183}
6184
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006185static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6186 u16 len)
6187{
6188 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006189 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6190 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006191 u16 param_count, expected_len;
6192 int i;
6193
6194 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006195 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6196 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006197
6198 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006199 if (param_count > max_param_count) {
6200 BT_ERR("load_conn_param: too big param_count value %u",
6201 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006202 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6203 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006204 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006205
6206 expected_len = sizeof(*cp) + param_count *
6207 sizeof(struct mgmt_conn_param);
6208 if (expected_len != len) {
6209 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6210 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006211 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6212 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006213 }
6214
6215 BT_DBG("%s param_count %u", hdev->name, param_count);
6216
6217 hci_dev_lock(hdev);
6218
6219 hci_conn_params_clear_disabled(hdev);
6220
6221 for (i = 0; i < param_count; i++) {
6222 struct mgmt_conn_param *param = &cp->params[i];
6223 struct hci_conn_params *hci_param;
6224 u16 min, max, latency, timeout;
6225 u8 addr_type;
6226
6227 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6228 param->addr.type);
6229
6230 if (param->addr.type == BDADDR_LE_PUBLIC) {
6231 addr_type = ADDR_LE_DEV_PUBLIC;
6232 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6233 addr_type = ADDR_LE_DEV_RANDOM;
6234 } else {
6235 BT_ERR("Ignoring invalid connection parameters");
6236 continue;
6237 }
6238
6239 min = le16_to_cpu(param->min_interval);
6240 max = le16_to_cpu(param->max_interval);
6241 latency = le16_to_cpu(param->latency);
6242 timeout = le16_to_cpu(param->timeout);
6243
6244 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6245 min, max, latency, timeout);
6246
6247 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6248 BT_ERR("Ignoring invalid connection parameters");
6249 continue;
6250 }
6251
6252 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6253 addr_type);
6254 if (!hci_param) {
6255 BT_ERR("Failed to add connection parameters");
6256 continue;
6257 }
6258
6259 hci_param->conn_min_interval = min;
6260 hci_param->conn_max_interval = max;
6261 hci_param->conn_latency = latency;
6262 hci_param->supervision_timeout = timeout;
6263 }
6264
6265 hci_dev_unlock(hdev);
6266
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006267 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6268 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006269}
6270
Marcel Holtmanndbece372014-07-04 18:11:55 +02006271static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6272 void *data, u16 len)
6273{
6274 struct mgmt_cp_set_external_config *cp = data;
6275 bool changed;
6276 int err;
6277
6278 BT_DBG("%s", hdev->name);
6279
6280 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006281 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6282 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006283
6284 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006285 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6286 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006287
6288 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006289 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6290 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006291
6292 hci_dev_lock(hdev);
6293
6294 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006295 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006296 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006297 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006298
6299 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6300 if (err < 0)
6301 goto unlock;
6302
6303 if (!changed)
6304 goto unlock;
6305
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006306 err = new_options(hdev, sk);
6307
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006308 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006309 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006310
Marcel Holtmann516018a2015-03-13 02:11:04 -07006311 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006312 hci_dev_set_flag(hdev, HCI_CONFIG);
6313 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006314
6315 queue_work(hdev->req_workqueue, &hdev->power_on);
6316 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006317 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006318 mgmt_index_added(hdev);
6319 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006320 }
6321
6322unlock:
6323 hci_dev_unlock(hdev);
6324 return err;
6325}
6326
Marcel Holtmann9713c172014-07-06 12:11:15 +02006327static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6328 void *data, u16 len)
6329{
6330 struct mgmt_cp_set_public_address *cp = data;
6331 bool changed;
6332 int err;
6333
6334 BT_DBG("%s", hdev->name);
6335
6336 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006337 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6338 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006339
6340 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006341 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6342 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006343
6344 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006345 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6346 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006347
6348 hci_dev_lock(hdev);
6349
6350 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6351 bacpy(&hdev->public_addr, &cp->bdaddr);
6352
6353 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6354 if (err < 0)
6355 goto unlock;
6356
6357 if (!changed)
6358 goto unlock;
6359
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006360 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006361 err = new_options(hdev, sk);
6362
6363 if (is_configured(hdev)) {
6364 mgmt_index_removed(hdev);
6365
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006366 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006367
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006368 hci_dev_set_flag(hdev, HCI_CONFIG);
6369 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006370
6371 queue_work(hdev->req_workqueue, &hdev->power_on);
6372 }
6373
6374unlock:
6375 hci_dev_unlock(hdev);
6376 return err;
6377}
6378
Marcel Holtmannbea41602015-03-14 22:43:17 -07006379static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6380 u8 data_len)
6381{
6382 eir[eir_len++] = sizeof(type) + data_len;
6383 eir[eir_len++] = type;
6384 memcpy(&eir[eir_len], data, data_len);
6385 eir_len += data_len;
6386
6387 return eir_len;
6388}
6389
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006390static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6391 void *data, u16 data_len)
6392{
6393 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6394 struct mgmt_rp_read_local_oob_ext_data *rp;
6395 size_t rp_len;
6396 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006397 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006398 int err;
6399
6400 BT_DBG("%s", hdev->name);
6401
6402 if (!hdev_is_powered(hdev))
6403 return mgmt_cmd_complete(sk, hdev->id,
6404 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6405 MGMT_STATUS_NOT_POWERED,
6406 &cp->type, sizeof(cp->type));
6407
6408 switch (cp->type) {
6409 case BIT(BDADDR_BREDR):
6410 status = mgmt_bredr_support(hdev);
6411 if (status)
6412 return mgmt_cmd_complete(sk, hdev->id,
6413 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6414 status, &cp->type,
6415 sizeof(cp->type));
6416 eir_len = 5;
6417 break;
6418 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6419 status = mgmt_le_support(hdev);
6420 if (status)
6421 return mgmt_cmd_complete(sk, hdev->id,
6422 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6423 status, &cp->type,
6424 sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006425 eir_len = 9 + 3 + 18 + 18 + 3;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006426 break;
6427 default:
6428 return mgmt_cmd_complete(sk, hdev->id,
6429 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6430 MGMT_STATUS_INVALID_PARAMS,
6431 &cp->type, sizeof(cp->type));
6432 }
6433
6434 hci_dev_lock(hdev);
6435
6436 rp_len = sizeof(*rp) + eir_len;
6437 rp = kmalloc(rp_len, GFP_ATOMIC);
6438 if (!rp) {
6439 hci_dev_unlock(hdev);
6440 return -ENOMEM;
6441 }
6442
6443 eir_len = 0;
6444 switch (cp->type) {
6445 case BIT(BDADDR_BREDR):
6446 eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
6447 hdev->dev_class, 3);
6448 break;
6449 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006450 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6451 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006452 hci_dev_unlock(hdev);
6453 err = mgmt_cmd_complete(sk, hdev->id,
Marcel Holtmann5082a592015-03-16 12:39:00 -07006454 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6455 MGMT_STATUS_FAILED,
6456 &cp->type, sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006457 goto done;
6458 }
6459
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006460 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
6461 memcpy(addr, &hdev->rpa, 6);
6462 addr[6] = 0x01;
6463 } else if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6464 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6465 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6466 bacmp(&hdev->static_addr, BDADDR_ANY))) {
6467 memcpy(addr, &hdev->static_addr, 6);
6468 addr[6] = 0x01;
6469 } else {
6470 memcpy(addr, &hdev->bdaddr, 6);
6471 addr[6] = 0x00;
6472 }
6473
6474 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6475 addr, sizeof(addr));
6476
6477 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6478 role = 0x02;
6479 else
6480 role = 0x01;
6481
6482 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6483 &role, sizeof(role));
6484
Marcel Holtmann5082a592015-03-16 12:39:00 -07006485 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6486 eir_len = eir_append_data(rp->eir, eir_len,
6487 EIR_LE_SC_CONFIRM,
6488 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006489
Marcel Holtmann5082a592015-03-16 12:39:00 -07006490 eir_len = eir_append_data(rp->eir, eir_len,
6491 EIR_LE_SC_RANDOM,
6492 rand, sizeof(rand));
6493 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006494
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006495 flags = get_adv_discov_flags(hdev);
6496
6497 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6498 flags |= LE_AD_NO_BREDR;
6499
6500 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6501 &flags, sizeof(flags));
6502 break;
6503 }
6504
6505 rp->type = cp->type;
6506 rp->eir_len = cpu_to_le16(eir_len);
6507
6508 hci_dev_unlock(hdev);
6509
Marcel Holtmann72000df2015-03-16 16:11:21 -07006510 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6511
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006512 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann5425f982015-03-16 16:05:44 -07006513 MGMT_STATUS_SUCCESS, rp, sizeof(*rp) + eir_len);
Marcel Holtmann72000df2015-03-16 16:11:21 -07006514 if (err < 0)
6515 goto done;
6516
6517 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6518 rp, sizeof(*rp) + eir_len,
6519 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006520
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006521done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006522 kfree(rp);
6523
6524 return err;
6525}
6526
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006527static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6528 void *data, u16 data_len)
6529{
6530 struct mgmt_rp_read_adv_features *rp;
6531 size_t rp_len;
6532 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006533 bool instance;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006534
6535 BT_DBG("%s", hdev->name);
6536
6537 hci_dev_lock(hdev);
6538
6539 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006540
6541 /* Currently only one instance is supported, so just add 1 to the
6542 * response length.
6543 */
6544 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6545 if (instance)
6546 rp_len++;
6547
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006548 rp = kmalloc(rp_len, GFP_ATOMIC);
6549 if (!rp) {
6550 hci_dev_unlock(hdev);
6551 return -ENOMEM;
6552 }
6553
6554 rp->supported_flags = cpu_to_le32(0);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006555 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6556 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006557 rp->max_instances = 1;
6558
6559 /* Currently only one instance is supported, so simply return the
6560 * current instance number.
6561 */
6562 if (instance) {
6563 rp->num_instances = 1;
6564 rp->instance[0] = 1;
6565 } else {
6566 rp->num_instances = 0;
6567 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006568
6569 hci_dev_unlock(hdev);
6570
6571 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6572 MGMT_STATUS_SUCCESS, rp, rp_len);
6573
6574 kfree(rp);
6575
6576 return err;
6577}
6578
Arman Uguray4117ed72015-03-23 15:57:14 -07006579static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006580 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006581{
Arman Uguray4117ed72015-03-23 15:57:14 -07006582 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006583 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006584 bool flags_managed = false;
Arman Uguray807ec772015-03-25 18:53:42 -07006585 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV;
Arman Uguray24b4f382015-03-23 15:57:12 -07006586
Arman Uguray807ec772015-03-25 18:53:42 -07006587 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006588 flags_managed = true;
6589 max_len -= 3;
6590 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006591
Arman Uguray4117ed72015-03-23 15:57:14 -07006592 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006593 return false;
6594
Arman Uguray4117ed72015-03-23 15:57:14 -07006595 /* Make sure that the data is correctly formatted. */
6596 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6597 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006598
Arman Ugurayb44133f2015-03-25 18:53:41 -07006599 if (flags_managed && data[i + 1] == EIR_FLAGS)
6600 return false;
6601
Arman Uguray24b4f382015-03-23 15:57:12 -07006602 /* If the current field length would exceed the total data
6603 * length, then it's invalid.
6604 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006605 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006606 return false;
6607 }
6608
6609 return true;
6610}
6611
Arman Uguray24b4f382015-03-23 15:57:12 -07006612static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6613 u16 opcode)
6614{
6615 struct mgmt_pending_cmd *cmd;
6616 struct mgmt_rp_add_advertising rp;
6617
6618 BT_DBG("status %d", status);
6619
6620 hci_dev_lock(hdev);
6621
6622 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6623
6624 if (status) {
6625 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6626 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6627 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6628 }
6629
6630 if (!cmd)
6631 goto unlock;
6632
6633 rp.instance = 0x01;
6634
6635 if (status)
6636 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6637 mgmt_status(status));
6638 else
6639 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6640 mgmt_status(status), &rp, sizeof(rp));
6641
6642 mgmt_pending_remove(cmd);
6643
6644unlock:
6645 hci_dev_unlock(hdev);
6646}
6647
Arman Uguray912098a2015-03-23 15:57:15 -07006648static void adv_timeout_expired(struct work_struct *work)
6649{
6650 struct hci_dev *hdev = container_of(work, struct hci_dev,
6651 adv_instance.timeout_exp.work);
6652
6653 hdev->adv_instance.timeout = 0;
6654
6655 hci_dev_lock(hdev);
6656 clear_adv_instance(hdev);
6657 hci_dev_unlock(hdev);
6658}
6659
Arman Uguray24b4f382015-03-23 15:57:12 -07006660static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6661 void *data, u16 data_len)
6662{
6663 struct mgmt_cp_add_advertising *cp = data;
6664 struct mgmt_rp_add_advertising rp;
6665 u32 flags;
6666 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006667 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006668 int err;
6669 struct mgmt_pending_cmd *cmd;
6670 struct hci_request req;
6671
6672 BT_DBG("%s", hdev->name);
6673
6674 status = mgmt_le_support(hdev);
6675 if (status)
6676 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6677 status);
6678
6679 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006680 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006681
Arman Uguraye7a685d2015-03-25 18:53:40 -07006682 /* The current implementation only supports adding one instance */
6683 if (cp->instance != 0x01)
Arman Uguray24b4f382015-03-23 15:57:12 -07006684 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6685 MGMT_STATUS_INVALID_PARAMS);
6686
6687 hci_dev_lock(hdev);
6688
Arman Uguray912098a2015-03-23 15:57:15 -07006689 if (timeout && !hdev_is_powered(hdev)) {
6690 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6691 MGMT_STATUS_REJECTED);
6692 goto unlock;
6693 }
6694
Arman Uguray24b4f382015-03-23 15:57:12 -07006695 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006696 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006697 pending_find(MGMT_OP_SET_LE, hdev)) {
6698 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6699 MGMT_STATUS_BUSY);
6700 goto unlock;
6701 }
6702
Arman Ugurayb44133f2015-03-25 18:53:41 -07006703 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006704 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006705 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006706 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6707 MGMT_STATUS_INVALID_PARAMS);
6708 goto unlock;
6709 }
6710
Arman Uguray912098a2015-03-23 15:57:15 -07006711 INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
6712
Arman Uguray24b4f382015-03-23 15:57:12 -07006713 hdev->adv_instance.flags = flags;
6714 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6715 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6716
6717 if (cp->adv_data_len)
6718 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6719
6720 if (cp->scan_rsp_len)
6721 memcpy(hdev->adv_instance.scan_rsp_data,
6722 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6723
Arman Uguray912098a2015-03-23 15:57:15 -07006724 if (hdev->adv_instance.timeout)
6725 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6726
6727 hdev->adv_instance.timeout = timeout;
6728
6729 if (timeout)
6730 queue_delayed_work(hdev->workqueue,
6731 &hdev->adv_instance.timeout_exp,
6732 msecs_to_jiffies(timeout * 1000));
6733
Arman Uguray24b4f382015-03-23 15:57:12 -07006734 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6735 advertising_added(sk, hdev, 1);
6736
6737 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6738 * we have no HCI communication to make. Simply return.
6739 */
6740 if (!hdev_is_powered(hdev) ||
6741 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6742 rp.instance = 0x01;
6743 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6744 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6745 goto unlock;
6746 }
6747
6748 /* We're good to go, update advertising data, parameters, and start
6749 * advertising.
6750 */
6751 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6752 data_len);
6753 if (!cmd) {
6754 err = -ENOMEM;
6755 goto unlock;
6756 }
6757
6758 hci_req_init(&req, hdev);
6759
6760 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07006761 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07006762 enable_advertising(&req);
6763
6764 err = hci_req_run(&req, add_advertising_complete);
6765 if (err < 0)
6766 mgmt_pending_remove(cmd);
6767
6768unlock:
6769 hci_dev_unlock(hdev);
6770
6771 return err;
6772}
6773
Arman Ugurayda9293352015-03-23 15:57:13 -07006774static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6775 u16 opcode)
6776{
6777 struct mgmt_pending_cmd *cmd;
6778 struct mgmt_rp_remove_advertising rp;
6779
6780 BT_DBG("status %d", status);
6781
6782 hci_dev_lock(hdev);
6783
6784 /* A failure status here only means that we failed to disable
6785 * advertising. Otherwise, the advertising instance has been removed,
6786 * so report success.
6787 */
6788 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6789 if (!cmd)
6790 goto unlock;
6791
6792 rp.instance = 1;
6793
6794 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6795 &rp, sizeof(rp));
6796 mgmt_pending_remove(cmd);
6797
6798unlock:
6799 hci_dev_unlock(hdev);
6800}
6801
6802static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6803 void *data, u16 data_len)
6804{
6805 struct mgmt_cp_remove_advertising *cp = data;
6806 struct mgmt_rp_remove_advertising rp;
6807 int err;
6808 struct mgmt_pending_cmd *cmd;
6809 struct hci_request req;
6810
6811 BT_DBG("%s", hdev->name);
6812
6813 /* The current implementation only allows modifying instance no 1. A
6814 * value of 0 indicates that all instances should be cleared.
6815 */
6816 if (cp->instance > 1)
6817 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6818 MGMT_STATUS_INVALID_PARAMS);
6819
6820 hci_dev_lock(hdev);
6821
6822 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
6823 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
6824 pending_find(MGMT_OP_SET_LE, hdev)) {
6825 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6826 MGMT_STATUS_BUSY);
6827 goto unlock;
6828 }
6829
6830 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
6831 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6832 MGMT_STATUS_INVALID_PARAMS);
6833 goto unlock;
6834 }
6835
Arman Uguray912098a2015-03-23 15:57:15 -07006836 if (hdev->adv_instance.timeout)
6837 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6838
Arman Ugurayda9293352015-03-23 15:57:13 -07006839 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6840
6841 advertising_removed(sk, hdev, 1);
6842
6843 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6844
6845 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6846 * we have no HCI communication to make. Simply return.
6847 */
6848 if (!hdev_is_powered(hdev) ||
6849 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6850 rp.instance = 1;
6851 err = mgmt_cmd_complete(sk, hdev->id,
6852 MGMT_OP_REMOVE_ADVERTISING,
6853 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6854 goto unlock;
6855 }
6856
6857 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
6858 data_len);
6859 if (!cmd) {
6860 err = -ENOMEM;
6861 goto unlock;
6862 }
6863
6864 hci_req_init(&req, hdev);
6865 disable_advertising(&req);
6866
6867 err = hci_req_run(&req, remove_advertising_complete);
6868 if (err < 0)
6869 mgmt_pending_remove(cmd);
6870
6871unlock:
6872 hci_dev_unlock(hdev);
6873
6874 return err;
6875}
6876
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006877static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006878 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006879 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006880 HCI_MGMT_NO_HDEV |
6881 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006882 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006883 HCI_MGMT_NO_HDEV |
6884 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006885 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006886 HCI_MGMT_NO_HDEV |
6887 HCI_MGMT_UNTRUSTED },
6888 { read_controller_info, MGMT_READ_INFO_SIZE,
6889 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006890 { set_powered, MGMT_SETTING_SIZE },
6891 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
6892 { set_connectable, MGMT_SETTING_SIZE },
6893 { set_fast_connectable, MGMT_SETTING_SIZE },
6894 { set_bondable, MGMT_SETTING_SIZE },
6895 { set_link_security, MGMT_SETTING_SIZE },
6896 { set_ssp, MGMT_SETTING_SIZE },
6897 { set_hs, MGMT_SETTING_SIZE },
6898 { set_le, MGMT_SETTING_SIZE },
6899 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
6900 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
6901 { add_uuid, MGMT_ADD_UUID_SIZE },
6902 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006903 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6904 HCI_MGMT_VAR_LEN },
6905 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6906 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006907 { disconnect, MGMT_DISCONNECT_SIZE },
6908 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
6909 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
6910 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6911 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
6912 { pair_device, MGMT_PAIR_DEVICE_SIZE },
6913 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6914 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
6915 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
6916 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6917 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
6918 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006919 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6920 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6921 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006922 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6923 { start_discovery, MGMT_START_DISCOVERY_SIZE },
6924 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
6925 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
6926 { block_device, MGMT_BLOCK_DEVICE_SIZE },
6927 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
6928 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
6929 { set_advertising, MGMT_SETTING_SIZE },
6930 { set_bredr, MGMT_SETTING_SIZE },
6931 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
6932 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
6933 { set_secure_conn, MGMT_SETTING_SIZE },
6934 { set_debug_keys, MGMT_SETTING_SIZE },
6935 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006936 { load_irks, MGMT_LOAD_IRKS_SIZE,
6937 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006938 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
6939 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
6940 { add_device, MGMT_ADD_DEVICE_SIZE },
6941 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006942 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6943 HCI_MGMT_VAR_LEN },
6944 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006945 HCI_MGMT_NO_HDEV |
6946 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006947 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006948 HCI_MGMT_UNCONFIGURED |
6949 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006950 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6951 HCI_MGMT_UNCONFIGURED },
6952 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6953 HCI_MGMT_UNCONFIGURED },
6954 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6955 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006956 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07006957 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006958 HCI_MGMT_NO_HDEV |
6959 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006960 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07006961 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
6962 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07006963 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006964};
6965
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006966void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006967{
Marcel Holtmannced85542015-03-14 19:27:56 -07006968 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006969
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006970 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6971 return;
6972
Marcel Holtmannf9207332015-03-14 19:27:55 -07006973 switch (hdev->dev_type) {
6974 case HCI_BREDR:
6975 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6976 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
6977 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006978 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006979 } else {
6980 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
6981 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006982 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006983 }
6984 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006985 case HCI_AMP:
6986 ev.type = 0x02;
6987 break;
6988 default:
6989 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006990 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006991
6992 ev.bus = hdev->bus;
6993
6994 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
6995 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006996}
6997
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006998void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006999{
Marcel Holtmannced85542015-03-14 19:27:56 -07007000 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007001 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007002
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007003 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7004 return;
7005
Marcel Holtmannf9207332015-03-14 19:27:55 -07007006 switch (hdev->dev_type) {
7007 case HCI_BREDR:
7008 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007009
Marcel Holtmannf9207332015-03-14 19:27:55 -07007010 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7011 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7012 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007013 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007014 } else {
7015 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7016 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007017 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007018 }
7019 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007020 case HCI_AMP:
7021 ev.type = 0x02;
7022 break;
7023 default:
7024 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007025 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007026
7027 ev.bus = hdev->bus;
7028
7029 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7030 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007031}
7032
Andre Guedes6046dc32014-02-26 20:21:51 -03007033/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007034static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007035{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007036 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007037 struct hci_conn_params *p;
7038
7039 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007040 /* Needed for AUTO_OFF case where might not "really"
7041 * have been powered off.
7042 */
7043 list_del_init(&p->action);
7044
7045 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007046 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007047 case HCI_AUTO_CONN_ALWAYS:
7048 list_add(&p->action, &hdev->pend_le_conns);
7049 break;
7050 case HCI_AUTO_CONN_REPORT:
7051 list_add(&p->action, &hdev->pend_le_reports);
7052 break;
7053 default:
7054 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007055 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007056 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007057
Johan Hedberg2cf22212014-12-19 22:26:00 +02007058 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007059}
7060
Marcel Holtmann1904a852015-01-11 13:50:44 -08007061static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007062{
7063 struct cmd_lookup match = { NULL, hdev };
7064
7065 BT_DBG("status 0x%02x", status);
7066
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007067 if (!status) {
7068 /* Register the available SMP channels (BR/EDR and LE) only
7069 * when successfully powering on the controller. This late
7070 * registration is required so that LE SMP can clearly
7071 * decide if the public address or static address is used.
7072 */
7073 smp_register(hdev);
7074 }
7075
Johan Hedberg229ab392013-03-15 17:06:53 -05007076 hci_dev_lock(hdev);
7077
7078 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7079
7080 new_settings(hdev, match.sk);
7081
7082 hci_dev_unlock(hdev);
7083
7084 if (match.sk)
7085 sock_put(match.sk);
7086}
7087
Johan Hedberg70da6242013-03-15 17:06:51 -05007088static int powered_update_hci(struct hci_dev *hdev)
7089{
Johan Hedberg890ea892013-03-15 17:06:52 -05007090 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007091 u8 link_sec;
7092
Johan Hedberg890ea892013-03-15 17:06:52 -05007093 hci_req_init(&req, hdev);
7094
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007095 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007096 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007097 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007098
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007099 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007100
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007101 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7102 u8 support = 0x01;
7103
7104 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7105 sizeof(support), &support);
7106 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007107 }
7108
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007109 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007110 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007111 struct hci_cp_write_le_host_supported cp;
7112
Marcel Holtmann32226e42014-07-24 20:04:16 +02007113 cp.le = 0x01;
7114 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007115
7116 /* Check first if we already have the right
7117 * host state (host features set)
7118 */
7119 if (cp.le != lmp_host_le_capable(hdev) ||
7120 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007121 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7122 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007123 }
7124
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007125 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007126 /* Make sure the controller has a good default for
7127 * advertising data. This also applies to the case
7128 * where BR/EDR was toggled during the AUTO_OFF phase.
7129 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007130 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007131 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007132 update_scan_rsp_data(&req);
7133 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007134
Arman Uguray24b4f382015-03-23 15:57:12 -07007135 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7136 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007137 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007138
7139 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007140 }
7141
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007142 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007143 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007144 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7145 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007146
7147 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007148 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007149 write_fast_connectable(&req, true);
7150 else
7151 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007152 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007153 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007154 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007155 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007156 }
7157
Johan Hedberg229ab392013-03-15 17:06:53 -05007158 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007159}
7160
Johan Hedberg744cf192011-11-08 20:40:14 +02007161int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007162{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007163 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007164 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007165 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007166
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007167 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007168 return 0;
7169
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007170 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007171 if (powered_update_hci(hdev) == 0)
7172 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007173
Johan Hedberg229ab392013-03-15 17:06:53 -05007174 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7175 &match);
7176 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007177 }
7178
Johan Hedberg229ab392013-03-15 17:06:53 -05007179 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007180
7181 /* If the power off is because of hdev unregistration let
7182 * use the appropriate INVALID_INDEX status. Otherwise use
7183 * NOT_POWERED. We cover both scenarios here since later in
7184 * mgmt_index_removed() any hci_conn callbacks will have already
7185 * been triggered, potentially causing misleading DISCONNECTED
7186 * status responses.
7187 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007188 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007189 status = MGMT_STATUS_INVALID_INDEX;
7190 else
7191 status = MGMT_STATUS_NOT_POWERED;
7192
7193 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007194
7195 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007196 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7197 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007198
7199new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007200 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007201
7202 if (match.sk)
7203 sock_put(match.sk);
7204
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007205 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007206}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007207
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007208void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007209{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007210 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007211 u8 status;
7212
Johan Hedberg333ae952015-03-17 13:48:47 +02007213 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007214 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007215 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007216
7217 if (err == -ERFKILL)
7218 status = MGMT_STATUS_RFKILLED;
7219 else
7220 status = MGMT_STATUS_FAILED;
7221
Johan Hedberga69e8372015-03-06 21:08:53 +02007222 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007223
7224 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007225}
7226
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007227void mgmt_discoverable_timeout(struct hci_dev *hdev)
7228{
7229 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007230
7231 hci_dev_lock(hdev);
7232
7233 /* When discoverable timeout triggers, then just make sure
7234 * the limited discoverable flag is cleared. Even in the case
7235 * of a timeout triggered from general discoverable, it is
7236 * safe to unconditionally clear the flag.
7237 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007238 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7239 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007240
7241 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007242 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007243 u8 scan = SCAN_PAGE;
7244 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7245 sizeof(scan), &scan);
7246 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007247 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007248
7249 /* Advertising instances don't use the global discoverable setting, so
7250 * only update AD if advertising was enabled using Set Advertising.
7251 */
7252 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7253 update_adv_data(&req);
7254
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007255 hci_req_run(&req, NULL);
7256
7257 hdev->discov_timeout = 0;
7258
Johan Hedberg9a43e252013-10-20 19:00:07 +03007259 new_settings(hdev, NULL);
7260
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007261 hci_dev_unlock(hdev);
7262}
7263
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007264void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7265 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007266{
Johan Hedberg86742e12011-11-07 23:13:38 +02007267 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007268
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007269 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007270
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007271 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007272 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007273 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007274 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007275 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007276 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007277
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007278 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007279}
Johan Hedbergf7520542011-01-20 12:34:39 +02007280
Johan Hedbergd7b25452014-05-23 13:19:53 +03007281static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7282{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007283 switch (ltk->type) {
7284 case SMP_LTK:
7285 case SMP_LTK_SLAVE:
7286 if (ltk->authenticated)
7287 return MGMT_LTK_AUTHENTICATED;
7288 return MGMT_LTK_UNAUTHENTICATED;
7289 case SMP_LTK_P256:
7290 if (ltk->authenticated)
7291 return MGMT_LTK_P256_AUTH;
7292 return MGMT_LTK_P256_UNAUTH;
7293 case SMP_LTK_P256_DEBUG:
7294 return MGMT_LTK_P256_DEBUG;
7295 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007296
7297 return MGMT_LTK_UNAUTHENTICATED;
7298}
7299
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007300void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007301{
7302 struct mgmt_ev_new_long_term_key ev;
7303
7304 memset(&ev, 0, sizeof(ev));
7305
Marcel Holtmann5192d302014-02-19 17:11:58 -08007306 /* Devices using resolvable or non-resolvable random addresses
7307 * without providing an indentity resolving key don't require
7308 * to store long term keys. Their addresses will change the
7309 * next time around.
7310 *
7311 * Only when a remote device provides an identity address
7312 * make sure the long term key is stored. If the remote
7313 * identity is known, the long term keys are internally
7314 * mapped to the identity address. So allow static random
7315 * and public addresses here.
7316 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007317 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7318 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7319 ev.store_hint = 0x00;
7320 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007321 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007322
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007323 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007324 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007325 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007326 ev.key.enc_size = key->enc_size;
7327 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007328 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007329
Johan Hedberg2ceba532014-06-16 19:25:16 +03007330 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007331 ev.key.master = 1;
7332
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007333 memcpy(ev.key.val, key->val, sizeof(key->val));
7334
Marcel Holtmann083368f2013-10-15 14:26:29 -07007335 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007336}
7337
Johan Hedberg95fbac82014-02-19 15:18:31 +02007338void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7339{
7340 struct mgmt_ev_new_irk ev;
7341
7342 memset(&ev, 0, sizeof(ev));
7343
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007344 /* For identity resolving keys from devices that are already
7345 * using a public address or static random address, do not
7346 * ask for storing this key. The identity resolving key really
7347 * is only mandatory for devices using resovlable random
7348 * addresses.
7349 *
7350 * Storing all identity resolving keys has the downside that
7351 * they will be also loaded on next boot of they system. More
7352 * identity resolving keys, means more time during scanning is
7353 * needed to actually resolve these addresses.
7354 */
7355 if (bacmp(&irk->rpa, BDADDR_ANY))
7356 ev.store_hint = 0x01;
7357 else
7358 ev.store_hint = 0x00;
7359
Johan Hedberg95fbac82014-02-19 15:18:31 +02007360 bacpy(&ev.rpa, &irk->rpa);
7361 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7362 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7363 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7364
7365 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7366}
7367
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007368void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7369 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007370{
7371 struct mgmt_ev_new_csrk ev;
7372
7373 memset(&ev, 0, sizeof(ev));
7374
7375 /* Devices using resolvable or non-resolvable random addresses
7376 * without providing an indentity resolving key don't require
7377 * to store signature resolving keys. Their addresses will change
7378 * the next time around.
7379 *
7380 * Only when a remote device provides an identity address
7381 * make sure the signature resolving key is stored. So allow
7382 * static random and public addresses here.
7383 */
7384 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7385 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7386 ev.store_hint = 0x00;
7387 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007388 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007389
7390 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7391 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007392 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007393 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7394
7395 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7396}
7397
Andre Guedesffb5a8272014-07-01 18:10:11 -03007398void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007399 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7400 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007401{
7402 struct mgmt_ev_new_conn_param ev;
7403
Johan Hedbergc103aea2014-07-02 17:37:34 +03007404 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7405 return;
7406
Andre Guedesffb5a8272014-07-01 18:10:11 -03007407 memset(&ev, 0, sizeof(ev));
7408 bacpy(&ev.addr.bdaddr, bdaddr);
7409 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007410 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007411 ev.min_interval = cpu_to_le16(min_interval);
7412 ev.max_interval = cpu_to_le16(max_interval);
7413 ev.latency = cpu_to_le16(latency);
7414 ev.timeout = cpu_to_le16(timeout);
7415
7416 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7417}
7418
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007419void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7420 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007421{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007422 char buf[512];
7423 struct mgmt_ev_device_connected *ev = (void *) buf;
7424 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007425
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007426 bacpy(&ev->addr.bdaddr, &conn->dst);
7427 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007428
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007429 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007430
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007431 /* We must ensure that the EIR Data fields are ordered and
7432 * unique. Keep it simple for now and avoid the problem by not
7433 * adding any BR/EDR data to the LE adv.
7434 */
7435 if (conn->le_adv_data_len > 0) {
7436 memcpy(&ev->eir[eir_len],
7437 conn->le_adv_data, conn->le_adv_data_len);
7438 eir_len = conn->le_adv_data_len;
7439 } else {
7440 if (name_len > 0)
7441 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7442 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007443
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007444 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007445 eir_len = eir_append_data(ev->eir, eir_len,
7446 EIR_CLASS_OF_DEV,
7447 conn->dev_class, 3);
7448 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007449
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007450 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007451
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007452 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7453 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007454}
7455
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007456static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007457{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007458 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007459
Johan Hedbergf5818c22014-12-05 13:36:02 +02007460 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007461
7462 *sk = cmd->sk;
7463 sock_hold(*sk);
7464
Johan Hedberga664b5b2011-02-19 12:06:02 -03007465 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007466}
7467
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007468static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007469{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007470 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007471 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007472
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007473 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7474
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007475 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007476 mgmt_pending_remove(cmd);
7477}
7478
Johan Hedberg84c61d92014-08-01 11:13:30 +03007479bool mgmt_powering_down(struct hci_dev *hdev)
7480{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007481 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007482 struct mgmt_mode *cp;
7483
Johan Hedberg333ae952015-03-17 13:48:47 +02007484 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007485 if (!cmd)
7486 return false;
7487
7488 cp = cmd->param;
7489 if (!cp->val)
7490 return true;
7491
7492 return false;
7493}
7494
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007495void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007496 u8 link_type, u8 addr_type, u8 reason,
7497 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007498{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007499 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007500 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007501
Johan Hedberg84c61d92014-08-01 11:13:30 +03007502 /* The connection is still in hci_conn_hash so test for 1
7503 * instead of 0 to know if this is the last one.
7504 */
7505 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7506 cancel_delayed_work(&hdev->power_off);
7507 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007508 }
7509
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007510 if (!mgmt_connected)
7511 return;
7512
Andre Guedes57eb7762013-10-30 19:01:41 -03007513 if (link_type != ACL_LINK && link_type != LE_LINK)
7514 return;
7515
Johan Hedberg744cf192011-11-08 20:40:14 +02007516 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007517
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007518 bacpy(&ev.addr.bdaddr, bdaddr);
7519 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7520 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007521
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007522 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007523
7524 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007525 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007526
Johan Hedberg124f6e32012-02-09 13:50:12 +02007527 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007528 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007529}
7530
Marcel Holtmann78929242013-10-06 23:55:47 -07007531void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7532 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007533{
Andre Guedes3655bba2013-10-30 19:01:40 -03007534 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7535 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007536 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007537
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007538 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7539 hdev);
7540
Johan Hedberg333ae952015-03-17 13:48:47 +02007541 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007542 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007543 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007544
Andre Guedes3655bba2013-10-30 19:01:40 -03007545 cp = cmd->param;
7546
7547 if (bacmp(bdaddr, &cp->addr.bdaddr))
7548 return;
7549
7550 if (cp->addr.type != bdaddr_type)
7551 return;
7552
Johan Hedbergf5818c22014-12-05 13:36:02 +02007553 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007554 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007555}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007556
Marcel Holtmann445608d2013-10-06 23:55:48 -07007557void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7558 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007559{
7560 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007561
Johan Hedberg84c61d92014-08-01 11:13:30 +03007562 /* The connection is still in hci_conn_hash so test for 1
7563 * instead of 0 to know if this is the last one.
7564 */
7565 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7566 cancel_delayed_work(&hdev->power_off);
7567 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007568 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007569
Johan Hedberg4c659c32011-11-07 23:13:39 +02007570 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007571 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007572 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007573
Marcel Holtmann445608d2013-10-06 23:55:48 -07007574 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007575}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007576
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007577void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007578{
7579 struct mgmt_ev_pin_code_request ev;
7580
Johan Hedbergd8457692012-02-17 14:24:57 +02007581 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007582 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007583 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007584
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007585 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007586}
7587
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007588void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7589 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007590{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007591 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007592
Johan Hedberg333ae952015-03-17 13:48:47 +02007593 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007594 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007595 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007596
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007597 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007598 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007599}
7600
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007601void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7602 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007603{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007604 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007605
Johan Hedberg333ae952015-03-17 13:48:47 +02007606 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007607 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007608 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007609
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007610 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007611 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007612}
Johan Hedberga5c29682011-02-19 12:05:57 -03007613
Johan Hedberg744cf192011-11-08 20:40:14 +02007614int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007615 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007616 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007617{
7618 struct mgmt_ev_user_confirm_request ev;
7619
Johan Hedberg744cf192011-11-08 20:40:14 +02007620 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007621
Johan Hedberg272d90d2012-02-09 15:26:12 +02007622 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007623 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007624 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007625 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007626
Johan Hedberg744cf192011-11-08 20:40:14 +02007627 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007628 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007629}
7630
Johan Hedberg272d90d2012-02-09 15:26:12 +02007631int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007632 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007633{
7634 struct mgmt_ev_user_passkey_request ev;
7635
7636 BT_DBG("%s", hdev->name);
7637
Johan Hedberg272d90d2012-02-09 15:26:12 +02007638 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007639 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007640
7641 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007642 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007643}
7644
Brian Gix0df4c182011-11-16 13:53:13 -08007645static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007646 u8 link_type, u8 addr_type, u8 status,
7647 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007648{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007649 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007650
Johan Hedberg333ae952015-03-17 13:48:47 +02007651 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007652 if (!cmd)
7653 return -ENOENT;
7654
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007655 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007656 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007657
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007658 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007659}
7660
Johan Hedberg744cf192011-11-08 20:40:14 +02007661int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007662 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007663{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007664 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007665 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007666}
7667
Johan Hedberg272d90d2012-02-09 15:26:12 +02007668int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007669 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007670{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007671 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007672 status,
7673 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007674}
Johan Hedberg2a611692011-02-19 12:06:00 -03007675
Brian Gix604086b2011-11-23 08:28:33 -08007676int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007677 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007678{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007679 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007680 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007681}
7682
Johan Hedberg272d90d2012-02-09 15:26:12 +02007683int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007684 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007685{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007686 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007687 status,
7688 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007689}
7690
Johan Hedberg92a25252012-09-06 18:39:26 +03007691int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7692 u8 link_type, u8 addr_type, u32 passkey,
7693 u8 entered)
7694{
7695 struct mgmt_ev_passkey_notify ev;
7696
7697 BT_DBG("%s", hdev->name);
7698
7699 bacpy(&ev.addr.bdaddr, bdaddr);
7700 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7701 ev.passkey = __cpu_to_le32(passkey);
7702 ev.entered = entered;
7703
7704 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7705}
7706
Johan Hedberge1e930f2014-09-08 17:09:49 -07007707void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007708{
7709 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007710 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007711 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007712
Johan Hedberge1e930f2014-09-08 17:09:49 -07007713 bacpy(&ev.addr.bdaddr, &conn->dst);
7714 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7715 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007716
Johan Hedberge1e930f2014-09-08 17:09:49 -07007717 cmd = find_pairing(conn);
7718
7719 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7720 cmd ? cmd->sk : NULL);
7721
Johan Hedberga511b352014-12-11 21:45:45 +02007722 if (cmd) {
7723 cmd->cmd_complete(cmd, status);
7724 mgmt_pending_remove(cmd);
7725 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007726}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007727
Marcel Holtmann464996a2013-10-15 14:26:24 -07007728void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007729{
7730 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007731 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007732
7733 if (status) {
7734 u8 mgmt_err = mgmt_status(status);
7735 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007736 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007737 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007738 }
7739
Marcel Holtmann464996a2013-10-15 14:26:24 -07007740 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007741 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007742 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007743 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007744
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007745 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007746 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007747
Johan Hedberg47990ea2012-02-22 11:58:37 +02007748 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007749 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007750
7751 if (match.sk)
7752 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007753}
7754
Johan Hedberg890ea892013-03-15 17:06:52 -05007755static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007756{
Johan Hedberg890ea892013-03-15 17:06:52 -05007757 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007758 struct hci_cp_write_eir cp;
7759
Johan Hedberg976eb202012-10-24 21:12:01 +03007760 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007761 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007762
Johan Hedbergc80da272012-02-22 15:38:48 +02007763 memset(hdev->eir, 0, sizeof(hdev->eir));
7764
Johan Hedbergcacaf522012-02-21 00:52:42 +02007765 memset(&cp, 0, sizeof(cp));
7766
Johan Hedberg890ea892013-03-15 17:06:52 -05007767 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007768}
7769
Marcel Holtmann3e248562013-10-15 14:26:25 -07007770void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007771{
7772 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007773 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007774 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007775
7776 if (status) {
7777 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007778
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007779 if (enable && hci_dev_test_and_clear_flag(hdev,
7780 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007781 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007782 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007783 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007784
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007785 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7786 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007787 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007788 }
7789
7790 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007791 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007792 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007793 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007794 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007795 changed = hci_dev_test_and_clear_flag(hdev,
7796 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007797 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007798 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007799 }
7800
7801 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7802
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007803 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007804 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007805
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007806 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007807 sock_put(match.sk);
7808
Johan Hedberg890ea892013-03-15 17:06:52 -05007809 hci_req_init(&req, hdev);
7810
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007811 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7812 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007813 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7814 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007815 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007816 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007817 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007818 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007819
7820 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007821}
7822
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007823static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007824{
7825 struct cmd_lookup *match = data;
7826
Johan Hedberg90e70452012-02-23 23:09:40 +02007827 if (match->sk == NULL) {
7828 match->sk = cmd->sk;
7829 sock_hold(match->sk);
7830 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007831}
7832
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007833void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7834 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007835{
Johan Hedberg90e70452012-02-23 23:09:40 +02007836 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007837
Johan Hedberg92da6092013-03-15 17:06:55 -05007838 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7839 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7840 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007841
7842 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007843 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7844 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007845
7846 if (match.sk)
7847 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007848}
7849
Marcel Holtmann7667da32013-10-15 14:26:27 -07007850void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007851{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007852 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007853 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007854
Johan Hedberg13928972013-03-15 17:07:00 -05007855 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007856 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007857
7858 memset(&ev, 0, sizeof(ev));
7859 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007860 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007861
Johan Hedberg333ae952015-03-17 13:48:47 +02007862 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007863 if (!cmd) {
7864 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007865
Johan Hedberg13928972013-03-15 17:07:00 -05007866 /* If this is a HCI command related to powering on the
7867 * HCI dev don't send any mgmt signals.
7868 */
Johan Hedberg333ae952015-03-17 13:48:47 +02007869 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007870 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007871 }
7872
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007873 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7874 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007875}
Szymon Jancc35938b2011-03-22 13:12:21 +01007876
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007877void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007878 u8 *rand192, u8 *hash256, u8 *rand256,
7879 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007880{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007881 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007882
Johan Hedberg744cf192011-11-08 20:40:14 +02007883 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007884
Johan Hedberg333ae952015-03-17 13:48:47 +02007885 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007886 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007887 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007888
7889 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007890 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7891 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007892 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007893 struct mgmt_rp_read_local_oob_data rp;
7894 size_t rp_size = sizeof(rp);
7895
7896 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7897 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7898
Johan Hedberg710f11c2014-05-26 11:21:22 +03007899 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007900 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007901 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007902 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007903 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007904 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007905
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007906 mgmt_cmd_complete(cmd->sk, hdev->id,
7907 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7908 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007909 }
7910
7911 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007912}
Johan Hedberge17acd42011-03-30 23:57:16 +03007913
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007914static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7915{
7916 int i;
7917
7918 for (i = 0; i < uuid_count; i++) {
7919 if (!memcmp(uuid, uuids[i], 16))
7920 return true;
7921 }
7922
7923 return false;
7924}
7925
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007926static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7927{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007928 u16 parsed = 0;
7929
7930 while (parsed < eir_len) {
7931 u8 field_len = eir[0];
7932 u8 uuid[16];
7933 int i;
7934
7935 if (field_len == 0)
7936 break;
7937
7938 if (eir_len - parsed < field_len + 1)
7939 break;
7940
7941 switch (eir[1]) {
7942 case EIR_UUID16_ALL:
7943 case EIR_UUID16_SOME:
7944 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007945 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007946 uuid[13] = eir[i + 3];
7947 uuid[12] = eir[i + 2];
7948 if (has_uuid(uuid, uuid_count, uuids))
7949 return true;
7950 }
7951 break;
7952 case EIR_UUID32_ALL:
7953 case EIR_UUID32_SOME:
7954 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007955 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007956 uuid[15] = eir[i + 5];
7957 uuid[14] = eir[i + 4];
7958 uuid[13] = eir[i + 3];
7959 uuid[12] = eir[i + 2];
7960 if (has_uuid(uuid, uuid_count, uuids))
7961 return true;
7962 }
7963 break;
7964 case EIR_UUID128_ALL:
7965 case EIR_UUID128_SOME:
7966 for (i = 0; i + 17 <= field_len; i += 16) {
7967 memcpy(uuid, eir + i + 2, 16);
7968 if (has_uuid(uuid, uuid_count, uuids))
7969 return true;
7970 }
7971 break;
7972 }
7973
7974 parsed += field_len + 1;
7975 eir += field_len + 1;
7976 }
7977
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007978 return false;
7979}
7980
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007981static void restart_le_scan(struct hci_dev *hdev)
7982{
7983 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007984 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007985 return;
7986
7987 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7988 hdev->discovery.scan_start +
7989 hdev->discovery.scan_duration))
7990 return;
7991
7992 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7993 DISCOV_LE_RESTART_DELAY);
7994}
7995
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007996static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7997 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7998{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007999 /* If a RSSI threshold has been specified, and
8000 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8001 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8002 * is set, let it through for further processing, as we might need to
8003 * restart the scan.
8004 *
8005 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8006 * the results are also dropped.
8007 */
8008 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8009 (rssi == HCI_RSSI_INVALID ||
8010 (rssi < hdev->discovery.rssi &&
8011 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8012 return false;
8013
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008014 if (hdev->discovery.uuid_count != 0) {
8015 /* If a list of UUIDs is provided in filter, results with no
8016 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008017 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008018 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8019 hdev->discovery.uuids) &&
8020 !eir_has_uuids(scan_rsp, scan_rsp_len,
8021 hdev->discovery.uuid_count,
8022 hdev->discovery.uuids))
8023 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008024 }
8025
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008026 /* If duplicate filtering does not report RSSI changes, then restart
8027 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008028 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008029 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8030 restart_le_scan(hdev);
8031
8032 /* Validate RSSI value against the RSSI threshold once more. */
8033 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8034 rssi < hdev->discovery.rssi)
8035 return false;
8036 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008037
8038 return true;
8039}
8040
Marcel Holtmann901801b2013-10-06 23:55:51 -07008041void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008042 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8043 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008044{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008045 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008046 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008047 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008048
Johan Hedberg75ce2082014-07-02 22:42:01 +03008049 /* Don't send events for a non-kernel initiated discovery. With
8050 * LE one exception is if we have pend_le_reports > 0 in which
8051 * case we're doing passive scanning and want these events.
8052 */
8053 if (!hci_discovery_active(hdev)) {
8054 if (link_type == ACL_LINK)
8055 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008056 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008057 return;
8058 }
Andre Guedes12602d02013-04-30 15:29:40 -03008059
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008060 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008061 /* We are using service discovery */
8062 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8063 scan_rsp_len))
8064 return;
8065 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008066
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008067 /* Make sure that the buffer is big enough. The 5 extra bytes
8068 * are for the potential CoD field.
8069 */
8070 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008071 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008072
Johan Hedberg1dc06092012-01-15 21:01:23 +02008073 memset(buf, 0, sizeof(buf));
8074
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008075 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8076 * RSSI value was reported as 0 when not available. This behavior
8077 * is kept when using device discovery. This is required for full
8078 * backwards compatibility with the API.
8079 *
8080 * However when using service discovery, the value 127 will be
8081 * returned when the RSSI is not available.
8082 */
Szymon Janc91200e92015-01-22 16:57:05 +01008083 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8084 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008085 rssi = 0;
8086
Johan Hedberg841c5642014-07-07 12:45:54 +03008087 bacpy(&ev->addr.bdaddr, bdaddr);
8088 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008089 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008090 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008091
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008092 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008093 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008094 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008095
Johan Hedberg1dc06092012-01-15 21:01:23 +02008096 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8097 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008098 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008099
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008100 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008101 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008102 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008103
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008104 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8105 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008106
Marcel Holtmann901801b2013-10-06 23:55:51 -07008107 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008108}
Johan Hedberga88a9652011-03-30 13:18:12 +03008109
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008110void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8111 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008112{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008113 struct mgmt_ev_device_found *ev;
8114 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8115 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008116
Johan Hedbergb644ba32012-01-17 21:48:47 +02008117 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008118
Johan Hedbergb644ba32012-01-17 21:48:47 +02008119 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008120
Johan Hedbergb644ba32012-01-17 21:48:47 +02008121 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008122 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008123 ev->rssi = rssi;
8124
8125 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008126 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008127
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008128 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008129
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008130 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008131}
Johan Hedberg314b2382011-04-27 10:29:57 -04008132
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008133void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008134{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008135 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008136
Andre Guedes343fb142011-11-22 17:14:19 -03008137 BT_DBG("%s discovering %u", hdev->name, discovering);
8138
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008139 memset(&ev, 0, sizeof(ev));
8140 ev.type = hdev->discovery.type;
8141 ev.discovering = discovering;
8142
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008143 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008144}
Antti Julku5e762442011-08-25 16:48:02 +03008145
Marcel Holtmann1904a852015-01-11 13:50:44 -08008146static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008147{
8148 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008149}
8150
8151void mgmt_reenable_advertising(struct hci_dev *hdev)
8152{
8153 struct hci_request req;
8154
Arman Uguray24b4f382015-03-23 15:57:12 -07008155 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8156 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008157 return;
8158
8159 hci_req_init(&req, hdev);
8160 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008161 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008162}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008163
8164static struct hci_mgmt_chan chan = {
8165 .channel = HCI_CHANNEL_CONTROL,
8166 .handler_count = ARRAY_SIZE(mgmt_handlers),
8167 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008168 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008169};
8170
8171int mgmt_init(void)
8172{
8173 return hci_mgmt_chan_register(&chan);
8174}
8175
8176void mgmt_exit(void)
8177{
8178 hci_mgmt_chan_unregister(&chan);
8179}