blob: bb0c53ac4c663a8e29eee2d6469135cd65135e56 [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 Uguraye7a685d2015-03-25 18:53:40 -0700944static u8 get_current_adv_instance(struct hci_dev *hdev)
Arman Uguray24b4f382015-03-23 15:57:12 -0700945{
Arman Uguray24b4f382015-03-23 15:57:12 -0700946 /* The "Set Advertising" setting supersedes the "Add Advertising"
947 * setting. Here we set the advertising data based on which
948 * setting was set. When neither apply, default to the global settings,
949 * represented by instance "0".
950 */
951 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
952 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700953 return 0x01;
954
955 return 0x00;
956}
957
958static bool get_connectable(struct hci_dev *hdev)
959{
960 struct mgmt_pending_cmd *cmd;
961
962 /* If there's a pending mgmt command the flag will not yet have
963 * it's final value, so check for this first.
964 */
965 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
966 if (cmd) {
967 struct mgmt_mode *cp = cmd->param;
968
969 return cp->val;
970 }
971
972 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
973}
974
975static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
976{
977 u32 flags;
978
979 if (instance > 0x01)
980 return 0;
981
Arman Ugurayfdf51782015-03-25 18:53:46 -0700982 if (instance == 0x01)
Arman Uguraye7a685d2015-03-25 18:53:40 -0700983 return hdev->adv_instance.flags;
984
Arman Ugurayfdf51782015-03-25 18:53:46 -0700985 /* Instance 0 always manages the "Tx Power" and "Flags" fields */
986 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700987
Arman Ugurayfaccb952015-03-28 12:38:58 -0700988 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting corresponds
989 * to the "connectable" instance flag.
990 */
991 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700992 flags |= MGMT_ADV_FLAG_CONNECTABLE;
993
Arman Uguraye7a685d2015-03-25 18:53:40 -0700994 return flags;
995}
996
Arman Ugurayc7d48832015-03-28 12:38:59 -0700997static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
998{
999 /* Ignore instance 0 and other unsupported instances */
1000 if (instance != 0x01)
1001 return 0;
1002
1003 /* TODO: Take into account the "appearance" and "local-name" flags here.
1004 * These are currently being ignored as they are not supported.
1005 */
1006 return hdev->adv_instance.scan_rsp_len;
1007}
1008
Arman Ugurayfdf51782015-03-25 18:53:46 -07001009static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1010{
1011 u8 ad_len = 0, flags = 0;
1012 u32 instance_flags = get_adv_instance_flags(hdev, instance);
1013
1014 /* The Add Advertising command allows userspace to set both the general
1015 * and limited discoverable flags.
1016 */
1017 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1018 flags |= LE_AD_GENERAL;
1019
1020 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1021 flags |= LE_AD_LIMITED;
1022
1023 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1024 /* If a discovery flag wasn't provided, simply use the global
1025 * settings.
1026 */
1027 if (!flags)
1028 flags |= get_adv_discov_flags(hdev);
1029
1030 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1031 flags |= LE_AD_NO_BREDR;
1032
1033 /* If flags would still be empty, then there is no need to
1034 * include the "Flags" AD field".
1035 */
1036 if (flags) {
1037 ptr[0] = 0x02;
1038 ptr[1] = EIR_FLAGS;
1039 ptr[2] = flags;
1040
1041 ad_len += 3;
1042 ptr += 3;
1043 }
1044 }
1045
1046 /* Provide Tx Power only if we can provide a valid value for it */
1047 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1048 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1049 ptr[0] = 0x02;
1050 ptr[1] = EIR_TX_POWER;
1051 ptr[2] = (u8)hdev->adv_tx_power;
1052
1053 ad_len += 3;
1054 ptr += 3;
1055 }
1056
1057 if (instance) {
1058 memcpy(ptr, hdev->adv_instance.adv_data,
1059 hdev->adv_instance.adv_data_len);
1060 ad_len += hdev->adv_instance.adv_data_len;
1061 }
1062
1063 return ad_len;
1064}
1065
1066static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
1067{
1068 struct hci_dev *hdev = req->hdev;
1069 struct hci_cp_le_set_adv_data cp;
1070 u8 len;
1071
1072 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1073 return;
1074
1075 memset(&cp, 0, sizeof(cp));
1076
1077 len = create_instance_adv_data(hdev, instance, cp.data);
1078
1079 /* There's nothing to do if the data hasn't changed */
1080 if (hdev->adv_data_len == len &&
1081 memcmp(cp.data, hdev->adv_data, len) == 0)
1082 return;
1083
1084 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1085 hdev->adv_data_len = len;
1086
1087 cp.length = len;
1088
1089 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1090}
1091
Arman Uguraye7a685d2015-03-25 18:53:40 -07001092static void update_adv_data(struct hci_request *req)
1093{
1094 struct hci_dev *hdev = req->hdev;
1095 u8 instance = get_current_adv_instance(hdev);
Arman Uguray24b4f382015-03-23 15:57:12 -07001096
1097 update_adv_data_for_instance(req, instance);
1098}
1099
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001100int mgmt_update_adv_data(struct hci_dev *hdev)
1101{
1102 struct hci_request req;
1103
1104 hci_req_init(&req, hdev);
1105 update_adv_data(&req);
1106
1107 return hci_req_run(&req, NULL);
1108}
1109
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001110static void create_eir(struct hci_dev *hdev, u8 *data)
1111{
1112 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001113 size_t name_len;
1114
1115 name_len = strlen(hdev->dev_name);
1116
1117 if (name_len > 0) {
1118 /* EIR Data type */
1119 if (name_len > 48) {
1120 name_len = 48;
1121 ptr[1] = EIR_NAME_SHORT;
1122 } else
1123 ptr[1] = EIR_NAME_COMPLETE;
1124
1125 /* EIR Data length */
1126 ptr[0] = name_len + 1;
1127
1128 memcpy(ptr + 2, hdev->dev_name, name_len);
1129
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001130 ptr += (name_len + 2);
1131 }
1132
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001133 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001134 ptr[0] = 2;
1135 ptr[1] = EIR_TX_POWER;
1136 ptr[2] = (u8) hdev->inq_tx_power;
1137
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001138 ptr += 3;
1139 }
1140
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001141 if (hdev->devid_source > 0) {
1142 ptr[0] = 9;
1143 ptr[1] = EIR_DEVICE_ID;
1144
1145 put_unaligned_le16(hdev->devid_source, ptr + 2);
1146 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1147 put_unaligned_le16(hdev->devid_product, ptr + 6);
1148 put_unaligned_le16(hdev->devid_version, ptr + 8);
1149
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001150 ptr += 10;
1151 }
1152
Johan Hedberg213202e2013-01-27 00:31:33 +02001153 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001154 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001155 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001156}
1157
Johan Hedberg890ea892013-03-15 17:06:52 -05001158static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001159{
Johan Hedberg890ea892013-03-15 17:06:52 -05001160 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001161 struct hci_cp_write_eir cp;
1162
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001163 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001164 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001165
Johan Hedberg976eb202012-10-24 21:12:01 +03001166 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001167 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001168
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001169 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001170 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001171
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001172 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001173 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001174
1175 memset(&cp, 0, sizeof(cp));
1176
1177 create_eir(hdev, cp.data);
1178
1179 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001180 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001181
1182 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1183
Johan Hedberg890ea892013-03-15 17:06:52 -05001184 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001185}
1186
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001187static u8 get_service_classes(struct hci_dev *hdev)
1188{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001189 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001190 u8 val = 0;
1191
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001192 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001193 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001194
1195 return val;
1196}
1197
Johan Hedberg890ea892013-03-15 17:06:52 -05001198static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001199{
Johan Hedberg890ea892013-03-15 17:06:52 -05001200 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001201 u8 cod[3];
1202
1203 BT_DBG("%s", hdev->name);
1204
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001205 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001206 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001207
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001208 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001209 return;
1210
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001211 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001212 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001213
1214 cod[0] = hdev->minor_class;
1215 cod[1] = hdev->major_class;
1216 cod[2] = get_service_classes(hdev);
1217
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001218 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001219 cod[1] |= 0x20;
1220
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001221 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001222 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001223
Johan Hedberg890ea892013-03-15 17:06:52 -05001224 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001225}
1226
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001227static void disable_advertising(struct hci_request *req)
1228{
1229 u8 enable = 0x00;
1230
1231 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1232}
1233
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001234static void enable_advertising(struct hci_request *req)
1235{
1236 struct hci_dev *hdev = req->hdev;
1237 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001238 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001239 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001240 u8 instance;
1241 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001242
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001243 if (hci_conn_num(hdev, LE_LINK) > 0)
1244 return;
1245
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001246 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001247 disable_advertising(req);
1248
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001249 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001250 * hci_update_random_address knows that it's safe to go ahead
1251 * and write a new random address. The flag will be set back on
1252 * as soon as the SET_ADV_ENABLE HCI command completes.
1253 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001254 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001255
Arman Uguraye7a685d2015-03-25 18:53:40 -07001256 instance = get_current_adv_instance(hdev);
1257 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001258
1259 /* If the "connectable" instance flag was not set, then choose between
1260 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1261 */
1262 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1263 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001264
Johan Hedberga4858cb2014-02-25 19:56:31 +02001265 /* Set require_privacy to true only when non-connectable
1266 * advertising is used. In that case it is fine to use a
1267 * non-resolvable private address.
1268 */
1269 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001270 return;
1271
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001272 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001273 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1274 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001275
1276 if (connectable)
1277 cp.type = LE_ADV_IND;
1278 else if (get_adv_instance_scan_rsp_len(hdev, instance))
1279 cp.type = LE_ADV_SCAN_IND;
1280 else
1281 cp.type = LE_ADV_NONCONN_IND;
1282
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001283 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001284 cp.channel_map = hdev->le_adv_channel_map;
1285
1286 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1287
1288 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1289}
1290
Johan Hedberg7d785252011-12-15 00:47:39 +02001291static void service_cache_off(struct work_struct *work)
1292{
1293 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001294 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001295 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001296
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001297 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001298 return;
1299
Johan Hedberg890ea892013-03-15 17:06:52 -05001300 hci_req_init(&req, hdev);
1301
Johan Hedberg7d785252011-12-15 00:47:39 +02001302 hci_dev_lock(hdev);
1303
Johan Hedberg890ea892013-03-15 17:06:52 -05001304 update_eir(&req);
1305 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001306
1307 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001308
1309 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001310}
1311
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001312static void rpa_expired(struct work_struct *work)
1313{
1314 struct hci_dev *hdev = container_of(work, struct hci_dev,
1315 rpa_expired.work);
1316 struct hci_request req;
1317
1318 BT_DBG("");
1319
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001320 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001321
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001322 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001323 return;
1324
1325 /* The generation of a new RPA and programming it into the
1326 * controller happens in the enable_advertising() function.
1327 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001328 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001329 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001330 hci_req_run(&req, NULL);
1331}
1332
Johan Hedberg6a919082012-02-28 06:17:26 +02001333static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001334{
Marcel Holtmann238be782015-03-13 02:11:06 -07001335 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001336 return;
1337
Johan Hedberg4f87da82012-03-02 19:55:56 +02001338 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001339 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001340
Johan Hedberg4f87da82012-03-02 19:55:56 +02001341 /* Non-mgmt controlled devices get this bit set
1342 * implicitly so that pairing works for them, however
1343 * for mgmt we require user-space to explicitly enable
1344 * it
1345 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001346 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001347}
1348
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001349static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001350 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001351{
1352 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001354 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001355
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001356 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001357
Johan Hedberg03811012010-12-08 00:21:06 +02001358 memset(&rp, 0, sizeof(rp));
1359
Johan Hedberg03811012010-12-08 00:21:06 +02001360 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001361
1362 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001363 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001364
1365 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1366 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1367
1368 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001369
1370 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001371 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001372
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001373 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001374
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001375 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1376 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001377}
1378
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001379static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001380{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001381 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001382
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001383 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1384 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001385}
1386
Marcel Holtmann1904a852015-01-11 13:50:44 -08001387static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001388{
1389 BT_DBG("%s status 0x%02x", hdev->name, status);
1390
Johan Hedberga3172b72014-02-28 09:33:44 +02001391 if (hci_conn_count(hdev) == 0) {
1392 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001393 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001394 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001395}
1396
Johan Hedberg23a48092014-07-08 16:05:06 +03001397static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001398{
1399 struct hci_dev *hdev = req->hdev;
1400 struct hci_cp_remote_name_req_cancel cp;
1401 struct inquiry_entry *e;
1402
1403 switch (hdev->discovery.state) {
1404 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001405 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001406 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001407
1408 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001409 cancel_delayed_work(&hdev->le_scan_disable);
1410 hci_req_add_le_scan_disable(req);
1411 }
1412
Johan Hedberg23a48092014-07-08 16:05:06 +03001413 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001414
1415 case DISCOVERY_RESOLVING:
1416 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1417 NAME_PENDING);
1418 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001419 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001420
1421 bacpy(&cp.bdaddr, &e->data.bdaddr);
1422 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1423 &cp);
1424
Johan Hedberg23a48092014-07-08 16:05:06 +03001425 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001426
1427 default:
1428 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001429 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001430 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001431 return true;
1432 }
1433
Johan Hedberg21a60d32014-06-10 14:05:58 +03001434 break;
1435 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001436
1437 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001438}
1439
Arman Uguray912098a2015-03-23 15:57:15 -07001440static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1441 u8 instance)
1442{
1443 struct mgmt_ev_advertising_added ev;
1444
1445 ev.instance = instance;
1446
1447 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1448}
1449
1450static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1451 u8 instance)
1452{
1453 struct mgmt_ev_advertising_removed ev;
1454
1455 ev.instance = instance;
1456
1457 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1458}
1459
1460static void clear_adv_instance(struct hci_dev *hdev)
1461{
1462 struct hci_request req;
1463
1464 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1465 return;
1466
1467 if (hdev->adv_instance.timeout)
1468 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
1469
1470 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1471 advertising_removed(NULL, hdev, 1);
1472 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1473
1474 if (!hdev_is_powered(hdev) ||
1475 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1476 return;
1477
1478 hci_req_init(&req, hdev);
1479 disable_advertising(&req);
1480 hci_req_run(&req, NULL);
1481}
1482
Johan Hedberg8b064a32014-02-24 14:52:22 +02001483static int clean_up_hci_state(struct hci_dev *hdev)
1484{
1485 struct hci_request req;
1486 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001487 bool discov_stopped;
1488 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001489
1490 hci_req_init(&req, hdev);
1491
1492 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1493 test_bit(HCI_PSCAN, &hdev->flags)) {
1494 u8 scan = 0x00;
1495 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1496 }
1497
Arman Uguray912098a2015-03-23 15:57:15 -07001498 if (hdev->adv_instance.timeout)
1499 clear_adv_instance(hdev);
1500
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001501 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001502 disable_advertising(&req);
1503
Johan Hedberg23a48092014-07-08 16:05:06 +03001504 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001505
1506 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1507 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001508 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001509
Johan Hedbergc9910d02014-02-27 14:35:12 +02001510 switch (conn->state) {
1511 case BT_CONNECTED:
1512 case BT_CONFIG:
1513 dc.handle = cpu_to_le16(conn->handle);
1514 dc.reason = 0x15; /* Terminated due to Power Off */
1515 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1516 break;
1517 case BT_CONNECT:
1518 if (conn->type == LE_LINK)
1519 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1520 0, NULL);
1521 else if (conn->type == ACL_LINK)
1522 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1523 6, &conn->dst);
1524 break;
1525 case BT_CONNECT2:
1526 bacpy(&rej.bdaddr, &conn->dst);
1527 rej.reason = 0x15; /* Terminated due to Power Off */
1528 if (conn->type == ACL_LINK)
1529 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1530 sizeof(rej), &rej);
1531 else if (conn->type == SCO_LINK)
1532 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1533 sizeof(rej), &rej);
1534 break;
1535 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001536 }
1537
Johan Hedberg23a48092014-07-08 16:05:06 +03001538 err = hci_req_run(&req, clean_up_hci_complete);
1539 if (!err && discov_stopped)
1540 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1541
1542 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001543}
1544
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001545static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001546 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001547{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001548 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001549 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001550 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001552 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001553
Johan Hedberga7e80f22013-01-09 16:05:19 +02001554 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001555 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1556 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001557
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001558 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001559
Johan Hedberg333ae952015-03-17 13:48:47 +02001560 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001561 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1562 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001563 goto failed;
1564 }
1565
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001566 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001567 cancel_delayed_work(&hdev->power_off);
1568
1569 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001570 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1571 data, len);
1572 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001573 goto failed;
1574 }
1575 }
1576
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001577 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001578 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001579 goto failed;
1580 }
1581
Johan Hedberg03811012010-12-08 00:21:06 +02001582 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1583 if (!cmd) {
1584 err = -ENOMEM;
1585 goto failed;
1586 }
1587
Johan Hedberg8b064a32014-02-24 14:52:22 +02001588 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001589 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590 err = 0;
1591 } else {
1592 /* Disconnect connections, stop scans, etc */
1593 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001594 if (!err)
1595 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1596 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001597
Johan Hedberg8b064a32014-02-24 14:52:22 +02001598 /* ENODATA means there were no HCI commands queued */
1599 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001600 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001601 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1602 err = 0;
1603 }
1604 }
Johan Hedberg03811012010-12-08 00:21:06 +02001605
1606failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001607 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001608 return err;
1609}
1610
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001611static int new_settings(struct hci_dev *hdev, struct sock *skip)
1612{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001613 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001614
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001615 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1616 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001617}
1618
Johan Hedberg91a668b2014-07-09 13:28:26 +03001619int mgmt_new_settings(struct hci_dev *hdev)
1620{
1621 return new_settings(hdev, NULL);
1622}
1623
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001624struct cmd_lookup {
1625 struct sock *sk;
1626 struct hci_dev *hdev;
1627 u8 mgmt_status;
1628};
1629
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001630static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001631{
1632 struct cmd_lookup *match = data;
1633
1634 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1635
1636 list_del(&cmd->list);
1637
1638 if (match->sk == NULL) {
1639 match->sk = cmd->sk;
1640 sock_hold(match->sk);
1641 }
1642
1643 mgmt_pending_free(cmd);
1644}
1645
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001646static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001647{
1648 u8 *status = data;
1649
Johan Hedberga69e8372015-03-06 21:08:53 +02001650 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001651 mgmt_pending_remove(cmd);
1652}
1653
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001654static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001655{
1656 if (cmd->cmd_complete) {
1657 u8 *status = data;
1658
1659 cmd->cmd_complete(cmd, *status);
1660 mgmt_pending_remove(cmd);
1661
1662 return;
1663 }
1664
1665 cmd_status_rsp(cmd, data);
1666}
1667
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001668static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001669{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001670 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1671 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001672}
1673
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001674static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001675{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001676 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1677 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001678}
1679
Johan Hedberge6fe7982013-10-02 15:45:22 +03001680static u8 mgmt_bredr_support(struct hci_dev *hdev)
1681{
1682 if (!lmp_bredr_capable(hdev))
1683 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001684 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001685 return MGMT_STATUS_REJECTED;
1686 else
1687 return MGMT_STATUS_SUCCESS;
1688}
1689
1690static u8 mgmt_le_support(struct hci_dev *hdev)
1691{
1692 if (!lmp_le_capable(hdev))
1693 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001694 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001695 return MGMT_STATUS_REJECTED;
1696 else
1697 return MGMT_STATUS_SUCCESS;
1698}
1699
Marcel Holtmann1904a852015-01-11 13:50:44 -08001700static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1701 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001702{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001703 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001704 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001705 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001706 bool changed;
1707
1708 BT_DBG("status 0x%02x", status);
1709
1710 hci_dev_lock(hdev);
1711
Johan Hedberg333ae952015-03-17 13:48:47 +02001712 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001713 if (!cmd)
1714 goto unlock;
1715
1716 if (status) {
1717 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001718 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001719 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001720 goto remove_cmd;
1721 }
1722
1723 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001724 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001725 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001726
1727 if (hdev->discov_timeout > 0) {
1728 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1729 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1730 to);
1731 }
1732 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001733 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001734 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001735
1736 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1737
1738 if (changed)
1739 new_settings(hdev, cmd->sk);
1740
Marcel Holtmann970ba522013-10-15 06:33:57 -07001741 /* When the discoverable mode gets changed, make sure
1742 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001743 * bit correctly set. Also update page scan based on whitelist
1744 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001745 */
1746 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001747 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001748 update_class(&req);
1749 hci_req_run(&req, NULL);
1750
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001751remove_cmd:
1752 mgmt_pending_remove(cmd);
1753
1754unlock:
1755 hci_dev_unlock(hdev);
1756}
1757
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001758static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001759 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001760{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001761 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001762 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001763 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001764 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001765 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001766 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001767
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001768 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001769
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001770 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1771 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001772 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1773 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001774
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001775 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001776 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1777 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001778
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001779 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001780
1781 /* Disabling discoverable requires that no timeout is set,
1782 * and enabling limited discoverable requires a timeout.
1783 */
1784 if ((cp->val == 0x00 && timeout > 0) ||
1785 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001786 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1787 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001788
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001789 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001790
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001791 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001792 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1793 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001794 goto failed;
1795 }
1796
Johan Hedberg333ae952015-03-17 13:48:47 +02001797 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1798 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001799 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1800 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001801 goto failed;
1802 }
1803
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001804 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001805 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1806 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001807 goto failed;
1808 }
1809
1810 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001811 bool changed = false;
1812
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001813 /* Setting limited discoverable when powered off is
1814 * not a valid operation since it requires a timeout
1815 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1816 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001817 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001818 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001819 changed = true;
1820 }
1821
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001822 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001823 if (err < 0)
1824 goto failed;
1825
1826 if (changed)
1827 err = new_settings(hdev, sk);
1828
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001829 goto failed;
1830 }
1831
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001832 /* If the current mode is the same, then just update the timeout
1833 * value with the new value. And if only the timeout gets updated,
1834 * then no need for any HCI transactions.
1835 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001836 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1837 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1838 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001839 cancel_delayed_work(&hdev->discov_off);
1840 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001841
Marcel Holtmann36261542013-10-15 08:28:51 -07001842 if (cp->val && hdev->discov_timeout > 0) {
1843 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001844 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001845 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001846 }
1847
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001848 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001849 goto failed;
1850 }
1851
1852 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1853 if (!cmd) {
1854 err = -ENOMEM;
1855 goto failed;
1856 }
1857
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001858 /* Cancel any potential discoverable timeout that might be
1859 * still active and store new timeout value. The arming of
1860 * the timeout happens in the complete handler.
1861 */
1862 cancel_delayed_work(&hdev->discov_off);
1863 hdev->discov_timeout = timeout;
1864
Johan Hedbergb456f872013-10-19 23:38:22 +03001865 /* Limited discoverable mode */
1866 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001867 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001868 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001869 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001870
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001871 hci_req_init(&req, hdev);
1872
Johan Hedberg9a43e252013-10-20 19:00:07 +03001873 /* The procedure for LE-only controllers is much simpler - just
1874 * update the advertising data.
1875 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001876 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001877 goto update_ad;
1878
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001879 scan = SCAN_PAGE;
1880
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001881 if (cp->val) {
1882 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001883
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001884 if (cp->val == 0x02) {
1885 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001886 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001887 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1888 hci_cp.iac_lap[1] = 0x8b;
1889 hci_cp.iac_lap[2] = 0x9e;
1890 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1891 hci_cp.iac_lap[4] = 0x8b;
1892 hci_cp.iac_lap[5] = 0x9e;
1893 } else {
1894 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001895 hci_cp.num_iac = 1;
1896 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1897 hci_cp.iac_lap[1] = 0x8b;
1898 hci_cp.iac_lap[2] = 0x9e;
1899 }
1900
1901 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1902 (hci_cp.num_iac * 3) + 1, &hci_cp);
1903
1904 scan |= SCAN_INQUIRY;
1905 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001906 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001907 }
1908
1909 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001910
Johan Hedberg9a43e252013-10-20 19:00:07 +03001911update_ad:
1912 update_adv_data(&req);
1913
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001914 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001915 if (err < 0)
1916 mgmt_pending_remove(cmd);
1917
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001918failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001919 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001920 return err;
1921}
1922
Johan Hedberg406d7802013-03-15 17:07:09 -05001923static void write_fast_connectable(struct hci_request *req, bool enable)
1924{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001925 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001926 struct hci_cp_write_page_scan_activity acp;
1927 u8 type;
1928
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001929 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001930 return;
1931
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001932 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1933 return;
1934
Johan Hedberg406d7802013-03-15 17:07:09 -05001935 if (enable) {
1936 type = PAGE_SCAN_TYPE_INTERLACED;
1937
1938 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001939 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001940 } else {
1941 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1942
1943 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001944 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001945 }
1946
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001947 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001948
Johan Hedbergbd98b992013-03-15 17:07:13 -05001949 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1950 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1951 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1952 sizeof(acp), &acp);
1953
1954 if (hdev->page_scan_type != type)
1955 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001956}
1957
Marcel Holtmann1904a852015-01-11 13:50:44 -08001958static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1959 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001960{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001961 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001962 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001963 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001964
1965 BT_DBG("status 0x%02x", status);
1966
1967 hci_dev_lock(hdev);
1968
Johan Hedberg333ae952015-03-17 13:48:47 +02001969 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001970 if (!cmd)
1971 goto unlock;
1972
Johan Hedberg37438c12013-10-14 16:20:05 +03001973 if (status) {
1974 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001975 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001976 goto remove_cmd;
1977 }
1978
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001979 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001980 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001981 conn_changed = !hci_dev_test_and_set_flag(hdev,
1982 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001983 discov_changed = false;
1984 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001985 conn_changed = hci_dev_test_and_clear_flag(hdev,
1986 HCI_CONNECTABLE);
1987 discov_changed = hci_dev_test_and_clear_flag(hdev,
1988 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001989 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001990
Johan Hedberg2b76f452013-03-15 17:07:04 -05001991 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1992
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001993 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001994 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001995 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001996 if (discov_changed)
1997 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001998 hci_update_background_scan(hdev);
1999 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002000
Johan Hedberg37438c12013-10-14 16:20:05 +03002001remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002002 mgmt_pending_remove(cmd);
2003
2004unlock:
2005 hci_dev_unlock(hdev);
2006}
2007
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002008static int set_connectable_update_settings(struct hci_dev *hdev,
2009 struct sock *sk, u8 val)
2010{
2011 bool changed = false;
2012 int err;
2013
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002014 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002015 changed = true;
2016
2017 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002018 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002019 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002020 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2021 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002022 }
2023
2024 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2025 if (err < 0)
2026 return err;
2027
Johan Hedberg562064e2014-07-08 16:35:34 +03002028 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002029 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002030 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002031 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002032 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002033
2034 return 0;
2035}
2036
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002037static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002038 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002039{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002040 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002041 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002042 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002043 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002044 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002045
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002046 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002047
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002048 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2049 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002050 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2051 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002052
Johan Hedberga7e80f22013-01-09 16:05:19 +02002053 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002054 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2055 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002056
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002057 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002058
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002059 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002060 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002061 goto failed;
2062 }
2063
Johan Hedberg333ae952015-03-17 13:48:47 +02002064 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2065 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002066 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2067 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002068 goto failed;
2069 }
2070
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002071 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2072 if (!cmd) {
2073 err = -ENOMEM;
2074 goto failed;
2075 }
2076
Johan Hedberg2b76f452013-03-15 17:07:04 -05002077 hci_req_init(&req, hdev);
2078
Johan Hedberg9a43e252013-10-20 19:00:07 +03002079 /* If BR/EDR is not enabled and we disable advertising as a
2080 * by-product of disabling connectable, we need to update the
2081 * advertising flags.
2082 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002083 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002084 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002085 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2086 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002087 }
2088 update_adv_data(&req);
2089 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002090 if (cp->val) {
2091 scan = SCAN_PAGE;
2092 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002093 /* If we don't have any whitelist entries just
2094 * disable all scanning. If there are entries
2095 * and we had both page and inquiry scanning
2096 * enabled then fall back to only page scanning.
2097 * Otherwise no changes are needed.
2098 */
2099 if (list_empty(&hdev->whitelist))
2100 scan = SCAN_DISABLED;
2101 else if (test_bit(HCI_ISCAN, &hdev->flags))
2102 scan = SCAN_PAGE;
2103 else
2104 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002105
2106 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002107 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002108 cancel_delayed_work(&hdev->discov_off);
2109 }
2110
2111 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2112 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002113
Johan Hedberg3bd27242014-07-28 20:53:58 +03002114no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002115 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002116 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2117 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002118 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002119
Johan Hedberg2b76f452013-03-15 17:07:04 -05002120 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002121 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002122 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002123 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002124 err = set_connectable_update_settings(hdev, sk,
2125 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002126 goto failed;
2127 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002128
2129failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002130 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002131 return err;
2132}
2133
Johan Hedbergb2939472014-07-30 09:22:23 +03002134static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002135 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002136{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002137 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002138 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002139 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002141 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002142
Johan Hedberga7e80f22013-01-09 16:05:19 +02002143 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002144 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2145 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002146
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002147 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002148
2149 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002150 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002151 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002152 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002153
Johan Hedbergb2939472014-07-30 09:22:23 +03002154 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002155 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002156 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002157
Marcel Holtmann55594352013-10-06 16:11:57 -07002158 if (changed)
2159 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002160
Marcel Holtmann55594352013-10-06 16:11:57 -07002161unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002162 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002163 return err;
2164}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002165
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002166static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2167 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002168{
2169 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002170 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002171 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002172 int err;
2173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002174 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002175
Johan Hedberge6fe7982013-10-02 15:45:22 +03002176 status = mgmt_bredr_support(hdev);
2177 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002178 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2179 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002180
Johan Hedberga7e80f22013-01-09 16:05:19 +02002181 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002182 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2183 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002184
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002185 hci_dev_lock(hdev);
2186
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002187 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002188 bool changed = false;
2189
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002190 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002191 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002192 changed = true;
2193 }
2194
2195 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2196 if (err < 0)
2197 goto failed;
2198
2199 if (changed)
2200 err = new_settings(hdev, sk);
2201
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002202 goto failed;
2203 }
2204
Johan Hedberg333ae952015-03-17 13:48:47 +02002205 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002206 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2207 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002208 goto failed;
2209 }
2210
2211 val = !!cp->val;
2212
2213 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2214 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2215 goto failed;
2216 }
2217
2218 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2219 if (!cmd) {
2220 err = -ENOMEM;
2221 goto failed;
2222 }
2223
2224 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2225 if (err < 0) {
2226 mgmt_pending_remove(cmd);
2227 goto failed;
2228 }
2229
2230failed:
2231 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002232 return err;
2233}
2234
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002235static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002236{
2237 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002238 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002239 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002240 int err;
2241
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002242 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002243
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002244 status = mgmt_bredr_support(hdev);
2245 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002246 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002247
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002248 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002249 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2250 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002251
Johan Hedberga7e80f22013-01-09 16:05:19 +02002252 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002253 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2254 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002255
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002256 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002257
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002258 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002259 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002260
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002261 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002262 changed = !hci_dev_test_and_set_flag(hdev,
2263 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002264 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002265 changed = hci_dev_test_and_clear_flag(hdev,
2266 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002267 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002268 changed = hci_dev_test_and_clear_flag(hdev,
2269 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002270 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002271 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002272 }
2273
2274 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2275 if (err < 0)
2276 goto failed;
2277
2278 if (changed)
2279 err = new_settings(hdev, sk);
2280
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002281 goto failed;
2282 }
2283
Johan Hedberg333ae952015-03-17 13:48:47 +02002284 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002285 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2286 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002287 goto failed;
2288 }
2289
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002290 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002291 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2292 goto failed;
2293 }
2294
2295 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2296 if (!cmd) {
2297 err = -ENOMEM;
2298 goto failed;
2299 }
2300
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002301 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002302 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2303 sizeof(cp->val), &cp->val);
2304
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002305 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002306 if (err < 0) {
2307 mgmt_pending_remove(cmd);
2308 goto failed;
2309 }
2310
2311failed:
2312 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002313 return err;
2314}
2315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002316static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002317{
2318 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002319 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002320 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002321 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002322
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002323 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002324
Johan Hedberge6fe7982013-10-02 15:45:22 +03002325 status = mgmt_bredr_support(hdev);
2326 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002327 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002328
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002329 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002330 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2331 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002332
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002333 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002334 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2335 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002336
Johan Hedberga7e80f22013-01-09 16:05:19 +02002337 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002338 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2339 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002340
Marcel Holtmannee392692013-10-01 22:59:23 -07002341 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002342
Johan Hedberg333ae952015-03-17 13:48:47 +02002343 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002344 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2345 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002346 goto unlock;
2347 }
2348
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002349 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002350 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002351 } else {
2352 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002353 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2354 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002355 goto unlock;
2356 }
2357
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002358 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002359 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002360
2361 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2362 if (err < 0)
2363 goto unlock;
2364
2365 if (changed)
2366 err = new_settings(hdev, sk);
2367
2368unlock:
2369 hci_dev_unlock(hdev);
2370 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002371}
2372
Marcel Holtmann1904a852015-01-11 13:50:44 -08002373static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002374{
2375 struct cmd_lookup match = { NULL, hdev };
2376
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302377 hci_dev_lock(hdev);
2378
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002379 if (status) {
2380 u8 mgmt_err = mgmt_status(status);
2381
2382 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2383 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302384 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002385 }
2386
2387 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2388
2389 new_settings(hdev, match.sk);
2390
2391 if (match.sk)
2392 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002393
2394 /* Make sure the controller has a good default for
2395 * advertising data. Restrict the update to when LE
2396 * has actually been enabled. During power on, the
2397 * update in powered_update_hci will take care of it.
2398 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002399 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002400 struct hci_request req;
2401
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002402 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002403 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002404 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002405 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002406 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002407 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302408
2409unlock:
2410 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002411}
2412
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002413static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002414{
2415 struct mgmt_mode *cp = data;
2416 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002417 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002418 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002419 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002420 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002421
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002422 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002423
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002424 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002425 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2426 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002427
Johan Hedberga7e80f22013-01-09 16:05:19 +02002428 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002429 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2430 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002431
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002432 /* Bluetooth single mode LE only controllers or dual-mode
2433 * controllers configured as LE only devices, do not allow
2434 * switching LE off. These have either LE enabled explicitly
2435 * or BR/EDR has been previously switched off.
2436 *
2437 * When trying to enable an already enabled LE, then gracefully
2438 * send a positive response. Trying to disable it however will
2439 * result into rejection.
2440 */
2441 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2442 if (cp->val == 0x01)
2443 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2444
Johan Hedberga69e8372015-03-06 21:08:53 +02002445 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2446 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002447 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002448
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002449 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002450
2451 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002452 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002453
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002454 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002455 bool changed = false;
2456
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002457 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002458 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002459 changed = true;
2460 }
2461
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002462 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002463 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002464 changed = true;
2465 }
2466
Johan Hedberg06199cf2012-02-22 16:37:11 +02002467 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2468 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002469 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002470
2471 if (changed)
2472 err = new_settings(hdev, sk);
2473
Johan Hedberg1de028c2012-02-29 19:55:35 -08002474 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002475 }
2476
Johan Hedberg333ae952015-03-17 13:48:47 +02002477 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2478 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002479 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2480 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002481 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002482 }
2483
2484 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2485 if (!cmd) {
2486 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002487 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002488 }
2489
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002490 hci_req_init(&req, hdev);
2491
Johan Hedberg06199cf2012-02-22 16:37:11 +02002492 memset(&hci_cp, 0, sizeof(hci_cp));
2493
2494 if (val) {
2495 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002496 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002497 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002498 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002499 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002500 }
2501
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002502 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2503 &hci_cp);
2504
2505 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302506 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002507 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002508
Johan Hedberg1de028c2012-02-29 19:55:35 -08002509unlock:
2510 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002511 return err;
2512}
2513
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002514/* This is a helper function to test for pending mgmt commands that can
2515 * cause CoD or EIR HCI commands. We can only allow one such pending
2516 * mgmt command at a time since otherwise we cannot easily track what
2517 * the current values are, will be, and based on that calculate if a new
2518 * HCI command needs to be sent and if yes with what value.
2519 */
2520static bool pending_eir_or_class(struct hci_dev *hdev)
2521{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002522 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002523
2524 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2525 switch (cmd->opcode) {
2526 case MGMT_OP_ADD_UUID:
2527 case MGMT_OP_REMOVE_UUID:
2528 case MGMT_OP_SET_DEV_CLASS:
2529 case MGMT_OP_SET_POWERED:
2530 return true;
2531 }
2532 }
2533
2534 return false;
2535}
2536
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002537static const u8 bluetooth_base_uuid[] = {
2538 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2539 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2540};
2541
2542static u8 get_uuid_size(const u8 *uuid)
2543{
2544 u32 val;
2545
2546 if (memcmp(uuid, bluetooth_base_uuid, 12))
2547 return 128;
2548
2549 val = get_unaligned_le32(&uuid[12]);
2550 if (val > 0xffff)
2551 return 32;
2552
2553 return 16;
2554}
2555
Johan Hedberg92da6092013-03-15 17:06:55 -05002556static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2557{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002558 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002559
2560 hci_dev_lock(hdev);
2561
Johan Hedberg333ae952015-03-17 13:48:47 +02002562 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002563 if (!cmd)
2564 goto unlock;
2565
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002566 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2567 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002568
2569 mgmt_pending_remove(cmd);
2570
2571unlock:
2572 hci_dev_unlock(hdev);
2573}
2574
Marcel Holtmann1904a852015-01-11 13:50:44 -08002575static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002576{
2577 BT_DBG("status 0x%02x", status);
2578
2579 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2580}
2581
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002582static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002583{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002584 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002585 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002586 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002587 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002588 int err;
2589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002590 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002591
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002592 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002593
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002594 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002595 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2596 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002597 goto failed;
2598 }
2599
Andre Guedes92c4c202012-06-07 19:05:44 -03002600 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002601 if (!uuid) {
2602 err = -ENOMEM;
2603 goto failed;
2604 }
2605
2606 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002607 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002608 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002609
Johan Hedbergde66aa62013-01-27 00:31:27 +02002610 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002611
Johan Hedberg890ea892013-03-15 17:06:52 -05002612 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002613
Johan Hedberg890ea892013-03-15 17:06:52 -05002614 update_class(&req);
2615 update_eir(&req);
2616
Johan Hedberg92da6092013-03-15 17:06:55 -05002617 err = hci_req_run(&req, add_uuid_complete);
2618 if (err < 0) {
2619 if (err != -ENODATA)
2620 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002621
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002622 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2623 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002624 goto failed;
2625 }
2626
2627 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002628 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002629 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002630 goto failed;
2631 }
2632
2633 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002634
2635failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002636 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002637 return err;
2638}
2639
Johan Hedberg24b78d02012-02-23 23:24:30 +02002640static bool enable_service_cache(struct hci_dev *hdev)
2641{
2642 if (!hdev_is_powered(hdev))
2643 return false;
2644
Marcel Holtmann238be782015-03-13 02:11:06 -07002645 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002646 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2647 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002648 return true;
2649 }
2650
2651 return false;
2652}
2653
Marcel Holtmann1904a852015-01-11 13:50:44 -08002654static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002655{
2656 BT_DBG("status 0x%02x", status);
2657
2658 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2659}
2660
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002661static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002662 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002663{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002664 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002665 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002666 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002667 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 -05002668 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002669 int err, found;
2670
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002671 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002673 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002674
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002675 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002676 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2677 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002678 goto unlock;
2679 }
2680
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002681 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002682 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002683
Johan Hedberg24b78d02012-02-23 23:24:30 +02002684 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002685 err = mgmt_cmd_complete(sk, hdev->id,
2686 MGMT_OP_REMOVE_UUID,
2687 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002688 goto unlock;
2689 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002690
Johan Hedberg9246a862012-02-23 21:33:16 +02002691 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002692 }
2693
2694 found = 0;
2695
Johan Hedberg056341c2013-01-27 00:31:30 +02002696 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002697 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2698 continue;
2699
2700 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002701 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002702 found++;
2703 }
2704
2705 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002706 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2707 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002708 goto unlock;
2709 }
2710
Johan Hedberg9246a862012-02-23 21:33:16 +02002711update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002712 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002713
Johan Hedberg890ea892013-03-15 17:06:52 -05002714 update_class(&req);
2715 update_eir(&req);
2716
Johan Hedberg92da6092013-03-15 17:06:55 -05002717 err = hci_req_run(&req, remove_uuid_complete);
2718 if (err < 0) {
2719 if (err != -ENODATA)
2720 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002721
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002722 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2723 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002724 goto unlock;
2725 }
2726
2727 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002728 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002729 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002730 goto unlock;
2731 }
2732
2733 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002734
2735unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002736 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002737 return err;
2738}
2739
Marcel Holtmann1904a852015-01-11 13:50:44 -08002740static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002741{
2742 BT_DBG("status 0x%02x", status);
2743
2744 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2745}
2746
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002747static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002748 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002749{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002750 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002751 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002752 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002753 int err;
2754
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002756
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002757 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002758 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2759 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002760
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002761 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002762
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002763 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002764 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2765 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002766 goto unlock;
2767 }
2768
2769 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002770 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2771 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002772 goto unlock;
2773 }
2774
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002775 hdev->major_class = cp->major;
2776 hdev->minor_class = cp->minor;
2777
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002778 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002779 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2780 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002781 goto unlock;
2782 }
2783
Johan Hedberg890ea892013-03-15 17:06:52 -05002784 hci_req_init(&req, hdev);
2785
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002786 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002787 hci_dev_unlock(hdev);
2788 cancel_delayed_work_sync(&hdev->service_cache);
2789 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002790 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002791 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002792
Johan Hedberg890ea892013-03-15 17:06:52 -05002793 update_class(&req);
2794
Johan Hedberg92da6092013-03-15 17:06:55 -05002795 err = hci_req_run(&req, set_class_complete);
2796 if (err < 0) {
2797 if (err != -ENODATA)
2798 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002799
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002800 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2801 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002802 goto unlock;
2803 }
2804
2805 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002806 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002807 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002808 goto unlock;
2809 }
2810
2811 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002812
Johan Hedbergb5235a62012-02-21 14:32:24 +02002813unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002814 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002815 return err;
2816}
2817
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002818static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002819 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002820{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002821 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002822 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2823 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002824 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002825 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002826 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002827
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002828 BT_DBG("request for %s", hdev->name);
2829
2830 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002831 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2832 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002833
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002834 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002835 if (key_count > max_key_count) {
2836 BT_ERR("load_link_keys: too big key_count value %u",
2837 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002838 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2839 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002840 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002841
Johan Hedberg86742e12011-11-07 23:13:38 +02002842 expected_len = sizeof(*cp) + key_count *
2843 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002844 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002845 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002846 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002847 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2848 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002849 }
2850
Johan Hedberg4ae14302013-01-20 14:27:13 +02002851 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002852 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2853 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002854
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002855 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002856 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002857
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002858 for (i = 0; i < key_count; i++) {
2859 struct mgmt_link_key_info *key = &cp->keys[i];
2860
Marcel Holtmann8e991132014-01-10 02:07:25 -08002861 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002862 return mgmt_cmd_status(sk, hdev->id,
2863 MGMT_OP_LOAD_LINK_KEYS,
2864 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002865 }
2866
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002867 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002868
2869 hci_link_keys_clear(hdev);
2870
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002871 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002872 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002873 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002874 changed = hci_dev_test_and_clear_flag(hdev,
2875 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002876
2877 if (changed)
2878 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002879
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002880 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002881 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002882
Johan Hedberg58e92932014-06-24 14:00:26 +03002883 /* Always ignore debug keys and require a new pairing if
2884 * the user wants to use them.
2885 */
2886 if (key->type == HCI_LK_DEBUG_COMBINATION)
2887 continue;
2888
Johan Hedberg7652ff62014-06-24 13:15:49 +03002889 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2890 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002891 }
2892
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002893 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002894
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002895 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002896
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002897 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002898}
2899
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002900static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002901 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002902{
2903 struct mgmt_ev_device_unpaired ev;
2904
2905 bacpy(&ev.addr.bdaddr, bdaddr);
2906 ev.addr.type = addr_type;
2907
2908 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002909 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002910}
2911
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002912static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002913 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002914{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002915 struct mgmt_cp_unpair_device *cp = data;
2916 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002917 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002918 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002919 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002920 int err;
2921
Johan Hedberga8a1d192011-11-10 15:54:38 +02002922 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002923 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2924 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002925
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002926 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002927 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2928 MGMT_STATUS_INVALID_PARAMS,
2929 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002930
Johan Hedberg118da702013-01-20 14:27:20 +02002931 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002932 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2933 MGMT_STATUS_INVALID_PARAMS,
2934 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002935
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002936 hci_dev_lock(hdev);
2937
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002938 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002939 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2940 MGMT_STATUS_NOT_POWERED, &rp,
2941 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002942 goto unlock;
2943 }
2944
Johan Hedberge0b2b272014-02-18 17:14:31 +02002945 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002946 /* If disconnection is requested, then look up the
2947 * connection. If the remote device is connected, it
2948 * will be later used to terminate the link.
2949 *
2950 * Setting it to NULL explicitly will cause no
2951 * termination of the link.
2952 */
2953 if (cp->disconnect)
2954 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2955 &cp->addr.bdaddr);
2956 else
2957 conn = NULL;
2958
Johan Hedberg124f6e32012-02-09 13:50:12 +02002959 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002960 } else {
2961 u8 addr_type;
2962
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002963 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2964 &cp->addr.bdaddr);
2965 if (conn) {
2966 /* Defer clearing up the connection parameters
2967 * until closing to give a chance of keeping
2968 * them if a repairing happens.
2969 */
2970 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2971
2972 /* If disconnection is not requested, then
2973 * clear the connection variable so that the
2974 * link is not terminated.
2975 */
2976 if (!cp->disconnect)
2977 conn = NULL;
2978 }
2979
Johan Hedberge0b2b272014-02-18 17:14:31 +02002980 if (cp->addr.type == BDADDR_LE_PUBLIC)
2981 addr_type = ADDR_LE_DEV_PUBLIC;
2982 else
2983 addr_type = ADDR_LE_DEV_RANDOM;
2984
Johan Hedberga7ec7332014-02-18 17:14:35 +02002985 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2986
Johan Hedberge0b2b272014-02-18 17:14:31 +02002987 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2988 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002989
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002990 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002991 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2992 MGMT_STATUS_NOT_PAIRED, &rp,
2993 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002994 goto unlock;
2995 }
2996
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002997 /* If the connection variable is set, then termination of the
2998 * link is requested.
2999 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02003000 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003001 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3002 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003003 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003004 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003005 }
3006
Johan Hedberg124f6e32012-02-09 13:50:12 +02003007 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003008 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003009 if (!cmd) {
3010 err = -ENOMEM;
3011 goto unlock;
3012 }
3013
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003014 cmd->cmd_complete = addr_cmd_complete;
3015
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003016 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003017 dc.reason = 0x13; /* Remote User Terminated Connection */
3018 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3019 if (err < 0)
3020 mgmt_pending_remove(cmd);
3021
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003022unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003023 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003024 return err;
3025}
3026
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003027static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003028 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003029{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003030 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003031 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003032 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003033 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003034 int err;
3035
3036 BT_DBG("");
3037
Johan Hedberg06a63b12013-01-20 14:27:21 +02003038 memset(&rp, 0, sizeof(rp));
3039 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3040 rp.addr.type = cp->addr.type;
3041
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003042 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003043 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3044 MGMT_STATUS_INVALID_PARAMS,
3045 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003046
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003047 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003048
3049 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003050 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3051 MGMT_STATUS_NOT_POWERED, &rp,
3052 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003053 goto failed;
3054 }
3055
Johan Hedberg333ae952015-03-17 13:48:47 +02003056 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003057 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3058 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003059 goto failed;
3060 }
3061
Andre Guedes591f47f2012-04-24 21:02:49 -03003062 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003063 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3064 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003065 else
3066 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003067
Vishal Agarwalf9607272012-06-13 05:32:43 +05303068 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003069 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3070 MGMT_STATUS_NOT_CONNECTED, &rp,
3071 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003072 goto failed;
3073 }
3074
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003075 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003076 if (!cmd) {
3077 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003078 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003079 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003080
Johan Hedbergf5818c22014-12-05 13:36:02 +02003081 cmd->cmd_complete = generic_cmd_complete;
3082
Johan Hedberge3f2f922014-08-18 20:33:33 +03003083 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003084 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003085 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003086
3087failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003088 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003089 return err;
3090}
3091
Andre Guedes57c14772012-04-24 21:02:50 -03003092static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003093{
3094 switch (link_type) {
3095 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003096 switch (addr_type) {
3097 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003098 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003099
Johan Hedberg48264f02011-11-09 13:58:58 +02003100 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003101 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003102 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003103 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003104
Johan Hedberg4c659c32011-11-07 23:13:39 +02003105 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003106 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003107 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003108 }
3109}
3110
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003111static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3112 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003113{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003114 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003115 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003116 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003117 int err;
3118 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003119
3120 BT_DBG("");
3121
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003122 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003123
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003124 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003125 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3126 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003127 goto unlock;
3128 }
3129
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003130 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003131 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3132 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003133 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003134 }
3135
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003136 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003137 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003138 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003139 err = -ENOMEM;
3140 goto unlock;
3141 }
3142
Johan Hedberg2784eb42011-01-21 13:56:35 +02003143 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003144 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003145 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3146 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003147 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003148 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003149 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003150 continue;
3151 i++;
3152 }
3153
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003154 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003155
Johan Hedberg4c659c32011-11-07 23:13:39 +02003156 /* Recalculate length in case of filtered SCO connections, etc */
3157 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003158
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003159 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3160 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003161
Johan Hedberga38528f2011-01-22 06:46:43 +02003162 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003163
3164unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003165 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003166 return err;
3167}
3168
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003169static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003170 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003171{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003172 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003173 int err;
3174
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003175 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003176 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003177 if (!cmd)
3178 return -ENOMEM;
3179
Johan Hedbergd8457692012-02-17 14:24:57 +02003180 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003181 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003182 if (err < 0)
3183 mgmt_pending_remove(cmd);
3184
3185 return err;
3186}
3187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003188static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003189 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003190{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003191 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003192 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003193 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003194 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003195 int err;
3196
3197 BT_DBG("");
3198
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003199 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003200
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003201 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003202 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3203 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003204 goto failed;
3205 }
3206
Johan Hedbergd8457692012-02-17 14:24:57 +02003207 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003208 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003209 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3210 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003211 goto failed;
3212 }
3213
3214 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003215 struct mgmt_cp_pin_code_neg_reply ncp;
3216
3217 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003218
3219 BT_ERR("PIN code is not 16 bytes long");
3220
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003221 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003222 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003223 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3224 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003225
3226 goto failed;
3227 }
3228
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003229 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003230 if (!cmd) {
3231 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003232 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003233 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003234
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003235 cmd->cmd_complete = addr_cmd_complete;
3236
Johan Hedbergd8457692012-02-17 14:24:57 +02003237 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003238 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003239 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003240
3241 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3242 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003243 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003244
3245failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003246 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003247 return err;
3248}
3249
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003250static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3251 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003252{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003253 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003254
3255 BT_DBG("");
3256
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003257 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003258 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3259 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003260
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003261 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003262
3263 hdev->io_capability = cp->io_capability;
3264
3265 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003266 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003267
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003268 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003269
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003270 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3271 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003272}
3273
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003274static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003275{
3276 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003277 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003278
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003279 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003280 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3281 continue;
3282
Johan Hedberge9a416b2011-02-19 12:05:56 -03003283 if (cmd->user_data != conn)
3284 continue;
3285
3286 return cmd;
3287 }
3288
3289 return NULL;
3290}
3291
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003292static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003293{
3294 struct mgmt_rp_pair_device rp;
3295 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003296 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003297
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003298 bacpy(&rp.addr.bdaddr, &conn->dst);
3299 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003300
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003301 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3302 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003303
3304 /* So we don't get further callbacks for this connection */
3305 conn->connect_cfm_cb = NULL;
3306 conn->security_cfm_cb = NULL;
3307 conn->disconn_cfm_cb = NULL;
3308
David Herrmann76a68ba2013-04-06 20:28:37 +02003309 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003310
3311 /* The device is paired so there is no need to remove
3312 * its connection parameters anymore.
3313 */
3314 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003315
3316 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003317
3318 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003319}
3320
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003321void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3322{
3323 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003324 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003325
3326 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003327 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003328 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003329 mgmt_pending_remove(cmd);
3330 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003331}
3332
Johan Hedberge9a416b2011-02-19 12:05:56 -03003333static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3334{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003335 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003336
3337 BT_DBG("status %u", status);
3338
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003339 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003340 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003341 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003342 return;
3343 }
3344
3345 cmd->cmd_complete(cmd, mgmt_status(status));
3346 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003347}
3348
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003349static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303350{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003351 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303352
3353 BT_DBG("status %u", status);
3354
3355 if (!status)
3356 return;
3357
3358 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003359 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303360 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003361 return;
3362 }
3363
3364 cmd->cmd_complete(cmd, mgmt_status(status));
3365 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303366}
3367
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003368static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003369 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003370{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003371 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003372 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003373 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003374 u8 sec_level, auth_type;
3375 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003376 int err;
3377
3378 BT_DBG("");
3379
Szymon Jancf950a30e2013-01-18 12:48:07 +01003380 memset(&rp, 0, sizeof(rp));
3381 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3382 rp.addr.type = cp->addr.type;
3383
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003384 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003385 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3386 MGMT_STATUS_INVALID_PARAMS,
3387 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003388
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003389 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003390 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3391 MGMT_STATUS_INVALID_PARAMS,
3392 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003393
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003394 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003395
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003396 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003397 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3398 MGMT_STATUS_NOT_POWERED, &rp,
3399 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003400 goto unlock;
3401 }
3402
Johan Hedberg55e76b32015-03-10 22:34:40 +02003403 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3404 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3405 MGMT_STATUS_ALREADY_PAIRED, &rp,
3406 sizeof(rp));
3407 goto unlock;
3408 }
3409
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003410 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003411 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003412
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003413 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003414 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3415 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003416 } else {
3417 u8 addr_type;
3418
3419 /* Convert from L2CAP channel address type to HCI address type
3420 */
3421 if (cp->addr.type == BDADDR_LE_PUBLIC)
3422 addr_type = ADDR_LE_DEV_PUBLIC;
3423 else
3424 addr_type = ADDR_LE_DEV_RANDOM;
3425
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003426 /* When pairing a new device, it is expected to remember
3427 * this device for future connections. Adding the connection
3428 * parameter information ahead of time allows tracking
3429 * of the slave preferred values and will speed up any
3430 * further connection establishment.
3431 *
3432 * If connection parameters already exist, then they
3433 * will be kept and this function does nothing.
3434 */
3435 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3436
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003437 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003438 sec_level, HCI_LE_CONN_TIMEOUT,
3439 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003440 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003441
Ville Tervo30e76272011-02-22 16:10:53 -03003442 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003443 int status;
3444
3445 if (PTR_ERR(conn) == -EBUSY)
3446 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003447 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3448 status = MGMT_STATUS_NOT_SUPPORTED;
3449 else if (PTR_ERR(conn) == -ECONNREFUSED)
3450 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003451 else
3452 status = MGMT_STATUS_CONNECT_FAILED;
3453
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003454 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3455 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003456 goto unlock;
3457 }
3458
3459 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003460 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003461 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3462 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003463 goto unlock;
3464 }
3465
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003466 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003467 if (!cmd) {
3468 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003469 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003470 goto unlock;
3471 }
3472
Johan Hedberg04ab2742014-12-05 13:36:04 +02003473 cmd->cmd_complete = pairing_complete;
3474
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003475 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003476 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003477 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003478 conn->security_cfm_cb = pairing_complete_cb;
3479 conn->disconn_cfm_cb = pairing_complete_cb;
3480 } else {
3481 conn->connect_cfm_cb = le_pairing_complete_cb;
3482 conn->security_cfm_cb = le_pairing_complete_cb;
3483 conn->disconn_cfm_cb = le_pairing_complete_cb;
3484 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003485
Johan Hedberge9a416b2011-02-19 12:05:56 -03003486 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003487 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003488
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003489 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003490 hci_conn_security(conn, sec_level, auth_type, true)) {
3491 cmd->cmd_complete(cmd, 0);
3492 mgmt_pending_remove(cmd);
3493 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003494
3495 err = 0;
3496
3497unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003498 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003499 return err;
3500}
3501
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3503 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003504{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003505 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003506 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003507 struct hci_conn *conn;
3508 int err;
3509
3510 BT_DBG("");
3511
Johan Hedberg28424702012-02-02 04:02:29 +02003512 hci_dev_lock(hdev);
3513
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003514 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003515 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3516 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003517 goto unlock;
3518 }
3519
Johan Hedberg333ae952015-03-17 13:48:47 +02003520 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003521 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003522 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3523 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003524 goto unlock;
3525 }
3526
3527 conn = cmd->user_data;
3528
3529 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003530 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3531 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003532 goto unlock;
3533 }
3534
Johan Hedberga511b352014-12-11 21:45:45 +02003535 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3536 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003537
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003538 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3539 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003540unlock:
3541 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003542 return err;
3543}
3544
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003545static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003546 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003547 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003548{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003549 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003550 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003551 int err;
3552
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003553 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003554
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003555 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003556 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3557 MGMT_STATUS_NOT_POWERED, addr,
3558 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003559 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003560 }
3561
Johan Hedberg1707c602013-03-15 17:07:15 -05003562 if (addr->type == BDADDR_BREDR)
3563 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003564 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003565 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003566
Johan Hedberg272d90d2012-02-09 15:26:12 +02003567 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003568 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3569 MGMT_STATUS_NOT_CONNECTED, addr,
3570 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003571 goto done;
3572 }
3573
Johan Hedberg1707c602013-03-15 17:07:15 -05003574 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003575 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003576 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003577 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3578 MGMT_STATUS_SUCCESS, addr,
3579 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003580 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003581 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3582 MGMT_STATUS_FAILED, addr,
3583 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003584
Brian Gix47c15e22011-11-16 13:53:14 -08003585 goto done;
3586 }
3587
Johan Hedberg1707c602013-03-15 17:07:15 -05003588 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003589 if (!cmd) {
3590 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003591 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003592 }
3593
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003594 cmd->cmd_complete = addr_cmd_complete;
3595
Brian Gix0df4c182011-11-16 13:53:13 -08003596 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003597 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3598 struct hci_cp_user_passkey_reply cp;
3599
Johan Hedberg1707c602013-03-15 17:07:15 -05003600 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003601 cp.passkey = passkey;
3602 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3603 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003604 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3605 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003606
Johan Hedberga664b5b2011-02-19 12:06:02 -03003607 if (err < 0)
3608 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003609
Brian Gix0df4c182011-11-16 13:53:13 -08003610done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003611 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003612 return err;
3613}
3614
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303615static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3616 void *data, u16 len)
3617{
3618 struct mgmt_cp_pin_code_neg_reply *cp = data;
3619
3620 BT_DBG("");
3621
Johan Hedberg1707c602013-03-15 17:07:15 -05003622 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303623 MGMT_OP_PIN_CODE_NEG_REPLY,
3624 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3625}
3626
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003627static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3628 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003629{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003630 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003631
3632 BT_DBG("");
3633
3634 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003635 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3636 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003637
Johan Hedberg1707c602013-03-15 17:07:15 -05003638 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003639 MGMT_OP_USER_CONFIRM_REPLY,
3640 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003641}
3642
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003643static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003644 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003645{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003646 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003647
3648 BT_DBG("");
3649
Johan Hedberg1707c602013-03-15 17:07:15 -05003650 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003651 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3652 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003653}
3654
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003655static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3656 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003657{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003658 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003659
3660 BT_DBG("");
3661
Johan Hedberg1707c602013-03-15 17:07:15 -05003662 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003663 MGMT_OP_USER_PASSKEY_REPLY,
3664 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003665}
3666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003667static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003668 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003669{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003670 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003671
3672 BT_DBG("");
3673
Johan Hedberg1707c602013-03-15 17:07:15 -05003674 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003675 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3676 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003677}
3678
Johan Hedberg13928972013-03-15 17:07:00 -05003679static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003680{
Johan Hedberg13928972013-03-15 17:07:00 -05003681 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003682 struct hci_cp_write_local_name cp;
3683
Johan Hedberg13928972013-03-15 17:07:00 -05003684 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003685
Johan Hedberg890ea892013-03-15 17:06:52 -05003686 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003687}
3688
Marcel Holtmann1904a852015-01-11 13:50:44 -08003689static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003690{
3691 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003692 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003693
3694 BT_DBG("status 0x%02x", status);
3695
3696 hci_dev_lock(hdev);
3697
Johan Hedberg333ae952015-03-17 13:48:47 +02003698 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003699 if (!cmd)
3700 goto unlock;
3701
3702 cp = cmd->param;
3703
3704 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003705 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3706 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003707 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003708 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3709 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003710
3711 mgmt_pending_remove(cmd);
3712
3713unlock:
3714 hci_dev_unlock(hdev);
3715}
3716
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003717static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003718 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003719{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003720 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003721 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003722 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003723 int err;
3724
3725 BT_DBG("");
3726
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003727 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003728
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003729 /* If the old values are the same as the new ones just return a
3730 * direct command complete event.
3731 */
3732 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3733 !memcmp(hdev->short_name, cp->short_name,
3734 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003735 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3736 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003737 goto failed;
3738 }
3739
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003740 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003741
Johan Hedbergb5235a62012-02-21 14:32:24 +02003742 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003743 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003744
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003745 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3746 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003747 if (err < 0)
3748 goto failed;
3749
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003750 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3751 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003752
Johan Hedbergb5235a62012-02-21 14:32:24 +02003753 goto failed;
3754 }
3755
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003756 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003757 if (!cmd) {
3758 err = -ENOMEM;
3759 goto failed;
3760 }
3761
Johan Hedberg13928972013-03-15 17:07:00 -05003762 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3763
Johan Hedberg890ea892013-03-15 17:06:52 -05003764 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003765
3766 if (lmp_bredr_capable(hdev)) {
3767 update_name(&req);
3768 update_eir(&req);
3769 }
3770
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003771 /* The name is stored in the scan response data and so
3772 * no need to udpate the advertising data here.
3773 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003774 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003775 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003776
Johan Hedberg13928972013-03-15 17:07:00 -05003777 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003778 if (err < 0)
3779 mgmt_pending_remove(cmd);
3780
3781failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003782 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003783 return err;
3784}
3785
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003786static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3787 u16 opcode, struct sk_buff *skb)
3788{
3789 struct mgmt_rp_read_local_oob_data mgmt_rp;
3790 size_t rp_size = sizeof(mgmt_rp);
3791 struct mgmt_pending_cmd *cmd;
3792
3793 BT_DBG("%s status %u", hdev->name, status);
3794
3795 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3796 if (!cmd)
3797 return;
3798
3799 if (status || !skb) {
3800 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3801 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3802 goto remove;
3803 }
3804
3805 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3806
3807 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3808 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3809
3810 if (skb->len < sizeof(*rp)) {
3811 mgmt_cmd_status(cmd->sk, hdev->id,
3812 MGMT_OP_READ_LOCAL_OOB_DATA,
3813 MGMT_STATUS_FAILED);
3814 goto remove;
3815 }
3816
3817 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3818 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3819
3820 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3821 } else {
3822 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3823
3824 if (skb->len < sizeof(*rp)) {
3825 mgmt_cmd_status(cmd->sk, hdev->id,
3826 MGMT_OP_READ_LOCAL_OOB_DATA,
3827 MGMT_STATUS_FAILED);
3828 goto remove;
3829 }
3830
3831 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3832 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3833
3834 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3835 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3836 }
3837
3838 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3839 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3840
3841remove:
3842 mgmt_pending_remove(cmd);
3843}
3844
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003845static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003846 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003847{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003848 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003849 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003850 int err;
3851
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003852 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003853
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003854 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003855
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003856 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003857 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3858 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003859 goto unlock;
3860 }
3861
Andre Guedes9a1a1992012-07-24 15:03:48 -03003862 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003863 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3864 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003865 goto unlock;
3866 }
3867
Johan Hedberg333ae952015-03-17 13:48:47 +02003868 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003869 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3870 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003871 goto unlock;
3872 }
3873
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003874 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003875 if (!cmd) {
3876 err = -ENOMEM;
3877 goto unlock;
3878 }
3879
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003880 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003881
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003882 if (bredr_sc_enabled(hdev))
3883 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3884 else
3885 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3886
3887 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003888 if (err < 0)
3889 mgmt_pending_remove(cmd);
3890
3891unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003892 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003893 return err;
3894}
3895
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003896static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003897 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003898{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003899 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003900 int err;
3901
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003902 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003903
Johan Hedberg5d57e792015-01-23 10:10:38 +02003904 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003905 return mgmt_cmd_complete(sk, hdev->id,
3906 MGMT_OP_ADD_REMOTE_OOB_DATA,
3907 MGMT_STATUS_INVALID_PARAMS,
3908 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003909
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003910 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003911
Marcel Holtmannec109112014-01-10 02:07:30 -08003912 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3913 struct mgmt_cp_add_remote_oob_data *cp = data;
3914 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003915
Johan Hedbergc19a4952014-11-17 20:52:19 +02003916 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003917 err = mgmt_cmd_complete(sk, hdev->id,
3918 MGMT_OP_ADD_REMOTE_OOB_DATA,
3919 MGMT_STATUS_INVALID_PARAMS,
3920 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003921 goto unlock;
3922 }
3923
Marcel Holtmannec109112014-01-10 02:07:30 -08003924 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003925 cp->addr.type, cp->hash,
3926 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003927 if (err < 0)
3928 status = MGMT_STATUS_FAILED;
3929 else
3930 status = MGMT_STATUS_SUCCESS;
3931
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003932 err = mgmt_cmd_complete(sk, hdev->id,
3933 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3934 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003935 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3936 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003937 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003938 u8 status;
3939
Johan Hedberg86df9202014-10-26 20:52:27 +01003940 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003941 /* Enforce zero-valued 192-bit parameters as
3942 * long as legacy SMP OOB isn't implemented.
3943 */
3944 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3945 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003946 err = mgmt_cmd_complete(sk, hdev->id,
3947 MGMT_OP_ADD_REMOTE_OOB_DATA,
3948 MGMT_STATUS_INVALID_PARAMS,
3949 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003950 goto unlock;
3951 }
3952
Johan Hedberg86df9202014-10-26 20:52:27 +01003953 rand192 = NULL;
3954 hash192 = NULL;
3955 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003956 /* In case one of the P-192 values is set to zero,
3957 * then just disable OOB data for P-192.
3958 */
3959 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3960 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3961 rand192 = NULL;
3962 hash192 = NULL;
3963 } else {
3964 rand192 = cp->rand192;
3965 hash192 = cp->hash192;
3966 }
3967 }
3968
3969 /* In case one of the P-256 values is set to zero, then just
3970 * disable OOB data for P-256.
3971 */
3972 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3973 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3974 rand256 = NULL;
3975 hash256 = NULL;
3976 } else {
3977 rand256 = cp->rand256;
3978 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003979 }
3980
Johan Hedberg81328d52014-10-26 20:33:47 +01003981 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003982 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003983 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003984 if (err < 0)
3985 status = MGMT_STATUS_FAILED;
3986 else
3987 status = MGMT_STATUS_SUCCESS;
3988
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003989 err = mgmt_cmd_complete(sk, hdev->id,
3990 MGMT_OP_ADD_REMOTE_OOB_DATA,
3991 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003992 } else {
3993 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003994 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3995 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003996 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003997
Johan Hedbergc19a4952014-11-17 20:52:19 +02003998unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003999 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004000 return err;
4001}
4002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004003static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004004 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01004005{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004006 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004007 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01004008 int err;
4009
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004010 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01004011
Johan Hedbergc19a4952014-11-17 20:52:19 +02004012 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004013 return mgmt_cmd_complete(sk, hdev->id,
4014 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4015 MGMT_STATUS_INVALID_PARAMS,
4016 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004017
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004018 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004019
Johan Hedbergeedbd582014-11-15 09:34:23 +02004020 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4021 hci_remote_oob_data_clear(hdev);
4022 status = MGMT_STATUS_SUCCESS;
4023 goto done;
4024 }
4025
Johan Hedberg6928a922014-10-26 20:46:09 +01004026 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004027 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004028 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004029 else
Szymon Janca6785be2012-12-13 15:11:21 +01004030 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004031
Johan Hedbergeedbd582014-11-15 09:34:23 +02004032done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004033 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4034 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004035
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004036 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004037 return err;
4038}
4039
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004040static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
4041{
4042 struct hci_dev *hdev = req->hdev;
4043 struct hci_cp_inquiry cp;
4044 /* General inquiry access code (GIAC) */
4045 u8 lap[3] = { 0x33, 0x8b, 0x9e };
4046
4047 *status = mgmt_bredr_support(hdev);
4048 if (*status)
4049 return false;
4050
4051 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
4052 *status = MGMT_STATUS_BUSY;
4053 return false;
4054 }
4055
4056 hci_inquiry_cache_flush(hdev);
4057
4058 memset(&cp, 0, sizeof(cp));
4059 memcpy(&cp.lap, lap, sizeof(cp.lap));
4060 cp.length = DISCOV_BREDR_INQUIRY_LEN;
4061
4062 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4063
4064 return true;
4065}
4066
4067static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004068{
Marcel Holtmann80190442014-12-04 11:36:36 +01004069 struct hci_dev *hdev = req->hdev;
4070 struct hci_cp_le_set_scan_param param_cp;
4071 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004072 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004073 int err;
4074
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004075 *status = mgmt_le_support(hdev);
4076 if (*status)
4077 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004078
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004079 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4080 /* Don't let discovery abort an outgoing connection attempt
4081 * that's using directed advertising.
4082 */
4083 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4084 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004085 return false;
4086 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004087
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004088 disable_advertising(req);
4089 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004090
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004091 /* If controller is scanning, it means the background scanning is
4092 * running. Thus, we should temporarily stop it in order to set the
4093 * discovery scanning parameters.
4094 */
4095 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4096 hci_req_add_le_scan_disable(req);
4097
4098 /* All active scans will be done with either a resolvable private
4099 * address (when privacy feature has been enabled) or non-resolvable
4100 * private address.
4101 */
4102 err = hci_update_random_address(req, true, &own_addr_type);
4103 if (err < 0) {
4104 *status = MGMT_STATUS_FAILED;
4105 return false;
4106 }
4107
4108 memset(&param_cp, 0, sizeof(param_cp));
4109 param_cp.type = LE_SCAN_ACTIVE;
4110 param_cp.interval = cpu_to_le16(interval);
4111 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4112 param_cp.own_address_type = own_addr_type;
4113
4114 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4115 &param_cp);
4116
4117 memset(&enable_cp, 0, sizeof(enable_cp));
4118 enable_cp.enable = LE_SCAN_ENABLE;
4119 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4120
4121 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4122 &enable_cp);
4123
4124 return true;
4125}
4126
4127static bool trigger_discovery(struct hci_request *req, u8 *status)
4128{
4129 struct hci_dev *hdev = req->hdev;
4130
4131 switch (hdev->discovery.type) {
4132 case DISCOV_TYPE_BREDR:
4133 if (!trigger_bredr_inquiry(req, status))
4134 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004135 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004136
Marcel Holtmann80190442014-12-04 11:36:36 +01004137 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004138 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4139 &hdev->quirks)) {
4140 /* During simultaneous discovery, we double LE scan
4141 * interval. We must leave some time for the controller
4142 * to do BR/EDR inquiry.
4143 */
4144 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4145 status))
4146 return false;
4147
4148 if (!trigger_bredr_inquiry(req, status))
4149 return false;
4150
4151 return true;
4152 }
4153
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004154 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004155 *status = MGMT_STATUS_NOT_SUPPORTED;
4156 return false;
4157 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004158 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004159
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004160 case DISCOV_TYPE_LE:
4161 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004162 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004163 break;
4164
4165 default:
4166 *status = MGMT_STATUS_INVALID_PARAMS;
4167 return false;
4168 }
4169
4170 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004171}
4172
Marcel Holtmann1904a852015-01-11 13:50:44 -08004173static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4174 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004175{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004176 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004177 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004178
Andre Guedes7c307722013-04-30 15:29:28 -03004179 BT_DBG("status %d", status);
4180
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004181 hci_dev_lock(hdev);
4182
Johan Hedberg333ae952015-03-17 13:48:47 +02004183 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004184 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004185 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004186
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004187 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004188 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004189 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004190 }
4191
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004192 if (status) {
4193 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4194 goto unlock;
4195 }
4196
Andre Guedes7c307722013-04-30 15:29:28 -03004197 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004198
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004199 /* If the scan involves LE scan, pick proper timeout to schedule
4200 * hdev->le_scan_disable that will stop it.
4201 */
Andre Guedes7c307722013-04-30 15:29:28 -03004202 switch (hdev->discovery.type) {
4203 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004204 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004205 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004206 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004207 /* When running simultaneous discovery, the LE scanning time
4208 * should occupy the whole discovery time sine BR/EDR inquiry
4209 * and LE scanning are scheduled by the controller.
4210 *
4211 * For interleaving discovery in comparison, BR/EDR inquiry
4212 * and LE scanning are done sequentially with separate
4213 * timeouts.
4214 */
4215 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4216 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4217 else
4218 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004219 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004220 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004221 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004222 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004223 default:
4224 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004225 timeout = 0;
4226 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004227 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004228
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004229 if (timeout) {
4230 /* When service discovery is used and the controller has
4231 * a strict duplicate filter, it is important to remember
4232 * the start and duration of the scan. This is required
4233 * for restarting scanning during the discovery phase.
4234 */
4235 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4236 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004237 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004238 hdev->discovery.scan_start = jiffies;
4239 hdev->discovery.scan_duration = timeout;
4240 }
4241
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004242 queue_delayed_work(hdev->workqueue,
4243 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004244 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004245
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004246unlock:
4247 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004248}
4249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004250static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004251 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004252{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004253 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004254 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004255 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004256 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004257 int err;
4258
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004259 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004260
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004261 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004262
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004263 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004264 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4265 MGMT_STATUS_NOT_POWERED,
4266 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004267 goto failed;
4268 }
4269
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004270 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004271 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004272 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4273 MGMT_STATUS_BUSY, &cp->type,
4274 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004275 goto failed;
4276 }
4277
Johan Hedberg2922a942014-12-05 13:36:06 +02004278 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004279 if (!cmd) {
4280 err = -ENOMEM;
4281 goto failed;
4282 }
4283
Johan Hedberg2922a942014-12-05 13:36:06 +02004284 cmd->cmd_complete = generic_cmd_complete;
4285
Marcel Holtmann22078802014-12-05 11:45:22 +01004286 /* Clear the discovery filter first to free any previously
4287 * allocated memory for the UUID list.
4288 */
4289 hci_discovery_filter_clear(hdev);
4290
Andre Guedes4aab14e2012-02-17 20:39:36 -03004291 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004292 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004293
Andre Guedes7c307722013-04-30 15:29:28 -03004294 hci_req_init(&req, hdev);
4295
Marcel Holtmann80190442014-12-04 11:36:36 +01004296 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004297 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4298 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004299 mgmt_pending_remove(cmd);
4300 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004301 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004302
Andre Guedes7c307722013-04-30 15:29:28 -03004303 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004304 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004305 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004306 goto failed;
4307 }
4308
4309 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004310
4311failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004312 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004313 return err;
4314}
4315
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004316static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4317 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004318{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004319 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4320 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004321}
4322
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004323static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4324 void *data, u16 len)
4325{
4326 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004327 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004328 struct hci_request req;
4329 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4330 u16 uuid_count, expected_len;
4331 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004332 int err;
4333
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004334 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004335
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004336 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004337
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004338 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004339 err = mgmt_cmd_complete(sk, hdev->id,
4340 MGMT_OP_START_SERVICE_DISCOVERY,
4341 MGMT_STATUS_NOT_POWERED,
4342 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004343 goto failed;
4344 }
4345
4346 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004347 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004348 err = mgmt_cmd_complete(sk, hdev->id,
4349 MGMT_OP_START_SERVICE_DISCOVERY,
4350 MGMT_STATUS_BUSY, &cp->type,
4351 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004352 goto failed;
4353 }
4354
4355 uuid_count = __le16_to_cpu(cp->uuid_count);
4356 if (uuid_count > max_uuid_count) {
4357 BT_ERR("service_discovery: too big uuid_count value %u",
4358 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004359 err = mgmt_cmd_complete(sk, hdev->id,
4360 MGMT_OP_START_SERVICE_DISCOVERY,
4361 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4362 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004363 goto failed;
4364 }
4365
4366 expected_len = sizeof(*cp) + uuid_count * 16;
4367 if (expected_len != len) {
4368 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4369 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004370 err = mgmt_cmd_complete(sk, hdev->id,
4371 MGMT_OP_START_SERVICE_DISCOVERY,
4372 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4373 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004374 goto failed;
4375 }
4376
4377 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004378 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004379 if (!cmd) {
4380 err = -ENOMEM;
4381 goto failed;
4382 }
4383
Johan Hedberg2922a942014-12-05 13:36:06 +02004384 cmd->cmd_complete = service_discovery_cmd_complete;
4385
Marcel Holtmann22078802014-12-05 11:45:22 +01004386 /* Clear the discovery filter first to free any previously
4387 * allocated memory for the UUID list.
4388 */
4389 hci_discovery_filter_clear(hdev);
4390
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004391 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004392 hdev->discovery.type = cp->type;
4393 hdev->discovery.rssi = cp->rssi;
4394 hdev->discovery.uuid_count = uuid_count;
4395
4396 if (uuid_count > 0) {
4397 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4398 GFP_KERNEL);
4399 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004400 err = mgmt_cmd_complete(sk, hdev->id,
4401 MGMT_OP_START_SERVICE_DISCOVERY,
4402 MGMT_STATUS_FAILED,
4403 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004404 mgmt_pending_remove(cmd);
4405 goto failed;
4406 }
4407 }
4408
4409 hci_req_init(&req, hdev);
4410
4411 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004412 err = mgmt_cmd_complete(sk, hdev->id,
4413 MGMT_OP_START_SERVICE_DISCOVERY,
4414 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004415 mgmt_pending_remove(cmd);
4416 goto failed;
4417 }
4418
4419 err = hci_req_run(&req, start_discovery_complete);
4420 if (err < 0) {
4421 mgmt_pending_remove(cmd);
4422 goto failed;
4423 }
4424
4425 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4426
4427failed:
4428 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004429 return err;
4430}
4431
Marcel Holtmann1904a852015-01-11 13:50:44 -08004432static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004433{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004434 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004435
Andre Guedes0e05bba2013-04-30 15:29:33 -03004436 BT_DBG("status %d", status);
4437
4438 hci_dev_lock(hdev);
4439
Johan Hedberg333ae952015-03-17 13:48:47 +02004440 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004441 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004442 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004443 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004444 }
4445
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004446 if (!status)
4447 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004448
Andre Guedes0e05bba2013-04-30 15:29:33 -03004449 hci_dev_unlock(hdev);
4450}
4451
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004452static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004453 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004454{
Johan Hedbergd9306502012-02-20 23:25:18 +02004455 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004456 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004457 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004458 int err;
4459
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004460 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004461
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004462 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004463
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004464 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004465 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4466 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4467 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004468 goto unlock;
4469 }
4470
4471 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004472 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4473 MGMT_STATUS_INVALID_PARAMS,
4474 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004475 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004476 }
4477
Johan Hedberg2922a942014-12-05 13:36:06 +02004478 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004479 if (!cmd) {
4480 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004481 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004482 }
4483
Johan Hedberg2922a942014-12-05 13:36:06 +02004484 cmd->cmd_complete = generic_cmd_complete;
4485
Andre Guedes0e05bba2013-04-30 15:29:33 -03004486 hci_req_init(&req, hdev);
4487
Johan Hedberg21a60d32014-06-10 14:05:58 +03004488 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004489
Johan Hedberg21a60d32014-06-10 14:05:58 +03004490 err = hci_req_run(&req, stop_discovery_complete);
4491 if (!err) {
4492 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004493 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004494 }
4495
Johan Hedberg21a60d32014-06-10 14:05:58 +03004496 mgmt_pending_remove(cmd);
4497
4498 /* If no HCI commands were sent we're done */
4499 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004500 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4501 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004502 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4503 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004504
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004505unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004506 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004507 return err;
4508}
4509
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004510static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004511 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004512{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004513 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004514 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004515 int err;
4516
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004517 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004518
Johan Hedberg561aafb2012-01-04 13:31:59 +02004519 hci_dev_lock(hdev);
4520
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004521 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004522 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4523 MGMT_STATUS_FAILED, &cp->addr,
4524 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004525 goto failed;
4526 }
4527
Johan Hedberga198e7b2012-02-17 14:27:06 +02004528 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004529 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004530 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4531 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4532 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004533 goto failed;
4534 }
4535
4536 if (cp->name_known) {
4537 e->name_state = NAME_KNOWN;
4538 list_del(&e->list);
4539 } else {
4540 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004541 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004542 }
4543
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004544 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4545 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004546
4547failed:
4548 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004549 return err;
4550}
4551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004552static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004553 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004554{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004555 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004556 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004557 int err;
4558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004559 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004560
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004561 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004562 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4563 MGMT_STATUS_INVALID_PARAMS,
4564 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004565
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004566 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004567
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004568 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4569 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004570 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004571 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004572 goto done;
4573 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004574
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004575 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4576 sk);
4577 status = MGMT_STATUS_SUCCESS;
4578
4579done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004580 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4581 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004582
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004583 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004584
4585 return err;
4586}
4587
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004588static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004589 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004590{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004591 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004592 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004593 int err;
4594
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004595 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004596
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004597 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004598 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4599 MGMT_STATUS_INVALID_PARAMS,
4600 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004601
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004602 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004603
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004604 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4605 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004606 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004607 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004608 goto done;
4609 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004610
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004611 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4612 sk);
4613 status = MGMT_STATUS_SUCCESS;
4614
4615done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004616 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4617 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004618
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004619 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004620
4621 return err;
4622}
4623
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004624static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4625 u16 len)
4626{
4627 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004628 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004629 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004630 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004631
4632 BT_DBG("%s", hdev->name);
4633
Szymon Jancc72d4b82012-03-16 16:02:57 +01004634 source = __le16_to_cpu(cp->source);
4635
4636 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004637 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4638 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004639
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004640 hci_dev_lock(hdev);
4641
Szymon Jancc72d4b82012-03-16 16:02:57 +01004642 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004643 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4644 hdev->devid_product = __le16_to_cpu(cp->product);
4645 hdev->devid_version = __le16_to_cpu(cp->version);
4646
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004647 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4648 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004649
Johan Hedberg890ea892013-03-15 17:06:52 -05004650 hci_req_init(&req, hdev);
4651 update_eir(&req);
4652 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004653
4654 hci_dev_unlock(hdev);
4655
4656 return err;
4657}
4658
Arman Uguray24b4f382015-03-23 15:57:12 -07004659static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4660 u16 opcode)
4661{
4662 BT_DBG("status %d", status);
4663}
4664
Marcel Holtmann1904a852015-01-11 13:50:44 -08004665static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4666 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004667{
4668 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004669 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004670
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304671 hci_dev_lock(hdev);
4672
Johan Hedberg4375f102013-09-25 13:26:10 +03004673 if (status) {
4674 u8 mgmt_err = mgmt_status(status);
4675
4676 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4677 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304678 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004679 }
4680
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004681 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004682 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004683 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004684 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004685
Johan Hedberg4375f102013-09-25 13:26:10 +03004686 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4687 &match);
4688
4689 new_settings(hdev, match.sk);
4690
4691 if (match.sk)
4692 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304693
Arman Uguray24b4f382015-03-23 15:57:12 -07004694 /* If "Set Advertising" was just disabled and instance advertising was
4695 * set up earlier, then enable the advertising instance.
4696 */
4697 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4698 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4699 goto unlock;
4700
4701 hci_req_init(&req, hdev);
4702
4703 update_adv_data(&req);
4704 enable_advertising(&req);
4705
4706 if (hci_req_run(&req, enable_advertising_instance) < 0)
4707 BT_ERR("Failed to re-configure advertising");
4708
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304709unlock:
4710 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004711}
4712
Marcel Holtmann21b51872013-10-10 09:47:53 -07004713static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4714 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004715{
4716 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004717 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004718 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004719 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004720 int err;
4721
4722 BT_DBG("request for %s", hdev->name);
4723
Johan Hedberge6fe7982013-10-02 15:45:22 +03004724 status = mgmt_le_support(hdev);
4725 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004726 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4727 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004728
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004729 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004730 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4731 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004732
4733 hci_dev_lock(hdev);
4734
4735 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004736
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004737 /* The following conditions are ones which mean that we should
4738 * not do any HCI communication but directly send a mgmt
4739 * response to user space (after toggling the flag if
4740 * necessary).
4741 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004742 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004743 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4744 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004745 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004746 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004747 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004748 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004749
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004750 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004751 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004752 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004753 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004754 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004755 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004756 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004757 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004758 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004759 }
4760
4761 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4762 if (err < 0)
4763 goto unlock;
4764
4765 if (changed)
4766 err = new_settings(hdev, sk);
4767
4768 goto unlock;
4769 }
4770
Johan Hedberg333ae952015-03-17 13:48:47 +02004771 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4772 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004773 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4774 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004775 goto unlock;
4776 }
4777
4778 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4779 if (!cmd) {
4780 err = -ENOMEM;
4781 goto unlock;
4782 }
4783
4784 hci_req_init(&req, hdev);
4785
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004786 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004787 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004788 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004789 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004790
Arman Uguray24b4f382015-03-23 15:57:12 -07004791 if (val) {
4792 /* Switch to instance "0" for the Set Advertising setting. */
4793 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004794 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004795 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004796 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004797 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004798 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004799
4800 err = hci_req_run(&req, set_advertising_complete);
4801 if (err < 0)
4802 mgmt_pending_remove(cmd);
4803
4804unlock:
4805 hci_dev_unlock(hdev);
4806 return err;
4807}
4808
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004809static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4810 void *data, u16 len)
4811{
4812 struct mgmt_cp_set_static_address *cp = data;
4813 int err;
4814
4815 BT_DBG("%s", hdev->name);
4816
Marcel Holtmann62af4442013-10-02 22:10:32 -07004817 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004818 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4819 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004820
4821 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004822 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4823 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004824
4825 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4826 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004827 return mgmt_cmd_status(sk, hdev->id,
4828 MGMT_OP_SET_STATIC_ADDRESS,
4829 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004830
4831 /* Two most significant bits shall be set */
4832 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004833 return mgmt_cmd_status(sk, hdev->id,
4834 MGMT_OP_SET_STATIC_ADDRESS,
4835 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004836 }
4837
4838 hci_dev_lock(hdev);
4839
4840 bacpy(&hdev->static_addr, &cp->bdaddr);
4841
Marcel Holtmann93690c22015-03-06 10:11:21 -08004842 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4843 if (err < 0)
4844 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004845
Marcel Holtmann93690c22015-03-06 10:11:21 -08004846 err = new_settings(hdev, sk);
4847
4848unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004849 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004850 return err;
4851}
4852
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004853static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4854 void *data, u16 len)
4855{
4856 struct mgmt_cp_set_scan_params *cp = data;
4857 __u16 interval, window;
4858 int err;
4859
4860 BT_DBG("%s", hdev->name);
4861
4862 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004863 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4864 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004865
4866 interval = __le16_to_cpu(cp->interval);
4867
4868 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004869 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4870 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004871
4872 window = __le16_to_cpu(cp->window);
4873
4874 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004875 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4876 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004877
Marcel Holtmann899e1072013-10-14 09:55:32 -07004878 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004879 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4880 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004881
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004882 hci_dev_lock(hdev);
4883
4884 hdev->le_scan_interval = interval;
4885 hdev->le_scan_window = window;
4886
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004887 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4888 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004889
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004890 /* If background scan is running, restart it so new parameters are
4891 * loaded.
4892 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004893 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004894 hdev->discovery.state == DISCOVERY_STOPPED) {
4895 struct hci_request req;
4896
4897 hci_req_init(&req, hdev);
4898
4899 hci_req_add_le_scan_disable(&req);
4900 hci_req_add_le_passive_scan(&req);
4901
4902 hci_req_run(&req, NULL);
4903 }
4904
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004905 hci_dev_unlock(hdev);
4906
4907 return err;
4908}
4909
Marcel Holtmann1904a852015-01-11 13:50:44 -08004910static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4911 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004912{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004913 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004914
4915 BT_DBG("status 0x%02x", status);
4916
4917 hci_dev_lock(hdev);
4918
Johan Hedberg333ae952015-03-17 13:48:47 +02004919 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004920 if (!cmd)
4921 goto unlock;
4922
4923 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004924 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4925 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004926 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004927 struct mgmt_mode *cp = cmd->param;
4928
4929 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004930 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004931 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004932 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004933
Johan Hedberg33e38b32013-03-15 17:07:05 -05004934 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4935 new_settings(hdev, cmd->sk);
4936 }
4937
4938 mgmt_pending_remove(cmd);
4939
4940unlock:
4941 hci_dev_unlock(hdev);
4942}
4943
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004944static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004945 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004946{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004947 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004948 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004949 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004950 int err;
4951
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004952 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004953
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004954 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004955 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004956 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4957 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004958
Johan Hedberga7e80f22013-01-09 16:05:19 +02004959 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004960 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4961 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004962
Antti Julkuf6422ec2011-06-22 13:11:56 +03004963 hci_dev_lock(hdev);
4964
Johan Hedberg333ae952015-03-17 13:48:47 +02004965 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004966 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4967 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004968 goto unlock;
4969 }
4970
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004971 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004972 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4973 hdev);
4974 goto unlock;
4975 }
4976
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004977 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004978 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004979 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4980 hdev);
4981 new_settings(hdev, sk);
4982 goto unlock;
4983 }
4984
Johan Hedberg33e38b32013-03-15 17:07:05 -05004985 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4986 data, len);
4987 if (!cmd) {
4988 err = -ENOMEM;
4989 goto unlock;
4990 }
4991
4992 hci_req_init(&req, hdev);
4993
Johan Hedberg406d7802013-03-15 17:07:09 -05004994 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004995
4996 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004997 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004998 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4999 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005000 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03005001 }
5002
Johan Hedberg33e38b32013-03-15 17:07:05 -05005003unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03005004 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005005
Antti Julkuf6422ec2011-06-22 13:11:56 +03005006 return err;
5007}
5008
Marcel Holtmann1904a852015-01-11 13:50:44 -08005009static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03005010{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005011 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005012
5013 BT_DBG("status 0x%02x", status);
5014
5015 hci_dev_lock(hdev);
5016
Johan Hedberg333ae952015-03-17 13:48:47 +02005017 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005018 if (!cmd)
5019 goto unlock;
5020
5021 if (status) {
5022 u8 mgmt_err = mgmt_status(status);
5023
5024 /* We need to restore the flag if related HCI commands
5025 * failed.
5026 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005027 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005028
Johan Hedberga69e8372015-03-06 21:08:53 +02005029 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005030 } else {
5031 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
5032 new_settings(hdev, cmd->sk);
5033 }
5034
5035 mgmt_pending_remove(cmd);
5036
5037unlock:
5038 hci_dev_unlock(hdev);
5039}
5040
5041static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
5042{
5043 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005044 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005045 struct hci_request req;
5046 int err;
5047
5048 BT_DBG("request for %s", hdev->name);
5049
5050 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005051 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5052 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005053
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005054 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005055 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5056 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005057
5058 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005059 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5060 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005061
5062 hci_dev_lock(hdev);
5063
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005064 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005065 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5066 goto unlock;
5067 }
5068
5069 if (!hdev_is_powered(hdev)) {
5070 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005071 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5072 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5073 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5074 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5075 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005076 }
5077
Marcel Holtmannce05d602015-03-13 02:11:03 -07005078 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005079
5080 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5081 if (err < 0)
5082 goto unlock;
5083
5084 err = new_settings(hdev, sk);
5085 goto unlock;
5086 }
5087
5088 /* Reject disabling when powered on */
5089 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005090 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5091 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005092 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005093 } else {
5094 /* When configuring a dual-mode controller to operate
5095 * with LE only and using a static address, then switching
5096 * BR/EDR back on is not allowed.
5097 *
5098 * Dual-mode controllers shall operate with the public
5099 * address as its identity address for BR/EDR and LE. So
5100 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005101 *
5102 * The same restrictions applies when secure connections
5103 * has been enabled. For BR/EDR this is a controller feature
5104 * while for LE it is a host stack feature. This means that
5105 * switching BR/EDR back on when secure connections has been
5106 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005107 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005108 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005109 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005110 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005111 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5112 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005113 goto unlock;
5114 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005115 }
5116
Johan Hedberg333ae952015-03-17 13:48:47 +02005117 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005118 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5119 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005120 goto unlock;
5121 }
5122
5123 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5124 if (!cmd) {
5125 err = -ENOMEM;
5126 goto unlock;
5127 }
5128
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005129 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005130 * generates the correct flags.
5131 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005132 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005133
5134 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005135
Johan Hedberg432df052014-08-01 11:13:31 +03005136 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005137 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005138
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005139 /* Since only the advertising data flags will change, there
5140 * is no need to update the scan response data.
5141 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005142 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005143
Johan Hedberg0663ca22013-10-02 13:43:14 +03005144 err = hci_req_run(&req, set_bredr_complete);
5145 if (err < 0)
5146 mgmt_pending_remove(cmd);
5147
5148unlock:
5149 hci_dev_unlock(hdev);
5150 return err;
5151}
5152
Johan Hedberga1443f52015-01-23 15:42:46 +02005153static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5154{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005155 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005156 struct mgmt_mode *cp;
5157
5158 BT_DBG("%s status %u", hdev->name, status);
5159
5160 hci_dev_lock(hdev);
5161
Johan Hedberg333ae952015-03-17 13:48:47 +02005162 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005163 if (!cmd)
5164 goto unlock;
5165
5166 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005167 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5168 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005169 goto remove;
5170 }
5171
5172 cp = cmd->param;
5173
5174 switch (cp->val) {
5175 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005176 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5177 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005178 break;
5179 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005180 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005181 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005182 break;
5183 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005184 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5185 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005186 break;
5187 }
5188
5189 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5190 new_settings(hdev, cmd->sk);
5191
5192remove:
5193 mgmt_pending_remove(cmd);
5194unlock:
5195 hci_dev_unlock(hdev);
5196}
5197
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005198static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5199 void *data, u16 len)
5200{
5201 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005202 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005203 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005204 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005205 int err;
5206
5207 BT_DBG("request for %s", hdev->name);
5208
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005209 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005210 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005211 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5212 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005213
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005214 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005215 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005216 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005217 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5218 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005219
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005220 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005221 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005222 MGMT_STATUS_INVALID_PARAMS);
5223
5224 hci_dev_lock(hdev);
5225
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005226 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005227 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005228 bool changed;
5229
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005230 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005231 changed = !hci_dev_test_and_set_flag(hdev,
5232 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005233 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005234 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005235 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005236 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005237 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005238 changed = hci_dev_test_and_clear_flag(hdev,
5239 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005240 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005241 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005242
5243 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5244 if (err < 0)
5245 goto failed;
5246
5247 if (changed)
5248 err = new_settings(hdev, sk);
5249
5250 goto failed;
5251 }
5252
Johan Hedberg333ae952015-03-17 13:48:47 +02005253 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005254 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5255 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005256 goto failed;
5257 }
5258
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005259 val = !!cp->val;
5260
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005261 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5262 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005263 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5264 goto failed;
5265 }
5266
5267 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5268 if (!cmd) {
5269 err = -ENOMEM;
5270 goto failed;
5271 }
5272
Johan Hedberga1443f52015-01-23 15:42:46 +02005273 hci_req_init(&req, hdev);
5274 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5275 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005276 if (err < 0) {
5277 mgmt_pending_remove(cmd);
5278 goto failed;
5279 }
5280
5281failed:
5282 hci_dev_unlock(hdev);
5283 return err;
5284}
5285
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005286static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5287 void *data, u16 len)
5288{
5289 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005290 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005291 int err;
5292
5293 BT_DBG("request for %s", hdev->name);
5294
Johan Hedbergb97109792014-06-24 14:00:28 +03005295 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005296 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5297 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005298
5299 hci_dev_lock(hdev);
5300
5301 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005302 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005303 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005304 changed = hci_dev_test_and_clear_flag(hdev,
5305 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005306
Johan Hedbergb97109792014-06-24 14:00:28 +03005307 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005308 use_changed = !hci_dev_test_and_set_flag(hdev,
5309 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005310 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005311 use_changed = hci_dev_test_and_clear_flag(hdev,
5312 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005313
5314 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005315 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005316 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5317 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5318 sizeof(mode), &mode);
5319 }
5320
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005321 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5322 if (err < 0)
5323 goto unlock;
5324
5325 if (changed)
5326 err = new_settings(hdev, sk);
5327
5328unlock:
5329 hci_dev_unlock(hdev);
5330 return err;
5331}
5332
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005333static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5334 u16 len)
5335{
5336 struct mgmt_cp_set_privacy *cp = cp_data;
5337 bool changed;
5338 int err;
5339
5340 BT_DBG("request for %s", hdev->name);
5341
5342 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005343 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5344 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005345
5346 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005347 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5348 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005349
5350 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005351 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5352 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005353
5354 hci_dev_lock(hdev);
5355
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005356 /* If user space supports this command it is also expected to
5357 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5358 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005359 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005360
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005361 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005362 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005363 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005364 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005365 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005366 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005367 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005368 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005369 }
5370
5371 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5372 if (err < 0)
5373 goto unlock;
5374
5375 if (changed)
5376 err = new_settings(hdev, sk);
5377
5378unlock:
5379 hci_dev_unlock(hdev);
5380 return err;
5381}
5382
Johan Hedberg41edf162014-02-18 10:19:35 +02005383static bool irk_is_valid(struct mgmt_irk_info *irk)
5384{
5385 switch (irk->addr.type) {
5386 case BDADDR_LE_PUBLIC:
5387 return true;
5388
5389 case BDADDR_LE_RANDOM:
5390 /* Two most significant bits shall be set */
5391 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5392 return false;
5393 return true;
5394 }
5395
5396 return false;
5397}
5398
5399static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5400 u16 len)
5401{
5402 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005403 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5404 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005405 u16 irk_count, expected_len;
5406 int i, err;
5407
5408 BT_DBG("request for %s", hdev->name);
5409
5410 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005411 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5412 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005413
5414 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005415 if (irk_count > max_irk_count) {
5416 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005417 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5418 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005419 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005420
5421 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5422 if (expected_len != len) {
5423 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005424 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005425 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5426 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005427 }
5428
5429 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5430
5431 for (i = 0; i < irk_count; i++) {
5432 struct mgmt_irk_info *key = &cp->irks[i];
5433
5434 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005435 return mgmt_cmd_status(sk, hdev->id,
5436 MGMT_OP_LOAD_IRKS,
5437 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005438 }
5439
5440 hci_dev_lock(hdev);
5441
5442 hci_smp_irks_clear(hdev);
5443
5444 for (i = 0; i < irk_count; i++) {
5445 struct mgmt_irk_info *irk = &cp->irks[i];
5446 u8 addr_type;
5447
5448 if (irk->addr.type == BDADDR_LE_PUBLIC)
5449 addr_type = ADDR_LE_DEV_PUBLIC;
5450 else
5451 addr_type = ADDR_LE_DEV_RANDOM;
5452
5453 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5454 BDADDR_ANY);
5455 }
5456
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005457 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005458
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005459 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005460
5461 hci_dev_unlock(hdev);
5462
5463 return err;
5464}
5465
Johan Hedberg3f706b72013-01-20 14:27:16 +02005466static bool ltk_is_valid(struct mgmt_ltk_info *key)
5467{
5468 if (key->master != 0x00 && key->master != 0x01)
5469 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005470
5471 switch (key->addr.type) {
5472 case BDADDR_LE_PUBLIC:
5473 return true;
5474
5475 case BDADDR_LE_RANDOM:
5476 /* Two most significant bits shall be set */
5477 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5478 return false;
5479 return true;
5480 }
5481
5482 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005483}
5484
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005485static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005486 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005487{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005488 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005489 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5490 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005491 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005492 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005493
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005494 BT_DBG("request for %s", hdev->name);
5495
5496 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005497 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5498 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005499
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005500 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005501 if (key_count > max_key_count) {
5502 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005503 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5504 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005505 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005506
5507 expected_len = sizeof(*cp) + key_count *
5508 sizeof(struct mgmt_ltk_info);
5509 if (expected_len != len) {
5510 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005511 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005512 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5513 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005514 }
5515
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005516 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005517
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005518 for (i = 0; i < key_count; i++) {
5519 struct mgmt_ltk_info *key = &cp->keys[i];
5520
Johan Hedberg3f706b72013-01-20 14:27:16 +02005521 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005522 return mgmt_cmd_status(sk, hdev->id,
5523 MGMT_OP_LOAD_LONG_TERM_KEYS,
5524 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005525 }
5526
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005527 hci_dev_lock(hdev);
5528
5529 hci_smp_ltks_clear(hdev);
5530
5531 for (i = 0; i < key_count; i++) {
5532 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005533 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005534
5535 if (key->addr.type == BDADDR_LE_PUBLIC)
5536 addr_type = ADDR_LE_DEV_PUBLIC;
5537 else
5538 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005539
Johan Hedberg61b43352014-05-29 19:36:53 +03005540 switch (key->type) {
5541 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005542 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005543 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005544 break;
5545 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005546 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005547 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005548 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005549 case MGMT_LTK_P256_UNAUTH:
5550 authenticated = 0x00;
5551 type = SMP_LTK_P256;
5552 break;
5553 case MGMT_LTK_P256_AUTH:
5554 authenticated = 0x01;
5555 type = SMP_LTK_P256;
5556 break;
5557 case MGMT_LTK_P256_DEBUG:
5558 authenticated = 0x00;
5559 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005560 default:
5561 continue;
5562 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005563
Johan Hedberg35d70272014-02-19 14:57:47 +02005564 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005565 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005566 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005567 }
5568
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005569 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005570 NULL, 0);
5571
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005572 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005573
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005574 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005575}
5576
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005577static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005578{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005579 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005580 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005581 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005582
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005583 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005584
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005585 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005586 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005587 rp.tx_power = conn->tx_power;
5588 rp.max_tx_power = conn->max_tx_power;
5589 } else {
5590 rp.rssi = HCI_RSSI_INVALID;
5591 rp.tx_power = HCI_TX_POWER_INVALID;
5592 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005593 }
5594
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005595 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5596 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005597
5598 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005599 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005600
5601 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005602}
5603
Marcel Holtmann1904a852015-01-11 13:50:44 -08005604static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5605 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005606{
5607 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005608 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005609 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005610 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005611 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005612
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005613 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005614
5615 hci_dev_lock(hdev);
5616
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005617 /* Commands sent in request are either Read RSSI or Read Transmit Power
5618 * Level so we check which one was last sent to retrieve connection
5619 * handle. Both commands have handle as first parameter so it's safe to
5620 * cast data on the same command struct.
5621 *
5622 * First command sent is always Read RSSI and we fail only if it fails.
5623 * In other case we simply override error to indicate success as we
5624 * already remembered if TX power value is actually valid.
5625 */
5626 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5627 if (!cp) {
5628 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005629 status = MGMT_STATUS_SUCCESS;
5630 } else {
5631 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005632 }
5633
5634 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005635 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005636 goto unlock;
5637 }
5638
5639 handle = __le16_to_cpu(cp->handle);
5640 conn = hci_conn_hash_lookup_handle(hdev, handle);
5641 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005642 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005643 goto unlock;
5644 }
5645
Johan Hedberg333ae952015-03-17 13:48:47 +02005646 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005647 if (!cmd)
5648 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005649
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005650 cmd->cmd_complete(cmd, status);
5651 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005652
5653unlock:
5654 hci_dev_unlock(hdev);
5655}
5656
5657static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5658 u16 len)
5659{
5660 struct mgmt_cp_get_conn_info *cp = data;
5661 struct mgmt_rp_get_conn_info rp;
5662 struct hci_conn *conn;
5663 unsigned long conn_info_age;
5664 int err = 0;
5665
5666 BT_DBG("%s", hdev->name);
5667
5668 memset(&rp, 0, sizeof(rp));
5669 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5670 rp.addr.type = cp->addr.type;
5671
5672 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005673 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5674 MGMT_STATUS_INVALID_PARAMS,
5675 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005676
5677 hci_dev_lock(hdev);
5678
5679 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005680 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5681 MGMT_STATUS_NOT_POWERED, &rp,
5682 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005683 goto unlock;
5684 }
5685
5686 if (cp->addr.type == BDADDR_BREDR)
5687 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5688 &cp->addr.bdaddr);
5689 else
5690 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5691
5692 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005693 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5694 MGMT_STATUS_NOT_CONNECTED, &rp,
5695 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005696 goto unlock;
5697 }
5698
Johan Hedberg333ae952015-03-17 13:48:47 +02005699 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005700 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5701 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005702 goto unlock;
5703 }
5704
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005705 /* To avoid client trying to guess when to poll again for information we
5706 * calculate conn info age as random value between min/max set in hdev.
5707 */
5708 conn_info_age = hdev->conn_info_min_age +
5709 prandom_u32_max(hdev->conn_info_max_age -
5710 hdev->conn_info_min_age);
5711
5712 /* Query controller to refresh cached values if they are too old or were
5713 * never read.
5714 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005715 if (time_after(jiffies, conn->conn_info_timestamp +
5716 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005717 !conn->conn_info_timestamp) {
5718 struct hci_request req;
5719 struct hci_cp_read_tx_power req_txp_cp;
5720 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005721 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005722
5723 hci_req_init(&req, hdev);
5724 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5725 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5726 &req_rssi_cp);
5727
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005728 /* For LE links TX power does not change thus we don't need to
5729 * query for it once value is known.
5730 */
5731 if (!bdaddr_type_is_le(cp->addr.type) ||
5732 conn->tx_power == HCI_TX_POWER_INVALID) {
5733 req_txp_cp.handle = cpu_to_le16(conn->handle);
5734 req_txp_cp.type = 0x00;
5735 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5736 sizeof(req_txp_cp), &req_txp_cp);
5737 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005738
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005739 /* Max TX power needs to be read only once per connection */
5740 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5741 req_txp_cp.handle = cpu_to_le16(conn->handle);
5742 req_txp_cp.type = 0x01;
5743 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5744 sizeof(req_txp_cp), &req_txp_cp);
5745 }
5746
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005747 err = hci_req_run(&req, conn_info_refresh_complete);
5748 if (err < 0)
5749 goto unlock;
5750
5751 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5752 data, len);
5753 if (!cmd) {
5754 err = -ENOMEM;
5755 goto unlock;
5756 }
5757
5758 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005759 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005760 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005761
5762 conn->conn_info_timestamp = jiffies;
5763 } else {
5764 /* Cache is valid, just reply with values cached in hci_conn */
5765 rp.rssi = conn->rssi;
5766 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005767 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005768
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005769 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5770 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005771 }
5772
5773unlock:
5774 hci_dev_unlock(hdev);
5775 return err;
5776}
5777
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005778static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005779{
5780 struct hci_conn *conn = cmd->user_data;
5781 struct mgmt_rp_get_clock_info rp;
5782 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005783 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005784
5785 memset(&rp, 0, sizeof(rp));
5786 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5787
5788 if (status)
5789 goto complete;
5790
5791 hdev = hci_dev_get(cmd->index);
5792 if (hdev) {
5793 rp.local_clock = cpu_to_le32(hdev->clock);
5794 hci_dev_put(hdev);
5795 }
5796
5797 if (conn) {
5798 rp.piconet_clock = cpu_to_le32(conn->clock);
5799 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5800 }
5801
5802complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005803 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5804 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005805
5806 if (conn) {
5807 hci_conn_drop(conn);
5808 hci_conn_put(conn);
5809 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005810
5811 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005812}
5813
Marcel Holtmann1904a852015-01-11 13:50:44 -08005814static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005815{
Johan Hedberg95868422014-06-28 17:54:07 +03005816 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005817 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005818 struct hci_conn *conn;
5819
5820 BT_DBG("%s status %u", hdev->name, status);
5821
5822 hci_dev_lock(hdev);
5823
5824 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5825 if (!hci_cp)
5826 goto unlock;
5827
5828 if (hci_cp->which) {
5829 u16 handle = __le16_to_cpu(hci_cp->handle);
5830 conn = hci_conn_hash_lookup_handle(hdev, handle);
5831 } else {
5832 conn = NULL;
5833 }
5834
Johan Hedberg333ae952015-03-17 13:48:47 +02005835 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005836 if (!cmd)
5837 goto unlock;
5838
Johan Hedberg69487372014-12-05 13:36:07 +02005839 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005840 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005841
5842unlock:
5843 hci_dev_unlock(hdev);
5844}
5845
5846static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5847 u16 len)
5848{
5849 struct mgmt_cp_get_clock_info *cp = data;
5850 struct mgmt_rp_get_clock_info rp;
5851 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005852 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005853 struct hci_request req;
5854 struct hci_conn *conn;
5855 int err;
5856
5857 BT_DBG("%s", hdev->name);
5858
5859 memset(&rp, 0, sizeof(rp));
5860 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5861 rp.addr.type = cp->addr.type;
5862
5863 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005864 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5865 MGMT_STATUS_INVALID_PARAMS,
5866 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005867
5868 hci_dev_lock(hdev);
5869
5870 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005871 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5872 MGMT_STATUS_NOT_POWERED, &rp,
5873 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005874 goto unlock;
5875 }
5876
5877 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5878 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5879 &cp->addr.bdaddr);
5880 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005881 err = mgmt_cmd_complete(sk, hdev->id,
5882 MGMT_OP_GET_CLOCK_INFO,
5883 MGMT_STATUS_NOT_CONNECTED,
5884 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005885 goto unlock;
5886 }
5887 } else {
5888 conn = NULL;
5889 }
5890
5891 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5892 if (!cmd) {
5893 err = -ENOMEM;
5894 goto unlock;
5895 }
5896
Johan Hedberg69487372014-12-05 13:36:07 +02005897 cmd->cmd_complete = clock_info_cmd_complete;
5898
Johan Hedberg95868422014-06-28 17:54:07 +03005899 hci_req_init(&req, hdev);
5900
5901 memset(&hci_cp, 0, sizeof(hci_cp));
5902 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5903
5904 if (conn) {
5905 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005906 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005907
5908 hci_cp.handle = cpu_to_le16(conn->handle);
5909 hci_cp.which = 0x01; /* Piconet clock */
5910 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5911 }
5912
5913 err = hci_req_run(&req, get_clock_info_complete);
5914 if (err < 0)
5915 mgmt_pending_remove(cmd);
5916
5917unlock:
5918 hci_dev_unlock(hdev);
5919 return err;
5920}
5921
Johan Hedberg5a154e62014-12-19 22:26:02 +02005922static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5923{
5924 struct hci_conn *conn;
5925
5926 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5927 if (!conn)
5928 return false;
5929
5930 if (conn->dst_type != type)
5931 return false;
5932
5933 if (conn->state != BT_CONNECTED)
5934 return false;
5935
5936 return true;
5937}
5938
5939/* This function requires the caller holds hdev->lock */
5940static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5941 u8 addr_type, u8 auto_connect)
5942{
5943 struct hci_dev *hdev = req->hdev;
5944 struct hci_conn_params *params;
5945
5946 params = hci_conn_params_add(hdev, addr, addr_type);
5947 if (!params)
5948 return -EIO;
5949
5950 if (params->auto_connect == auto_connect)
5951 return 0;
5952
5953 list_del_init(&params->action);
5954
5955 switch (auto_connect) {
5956 case HCI_AUTO_CONN_DISABLED:
5957 case HCI_AUTO_CONN_LINK_LOSS:
5958 __hci_update_background_scan(req);
5959 break;
5960 case HCI_AUTO_CONN_REPORT:
5961 list_add(&params->action, &hdev->pend_le_reports);
5962 __hci_update_background_scan(req);
5963 break;
5964 case HCI_AUTO_CONN_DIRECT:
5965 case HCI_AUTO_CONN_ALWAYS:
5966 if (!is_connected(hdev, addr, addr_type)) {
5967 list_add(&params->action, &hdev->pend_le_conns);
5968 __hci_update_background_scan(req);
5969 }
5970 break;
5971 }
5972
5973 params->auto_connect = auto_connect;
5974
5975 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5976 auto_connect);
5977
5978 return 0;
5979}
5980
Marcel Holtmann8afef092014-06-29 22:28:34 +02005981static void device_added(struct sock *sk, struct hci_dev *hdev,
5982 bdaddr_t *bdaddr, u8 type, u8 action)
5983{
5984 struct mgmt_ev_device_added ev;
5985
5986 bacpy(&ev.addr.bdaddr, bdaddr);
5987 ev.addr.type = type;
5988 ev.action = action;
5989
5990 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5991}
5992
Marcel Holtmann1904a852015-01-11 13:50:44 -08005993static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005994{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005995 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005996
5997 BT_DBG("status 0x%02x", status);
5998
5999 hci_dev_lock(hdev);
6000
Johan Hedberg333ae952015-03-17 13:48:47 +02006001 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006002 if (!cmd)
6003 goto unlock;
6004
6005 cmd->cmd_complete(cmd, mgmt_status(status));
6006 mgmt_pending_remove(cmd);
6007
6008unlock:
6009 hci_dev_unlock(hdev);
6010}
6011
Marcel Holtmann2faade52014-06-29 19:44:03 +02006012static int add_device(struct sock *sk, struct hci_dev *hdev,
6013 void *data, u16 len)
6014{
6015 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006016 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006017 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006018 u8 auto_conn, addr_type;
6019 int err;
6020
6021 BT_DBG("%s", hdev->name);
6022
Johan Hedberg66593582014-07-09 12:59:14 +03006023 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02006024 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006025 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6026 MGMT_STATUS_INVALID_PARAMS,
6027 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006028
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006029 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006030 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6031 MGMT_STATUS_INVALID_PARAMS,
6032 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006033
Johan Hedberg5a154e62014-12-19 22:26:02 +02006034 hci_req_init(&req, hdev);
6035
Marcel Holtmann2faade52014-06-29 19:44:03 +02006036 hci_dev_lock(hdev);
6037
Johan Hedberg5a154e62014-12-19 22:26:02 +02006038 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
6039 if (!cmd) {
6040 err = -ENOMEM;
6041 goto unlock;
6042 }
6043
6044 cmd->cmd_complete = addr_cmd_complete;
6045
Johan Hedberg66593582014-07-09 12:59:14 +03006046 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006047 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03006048 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006049 err = cmd->cmd_complete(cmd,
6050 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006051 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006052 goto unlock;
6053 }
6054
6055 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
6056 cp->addr.type);
6057 if (err)
6058 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03006059
Johan Hedberg5a154e62014-12-19 22:26:02 +02006060 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006061
Johan Hedberg66593582014-07-09 12:59:14 +03006062 goto added;
6063 }
6064
Marcel Holtmann2faade52014-06-29 19:44:03 +02006065 if (cp->addr.type == BDADDR_LE_PUBLIC)
6066 addr_type = ADDR_LE_DEV_PUBLIC;
6067 else
6068 addr_type = ADDR_LE_DEV_RANDOM;
6069
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006070 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006071 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006072 else if (cp->action == 0x01)
6073 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006074 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006075 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006076
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006077 /* If the connection parameters don't exist for this device,
6078 * they will be created and configured with defaults.
6079 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006080 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006081 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006082 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006083 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006084 goto unlock;
6085 }
6086
Johan Hedberg66593582014-07-09 12:59:14 +03006087added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006088 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6089
Johan Hedberg5a154e62014-12-19 22:26:02 +02006090 err = hci_req_run(&req, add_device_complete);
6091 if (err < 0) {
6092 /* ENODATA means no HCI commands were needed (e.g. if
6093 * the adapter is powered off).
6094 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006095 if (err == -ENODATA)
6096 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006097 mgmt_pending_remove(cmd);
6098 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006099
6100unlock:
6101 hci_dev_unlock(hdev);
6102 return err;
6103}
6104
Marcel Holtmann8afef092014-06-29 22:28:34 +02006105static void device_removed(struct sock *sk, struct hci_dev *hdev,
6106 bdaddr_t *bdaddr, u8 type)
6107{
6108 struct mgmt_ev_device_removed ev;
6109
6110 bacpy(&ev.addr.bdaddr, bdaddr);
6111 ev.addr.type = type;
6112
6113 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6114}
6115
Marcel Holtmann1904a852015-01-11 13:50:44 -08006116static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006117{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006118 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006119
6120 BT_DBG("status 0x%02x", status);
6121
6122 hci_dev_lock(hdev);
6123
Johan Hedberg333ae952015-03-17 13:48:47 +02006124 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006125 if (!cmd)
6126 goto unlock;
6127
6128 cmd->cmd_complete(cmd, mgmt_status(status));
6129 mgmt_pending_remove(cmd);
6130
6131unlock:
6132 hci_dev_unlock(hdev);
6133}
6134
Marcel Holtmann2faade52014-06-29 19:44:03 +02006135static int remove_device(struct sock *sk, struct hci_dev *hdev,
6136 void *data, u16 len)
6137{
6138 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006139 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006140 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006141 int err;
6142
6143 BT_DBG("%s", hdev->name);
6144
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006145 hci_req_init(&req, hdev);
6146
Marcel Holtmann2faade52014-06-29 19:44:03 +02006147 hci_dev_lock(hdev);
6148
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006149 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6150 if (!cmd) {
6151 err = -ENOMEM;
6152 goto unlock;
6153 }
6154
6155 cmd->cmd_complete = addr_cmd_complete;
6156
Marcel Holtmann2faade52014-06-29 19:44:03 +02006157 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006158 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006159 u8 addr_type;
6160
Johan Hedberg66593582014-07-09 12:59:14 +03006161 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006162 err = cmd->cmd_complete(cmd,
6163 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006164 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006165 goto unlock;
6166 }
6167
Johan Hedberg66593582014-07-09 12:59:14 +03006168 if (cp->addr.type == BDADDR_BREDR) {
6169 err = hci_bdaddr_list_del(&hdev->whitelist,
6170 &cp->addr.bdaddr,
6171 cp->addr.type);
6172 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006173 err = cmd->cmd_complete(cmd,
6174 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006175 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006176 goto unlock;
6177 }
6178
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006179 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006180
Johan Hedberg66593582014-07-09 12:59:14 +03006181 device_removed(sk, hdev, &cp->addr.bdaddr,
6182 cp->addr.type);
6183 goto complete;
6184 }
6185
Marcel Holtmann2faade52014-06-29 19:44:03 +02006186 if (cp->addr.type == BDADDR_LE_PUBLIC)
6187 addr_type = ADDR_LE_DEV_PUBLIC;
6188 else
6189 addr_type = ADDR_LE_DEV_RANDOM;
6190
Johan Hedbergc71593d2014-07-02 17:37:28 +03006191 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6192 addr_type);
6193 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006194 err = cmd->cmd_complete(cmd,
6195 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006196 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006197 goto unlock;
6198 }
6199
6200 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006201 err = cmd->cmd_complete(cmd,
6202 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006203 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006204 goto unlock;
6205 }
6206
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006207 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006208 list_del(&params->list);
6209 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006210 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006211
6212 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006213 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006214 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006215 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006216
Marcel Holtmann2faade52014-06-29 19:44:03 +02006217 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006218 err = cmd->cmd_complete(cmd,
6219 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006220 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006221 goto unlock;
6222 }
6223
Johan Hedberg66593582014-07-09 12:59:14 +03006224 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6225 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6226 list_del(&b->list);
6227 kfree(b);
6228 }
6229
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006230 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006231
Johan Hedberg19de0822014-07-06 13:06:51 +03006232 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6233 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6234 continue;
6235 device_removed(sk, hdev, &p->addr, p->addr_type);
6236 list_del(&p->action);
6237 list_del(&p->list);
6238 kfree(p);
6239 }
6240
6241 BT_DBG("All LE connection parameters were removed");
6242
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006243 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006244 }
6245
Johan Hedberg66593582014-07-09 12:59:14 +03006246complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006247 err = hci_req_run(&req, remove_device_complete);
6248 if (err < 0) {
6249 /* ENODATA means no HCI commands were needed (e.g. if
6250 * the adapter is powered off).
6251 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006252 if (err == -ENODATA)
6253 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006254 mgmt_pending_remove(cmd);
6255 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006256
6257unlock:
6258 hci_dev_unlock(hdev);
6259 return err;
6260}
6261
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006262static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6263 u16 len)
6264{
6265 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006266 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6267 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006268 u16 param_count, expected_len;
6269 int i;
6270
6271 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006272 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6273 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006274
6275 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006276 if (param_count > max_param_count) {
6277 BT_ERR("load_conn_param: too big param_count value %u",
6278 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006279 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6280 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006281 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006282
6283 expected_len = sizeof(*cp) + param_count *
6284 sizeof(struct mgmt_conn_param);
6285 if (expected_len != len) {
6286 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6287 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006288 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6289 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006290 }
6291
6292 BT_DBG("%s param_count %u", hdev->name, param_count);
6293
6294 hci_dev_lock(hdev);
6295
6296 hci_conn_params_clear_disabled(hdev);
6297
6298 for (i = 0; i < param_count; i++) {
6299 struct mgmt_conn_param *param = &cp->params[i];
6300 struct hci_conn_params *hci_param;
6301 u16 min, max, latency, timeout;
6302 u8 addr_type;
6303
6304 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6305 param->addr.type);
6306
6307 if (param->addr.type == BDADDR_LE_PUBLIC) {
6308 addr_type = ADDR_LE_DEV_PUBLIC;
6309 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6310 addr_type = ADDR_LE_DEV_RANDOM;
6311 } else {
6312 BT_ERR("Ignoring invalid connection parameters");
6313 continue;
6314 }
6315
6316 min = le16_to_cpu(param->min_interval);
6317 max = le16_to_cpu(param->max_interval);
6318 latency = le16_to_cpu(param->latency);
6319 timeout = le16_to_cpu(param->timeout);
6320
6321 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6322 min, max, latency, timeout);
6323
6324 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6325 BT_ERR("Ignoring invalid connection parameters");
6326 continue;
6327 }
6328
6329 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6330 addr_type);
6331 if (!hci_param) {
6332 BT_ERR("Failed to add connection parameters");
6333 continue;
6334 }
6335
6336 hci_param->conn_min_interval = min;
6337 hci_param->conn_max_interval = max;
6338 hci_param->conn_latency = latency;
6339 hci_param->supervision_timeout = timeout;
6340 }
6341
6342 hci_dev_unlock(hdev);
6343
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006344 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6345 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006346}
6347
Marcel Holtmanndbece372014-07-04 18:11:55 +02006348static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6349 void *data, u16 len)
6350{
6351 struct mgmt_cp_set_external_config *cp = data;
6352 bool changed;
6353 int err;
6354
6355 BT_DBG("%s", hdev->name);
6356
6357 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006358 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6359 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006360
6361 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006362 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6363 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006364
6365 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006366 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6367 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006368
6369 hci_dev_lock(hdev);
6370
6371 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006372 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006373 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006374 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006375
6376 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6377 if (err < 0)
6378 goto unlock;
6379
6380 if (!changed)
6381 goto unlock;
6382
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006383 err = new_options(hdev, sk);
6384
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006385 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006386 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006387
Marcel Holtmann516018a2015-03-13 02:11:04 -07006388 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006389 hci_dev_set_flag(hdev, HCI_CONFIG);
6390 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006391
6392 queue_work(hdev->req_workqueue, &hdev->power_on);
6393 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006394 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006395 mgmt_index_added(hdev);
6396 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006397 }
6398
6399unlock:
6400 hci_dev_unlock(hdev);
6401 return err;
6402}
6403
Marcel Holtmann9713c172014-07-06 12:11:15 +02006404static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6405 void *data, u16 len)
6406{
6407 struct mgmt_cp_set_public_address *cp = data;
6408 bool changed;
6409 int err;
6410
6411 BT_DBG("%s", hdev->name);
6412
6413 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006414 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6415 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006416
6417 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006418 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6419 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006420
6421 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006422 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6423 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006424
6425 hci_dev_lock(hdev);
6426
6427 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6428 bacpy(&hdev->public_addr, &cp->bdaddr);
6429
6430 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6431 if (err < 0)
6432 goto unlock;
6433
6434 if (!changed)
6435 goto unlock;
6436
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006437 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006438 err = new_options(hdev, sk);
6439
6440 if (is_configured(hdev)) {
6441 mgmt_index_removed(hdev);
6442
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006443 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006444
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006445 hci_dev_set_flag(hdev, HCI_CONFIG);
6446 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006447
6448 queue_work(hdev->req_workqueue, &hdev->power_on);
6449 }
6450
6451unlock:
6452 hci_dev_unlock(hdev);
6453 return err;
6454}
6455
Marcel Holtmannbea41602015-03-14 22:43:17 -07006456static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6457 u8 data_len)
6458{
6459 eir[eir_len++] = sizeof(type) + data_len;
6460 eir[eir_len++] = type;
6461 memcpy(&eir[eir_len], data, data_len);
6462 eir_len += data_len;
6463
6464 return eir_len;
6465}
6466
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006467static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6468 void *data, u16 data_len)
6469{
6470 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6471 struct mgmt_rp_read_local_oob_ext_data *rp;
6472 size_t rp_len;
6473 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006474 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006475 int err;
6476
6477 BT_DBG("%s", hdev->name);
6478
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006479 if (hdev_is_powered(hdev)) {
6480 switch (cp->type) {
6481 case BIT(BDADDR_BREDR):
6482 status = mgmt_bredr_support(hdev);
6483 if (status)
6484 eir_len = 0;
6485 else
6486 eir_len = 5;
6487 break;
6488 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6489 status = mgmt_le_support(hdev);
6490 if (status)
6491 eir_len = 0;
6492 else
6493 eir_len = 9 + 3 + 18 + 18 + 3;
6494 break;
6495 default:
6496 status = MGMT_STATUS_INVALID_PARAMS;
6497 eir_len = 0;
6498 break;
6499 }
6500 } else {
6501 status = MGMT_STATUS_NOT_POWERED;
6502 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006503 }
6504
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006505 rp_len = sizeof(*rp) + eir_len;
6506 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006507 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006508 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006509
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006510 if (status)
6511 goto complete;
6512
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006513 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006514
6515 eir_len = 0;
6516 switch (cp->type) {
6517 case BIT(BDADDR_BREDR):
6518 eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
6519 hdev->dev_class, 3);
6520 break;
6521 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006522 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6523 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006524 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006525 status = MGMT_STATUS_FAILED;
6526 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006527 }
6528
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006529 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
6530 memcpy(addr, &hdev->rpa, 6);
6531 addr[6] = 0x01;
6532 } else if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6533 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6534 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6535 bacmp(&hdev->static_addr, BDADDR_ANY))) {
6536 memcpy(addr, &hdev->static_addr, 6);
6537 addr[6] = 0x01;
6538 } else {
6539 memcpy(addr, &hdev->bdaddr, 6);
6540 addr[6] = 0x00;
6541 }
6542
6543 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6544 addr, sizeof(addr));
6545
6546 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6547 role = 0x02;
6548 else
6549 role = 0x01;
6550
6551 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6552 &role, sizeof(role));
6553
Marcel Holtmann5082a592015-03-16 12:39:00 -07006554 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6555 eir_len = eir_append_data(rp->eir, eir_len,
6556 EIR_LE_SC_CONFIRM,
6557 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006558
Marcel Holtmann5082a592015-03-16 12:39:00 -07006559 eir_len = eir_append_data(rp->eir, eir_len,
6560 EIR_LE_SC_RANDOM,
6561 rand, sizeof(rand));
6562 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006563
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006564 flags = get_adv_discov_flags(hdev);
6565
6566 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6567 flags |= LE_AD_NO_BREDR;
6568
6569 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6570 &flags, sizeof(flags));
6571 break;
6572 }
6573
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006574 hci_dev_unlock(hdev);
6575
Marcel Holtmann72000df2015-03-16 16:11:21 -07006576 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6577
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006578 status = MGMT_STATUS_SUCCESS;
6579
6580complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006581 rp->type = cp->type;
6582 rp->eir_len = cpu_to_le16(eir_len);
6583
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006584 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006585 status, rp, sizeof(*rp) + eir_len);
6586 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006587 goto done;
6588
6589 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6590 rp, sizeof(*rp) + eir_len,
6591 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006592
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006593done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006594 kfree(rp);
6595
6596 return err;
6597}
6598
Arman Uguray089fa8c2015-03-25 18:53:45 -07006599static u32 get_supported_adv_flags(struct hci_dev *hdev)
6600{
6601 u32 flags = 0;
6602
6603 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6604 flags |= MGMT_ADV_FLAG_DISCOV;
6605 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6606 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6607
6608 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6609 flags |= MGMT_ADV_FLAG_TX_POWER;
6610
6611 return flags;
6612}
6613
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006614static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6615 void *data, u16 data_len)
6616{
6617 struct mgmt_rp_read_adv_features *rp;
6618 size_t rp_len;
6619 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006620 bool instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006621 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006622
6623 BT_DBG("%s", hdev->name);
6624
Arman Uguray089fa8c2015-03-25 18:53:45 -07006625 if (!lmp_le_capable(hdev))
6626 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6627 MGMT_STATUS_REJECTED);
6628
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006629 hci_dev_lock(hdev);
6630
6631 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006632
6633 /* Currently only one instance is supported, so just add 1 to the
6634 * response length.
6635 */
6636 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6637 if (instance)
6638 rp_len++;
6639
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006640 rp = kmalloc(rp_len, GFP_ATOMIC);
6641 if (!rp) {
6642 hci_dev_unlock(hdev);
6643 return -ENOMEM;
6644 }
6645
Arman Uguray089fa8c2015-03-25 18:53:45 -07006646 supported_flags = get_supported_adv_flags(hdev);
6647
6648 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006649 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6650 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006651 rp->max_instances = 1;
6652
6653 /* Currently only one instance is supported, so simply return the
6654 * current instance number.
6655 */
6656 if (instance) {
6657 rp->num_instances = 1;
6658 rp->instance[0] = 1;
6659 } else {
6660 rp->num_instances = 0;
6661 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006662
6663 hci_dev_unlock(hdev);
6664
6665 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6666 MGMT_STATUS_SUCCESS, rp, rp_len);
6667
6668 kfree(rp);
6669
6670 return err;
6671}
6672
Arman Uguray4117ed72015-03-23 15:57:14 -07006673static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006674 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006675{
Arman Uguray4117ed72015-03-23 15:57:14 -07006676 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006677 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006678 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006679 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006680 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6681 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006682
Arman Uguray807ec772015-03-25 18:53:42 -07006683 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006684 flags_managed = true;
6685 max_len -= 3;
6686 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006687
Arman Uguray5507e352015-03-25 18:53:44 -07006688 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6689 tx_power_managed = true;
6690 max_len -= 3;
6691 }
6692
Arman Uguray4117ed72015-03-23 15:57:14 -07006693 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006694 return false;
6695
Arman Uguray4117ed72015-03-23 15:57:14 -07006696 /* Make sure that the data is correctly formatted. */
6697 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6698 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006699
Arman Ugurayb44133f2015-03-25 18:53:41 -07006700 if (flags_managed && data[i + 1] == EIR_FLAGS)
6701 return false;
6702
Arman Uguray5507e352015-03-25 18:53:44 -07006703 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6704 return false;
6705
Arman Uguray24b4f382015-03-23 15:57:12 -07006706 /* If the current field length would exceed the total data
6707 * length, then it's invalid.
6708 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006709 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006710 return false;
6711 }
6712
6713 return true;
6714}
6715
Arman Uguray24b4f382015-03-23 15:57:12 -07006716static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6717 u16 opcode)
6718{
6719 struct mgmt_pending_cmd *cmd;
6720 struct mgmt_rp_add_advertising rp;
6721
6722 BT_DBG("status %d", status);
6723
6724 hci_dev_lock(hdev);
6725
6726 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6727
6728 if (status) {
6729 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6730 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6731 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6732 }
6733
6734 if (!cmd)
6735 goto unlock;
6736
6737 rp.instance = 0x01;
6738
6739 if (status)
6740 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6741 mgmt_status(status));
6742 else
6743 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6744 mgmt_status(status), &rp, sizeof(rp));
6745
6746 mgmt_pending_remove(cmd);
6747
6748unlock:
6749 hci_dev_unlock(hdev);
6750}
6751
Arman Uguray912098a2015-03-23 15:57:15 -07006752static void adv_timeout_expired(struct work_struct *work)
6753{
6754 struct hci_dev *hdev = container_of(work, struct hci_dev,
6755 adv_instance.timeout_exp.work);
6756
6757 hdev->adv_instance.timeout = 0;
6758
6759 hci_dev_lock(hdev);
6760 clear_adv_instance(hdev);
6761 hci_dev_unlock(hdev);
6762}
6763
Arman Uguray24b4f382015-03-23 15:57:12 -07006764static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6765 void *data, u16 data_len)
6766{
6767 struct mgmt_cp_add_advertising *cp = data;
6768 struct mgmt_rp_add_advertising rp;
6769 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006770 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006771 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006772 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006773 int err;
6774 struct mgmt_pending_cmd *cmd;
6775 struct hci_request req;
6776
6777 BT_DBG("%s", hdev->name);
6778
6779 status = mgmt_le_support(hdev);
6780 if (status)
6781 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6782 status);
6783
6784 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006785 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006786
Arman Uguray089fa8c2015-03-25 18:53:45 -07006787 /* The current implementation only supports adding one instance and only
6788 * a subset of the specified flags.
6789 */
6790 supported_flags = get_supported_adv_flags(hdev);
6791 if (cp->instance != 0x01 || (flags & ~supported_flags))
Arman Uguray24b4f382015-03-23 15:57:12 -07006792 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6793 MGMT_STATUS_INVALID_PARAMS);
6794
6795 hci_dev_lock(hdev);
6796
Arman Uguray912098a2015-03-23 15:57:15 -07006797 if (timeout && !hdev_is_powered(hdev)) {
6798 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6799 MGMT_STATUS_REJECTED);
6800 goto unlock;
6801 }
6802
Arman Uguray24b4f382015-03-23 15:57:12 -07006803 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006804 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006805 pending_find(MGMT_OP_SET_LE, hdev)) {
6806 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6807 MGMT_STATUS_BUSY);
6808 goto unlock;
6809 }
6810
Arman Ugurayb44133f2015-03-25 18:53:41 -07006811 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006812 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006813 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006814 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6815 MGMT_STATUS_INVALID_PARAMS);
6816 goto unlock;
6817 }
6818
Arman Uguray912098a2015-03-23 15:57:15 -07006819 INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
6820
Arman Uguray24b4f382015-03-23 15:57:12 -07006821 hdev->adv_instance.flags = flags;
6822 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6823 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6824
6825 if (cp->adv_data_len)
6826 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6827
6828 if (cp->scan_rsp_len)
6829 memcpy(hdev->adv_instance.scan_rsp_data,
6830 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6831
Arman Uguray912098a2015-03-23 15:57:15 -07006832 if (hdev->adv_instance.timeout)
6833 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6834
6835 hdev->adv_instance.timeout = timeout;
6836
6837 if (timeout)
6838 queue_delayed_work(hdev->workqueue,
6839 &hdev->adv_instance.timeout_exp,
6840 msecs_to_jiffies(timeout * 1000));
6841
Arman Uguray24b4f382015-03-23 15:57:12 -07006842 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6843 advertising_added(sk, hdev, 1);
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 = 0x01;
6851 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6852 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6853 goto unlock;
6854 }
6855
6856 /* We're good to go, update advertising data, parameters, and start
6857 * advertising.
6858 */
6859 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6860 data_len);
6861 if (!cmd) {
6862 err = -ENOMEM;
6863 goto unlock;
6864 }
6865
6866 hci_req_init(&req, hdev);
6867
6868 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07006869 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07006870 enable_advertising(&req);
6871
6872 err = hci_req_run(&req, add_advertising_complete);
6873 if (err < 0)
6874 mgmt_pending_remove(cmd);
6875
6876unlock:
6877 hci_dev_unlock(hdev);
6878
6879 return err;
6880}
6881
Arman Ugurayda9293352015-03-23 15:57:13 -07006882static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6883 u16 opcode)
6884{
6885 struct mgmt_pending_cmd *cmd;
6886 struct mgmt_rp_remove_advertising rp;
6887
6888 BT_DBG("status %d", status);
6889
6890 hci_dev_lock(hdev);
6891
6892 /* A failure status here only means that we failed to disable
6893 * advertising. Otherwise, the advertising instance has been removed,
6894 * so report success.
6895 */
6896 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6897 if (!cmd)
6898 goto unlock;
6899
6900 rp.instance = 1;
6901
6902 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6903 &rp, sizeof(rp));
6904 mgmt_pending_remove(cmd);
6905
6906unlock:
6907 hci_dev_unlock(hdev);
6908}
6909
6910static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6911 void *data, u16 data_len)
6912{
6913 struct mgmt_cp_remove_advertising *cp = data;
6914 struct mgmt_rp_remove_advertising rp;
6915 int err;
6916 struct mgmt_pending_cmd *cmd;
6917 struct hci_request req;
6918
6919 BT_DBG("%s", hdev->name);
6920
6921 /* The current implementation only allows modifying instance no 1. A
6922 * value of 0 indicates that all instances should be cleared.
6923 */
6924 if (cp->instance > 1)
6925 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6926 MGMT_STATUS_INVALID_PARAMS);
6927
6928 hci_dev_lock(hdev);
6929
6930 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
6931 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
6932 pending_find(MGMT_OP_SET_LE, hdev)) {
6933 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6934 MGMT_STATUS_BUSY);
6935 goto unlock;
6936 }
6937
6938 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
6939 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6940 MGMT_STATUS_INVALID_PARAMS);
6941 goto unlock;
6942 }
6943
Arman Uguray912098a2015-03-23 15:57:15 -07006944 if (hdev->adv_instance.timeout)
6945 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6946
Arman Ugurayda9293352015-03-23 15:57:13 -07006947 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6948
6949 advertising_removed(sk, hdev, 1);
6950
6951 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6952
6953 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6954 * we have no HCI communication to make. Simply return.
6955 */
6956 if (!hdev_is_powered(hdev) ||
6957 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6958 rp.instance = 1;
6959 err = mgmt_cmd_complete(sk, hdev->id,
6960 MGMT_OP_REMOVE_ADVERTISING,
6961 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6962 goto unlock;
6963 }
6964
6965 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
6966 data_len);
6967 if (!cmd) {
6968 err = -ENOMEM;
6969 goto unlock;
6970 }
6971
6972 hci_req_init(&req, hdev);
6973 disable_advertising(&req);
6974
6975 err = hci_req_run(&req, remove_advertising_complete);
6976 if (err < 0)
6977 mgmt_pending_remove(cmd);
6978
6979unlock:
6980 hci_dev_unlock(hdev);
6981
6982 return err;
6983}
6984
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006985static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006986 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006987 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006988 HCI_MGMT_NO_HDEV |
6989 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006990 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006991 HCI_MGMT_NO_HDEV |
6992 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006993 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006994 HCI_MGMT_NO_HDEV |
6995 HCI_MGMT_UNTRUSTED },
6996 { read_controller_info, MGMT_READ_INFO_SIZE,
6997 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006998 { set_powered, MGMT_SETTING_SIZE },
6999 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7000 { set_connectable, MGMT_SETTING_SIZE },
7001 { set_fast_connectable, MGMT_SETTING_SIZE },
7002 { set_bondable, MGMT_SETTING_SIZE },
7003 { set_link_security, MGMT_SETTING_SIZE },
7004 { set_ssp, MGMT_SETTING_SIZE },
7005 { set_hs, MGMT_SETTING_SIZE },
7006 { set_le, MGMT_SETTING_SIZE },
7007 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7008 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7009 { add_uuid, MGMT_ADD_UUID_SIZE },
7010 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007011 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7012 HCI_MGMT_VAR_LEN },
7013 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7014 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007015 { disconnect, MGMT_DISCONNECT_SIZE },
7016 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7017 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7018 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7019 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7020 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7021 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7022 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7023 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7024 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7025 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7026 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007027 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7028 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7029 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007030 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7031 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7032 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7033 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7034 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7035 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7036 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7037 { set_advertising, MGMT_SETTING_SIZE },
7038 { set_bredr, MGMT_SETTING_SIZE },
7039 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7040 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7041 { set_secure_conn, MGMT_SETTING_SIZE },
7042 { set_debug_keys, MGMT_SETTING_SIZE },
7043 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007044 { load_irks, MGMT_LOAD_IRKS_SIZE,
7045 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007046 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7047 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7048 { add_device, MGMT_ADD_DEVICE_SIZE },
7049 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007050 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7051 HCI_MGMT_VAR_LEN },
7052 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007053 HCI_MGMT_NO_HDEV |
7054 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007055 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007056 HCI_MGMT_UNCONFIGURED |
7057 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007058 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7059 HCI_MGMT_UNCONFIGURED },
7060 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7061 HCI_MGMT_UNCONFIGURED },
7062 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7063 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007064 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007065 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007066 HCI_MGMT_NO_HDEV |
7067 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007068 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007069 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7070 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007071 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007072};
7073
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007074void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007075{
Marcel Holtmannced85542015-03-14 19:27:56 -07007076 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007077
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007078 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7079 return;
7080
Marcel Holtmannf9207332015-03-14 19:27:55 -07007081 switch (hdev->dev_type) {
7082 case HCI_BREDR:
7083 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7084 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7085 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007086 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007087 } else {
7088 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7089 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007090 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007091 }
7092 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007093 case HCI_AMP:
7094 ev.type = 0x02;
7095 break;
7096 default:
7097 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007098 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007099
7100 ev.bus = hdev->bus;
7101
7102 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7103 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007104}
7105
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007106void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007107{
Marcel Holtmannced85542015-03-14 19:27:56 -07007108 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007109 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007110
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007111 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7112 return;
7113
Marcel Holtmannf9207332015-03-14 19:27:55 -07007114 switch (hdev->dev_type) {
7115 case HCI_BREDR:
7116 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007117
Marcel Holtmannf9207332015-03-14 19:27:55 -07007118 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7119 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7120 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007121 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007122 } else {
7123 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7124 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007125 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007126 }
7127 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007128 case HCI_AMP:
7129 ev.type = 0x02;
7130 break;
7131 default:
7132 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007133 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007134
7135 ev.bus = hdev->bus;
7136
7137 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7138 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007139}
7140
Andre Guedes6046dc32014-02-26 20:21:51 -03007141/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007142static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007143{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007144 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007145 struct hci_conn_params *p;
7146
7147 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007148 /* Needed for AUTO_OFF case where might not "really"
7149 * have been powered off.
7150 */
7151 list_del_init(&p->action);
7152
7153 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007154 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007155 case HCI_AUTO_CONN_ALWAYS:
7156 list_add(&p->action, &hdev->pend_le_conns);
7157 break;
7158 case HCI_AUTO_CONN_REPORT:
7159 list_add(&p->action, &hdev->pend_le_reports);
7160 break;
7161 default:
7162 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007163 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007164 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007165
Johan Hedberg2cf22212014-12-19 22:26:00 +02007166 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007167}
7168
Marcel Holtmann1904a852015-01-11 13:50:44 -08007169static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007170{
7171 struct cmd_lookup match = { NULL, hdev };
7172
7173 BT_DBG("status 0x%02x", status);
7174
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007175 if (!status) {
7176 /* Register the available SMP channels (BR/EDR and LE) only
7177 * when successfully powering on the controller. This late
7178 * registration is required so that LE SMP can clearly
7179 * decide if the public address or static address is used.
7180 */
7181 smp_register(hdev);
7182 }
7183
Johan Hedberg229ab392013-03-15 17:06:53 -05007184 hci_dev_lock(hdev);
7185
7186 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7187
7188 new_settings(hdev, match.sk);
7189
7190 hci_dev_unlock(hdev);
7191
7192 if (match.sk)
7193 sock_put(match.sk);
7194}
7195
Johan Hedberg70da6242013-03-15 17:06:51 -05007196static int powered_update_hci(struct hci_dev *hdev)
7197{
Johan Hedberg890ea892013-03-15 17:06:52 -05007198 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007199 u8 link_sec;
7200
Johan Hedberg890ea892013-03-15 17:06:52 -05007201 hci_req_init(&req, hdev);
7202
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007203 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007204 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007205 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007206
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007207 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007208
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007209 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7210 u8 support = 0x01;
7211
7212 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7213 sizeof(support), &support);
7214 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007215 }
7216
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007217 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007218 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007219 struct hci_cp_write_le_host_supported cp;
7220
Marcel Holtmann32226e42014-07-24 20:04:16 +02007221 cp.le = 0x01;
7222 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007223
7224 /* Check first if we already have the right
7225 * host state (host features set)
7226 */
7227 if (cp.le != lmp_host_le_capable(hdev) ||
7228 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007229 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7230 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007231 }
7232
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007233 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007234 /* Make sure the controller has a good default for
7235 * advertising data. This also applies to the case
7236 * where BR/EDR was toggled during the AUTO_OFF phase.
7237 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007238 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007239 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007240 update_scan_rsp_data(&req);
7241 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007242
Arman Uguray24b4f382015-03-23 15:57:12 -07007243 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7244 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007245 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007246
7247 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007248 }
7249
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007250 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007251 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007252 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7253 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007254
7255 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007256 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007257 write_fast_connectable(&req, true);
7258 else
7259 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007260 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007261 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007262 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007263 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007264 }
7265
Johan Hedberg229ab392013-03-15 17:06:53 -05007266 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007267}
7268
Johan Hedberg744cf192011-11-08 20:40:14 +02007269int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007270{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007271 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007272 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007273 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007274
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007275 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007276 return 0;
7277
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007278 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007279 if (powered_update_hci(hdev) == 0)
7280 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007281
Johan Hedberg229ab392013-03-15 17:06:53 -05007282 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7283 &match);
7284 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007285 }
7286
Johan Hedberg229ab392013-03-15 17:06:53 -05007287 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007288
7289 /* If the power off is because of hdev unregistration let
7290 * use the appropriate INVALID_INDEX status. Otherwise use
7291 * NOT_POWERED. We cover both scenarios here since later in
7292 * mgmt_index_removed() any hci_conn callbacks will have already
7293 * been triggered, potentially causing misleading DISCONNECTED
7294 * status responses.
7295 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007296 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007297 status = MGMT_STATUS_INVALID_INDEX;
7298 else
7299 status = MGMT_STATUS_NOT_POWERED;
7300
7301 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007302
7303 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007304 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7305 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007306
7307new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007308 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007309
7310 if (match.sk)
7311 sock_put(match.sk);
7312
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007313 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007314}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007315
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007316void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007317{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007318 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007319 u8 status;
7320
Johan Hedberg333ae952015-03-17 13:48:47 +02007321 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007322 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007323 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007324
7325 if (err == -ERFKILL)
7326 status = MGMT_STATUS_RFKILLED;
7327 else
7328 status = MGMT_STATUS_FAILED;
7329
Johan Hedberga69e8372015-03-06 21:08:53 +02007330 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007331
7332 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007333}
7334
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007335void mgmt_discoverable_timeout(struct hci_dev *hdev)
7336{
7337 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007338
7339 hci_dev_lock(hdev);
7340
7341 /* When discoverable timeout triggers, then just make sure
7342 * the limited discoverable flag is cleared. Even in the case
7343 * of a timeout triggered from general discoverable, it is
7344 * safe to unconditionally clear the flag.
7345 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007346 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7347 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007348
7349 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007350 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007351 u8 scan = SCAN_PAGE;
7352 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7353 sizeof(scan), &scan);
7354 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007355 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007356
7357 /* Advertising instances don't use the global discoverable setting, so
7358 * only update AD if advertising was enabled using Set Advertising.
7359 */
7360 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7361 update_adv_data(&req);
7362
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007363 hci_req_run(&req, NULL);
7364
7365 hdev->discov_timeout = 0;
7366
Johan Hedberg9a43e252013-10-20 19:00:07 +03007367 new_settings(hdev, NULL);
7368
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007369 hci_dev_unlock(hdev);
7370}
7371
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007372void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7373 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007374{
Johan Hedberg86742e12011-11-07 23:13:38 +02007375 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007376
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007377 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007378
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007379 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007380 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007381 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007382 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007383 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007384 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007385
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007386 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007387}
Johan Hedbergf7520542011-01-20 12:34:39 +02007388
Johan Hedbergd7b25452014-05-23 13:19:53 +03007389static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7390{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007391 switch (ltk->type) {
7392 case SMP_LTK:
7393 case SMP_LTK_SLAVE:
7394 if (ltk->authenticated)
7395 return MGMT_LTK_AUTHENTICATED;
7396 return MGMT_LTK_UNAUTHENTICATED;
7397 case SMP_LTK_P256:
7398 if (ltk->authenticated)
7399 return MGMT_LTK_P256_AUTH;
7400 return MGMT_LTK_P256_UNAUTH;
7401 case SMP_LTK_P256_DEBUG:
7402 return MGMT_LTK_P256_DEBUG;
7403 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007404
7405 return MGMT_LTK_UNAUTHENTICATED;
7406}
7407
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007408void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007409{
7410 struct mgmt_ev_new_long_term_key ev;
7411
7412 memset(&ev, 0, sizeof(ev));
7413
Marcel Holtmann5192d302014-02-19 17:11:58 -08007414 /* Devices using resolvable or non-resolvable random addresses
7415 * without providing an indentity resolving key don't require
7416 * to store long term keys. Their addresses will change the
7417 * next time around.
7418 *
7419 * Only when a remote device provides an identity address
7420 * make sure the long term key is stored. If the remote
7421 * identity is known, the long term keys are internally
7422 * mapped to the identity address. So allow static random
7423 * and public addresses here.
7424 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007425 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7426 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7427 ev.store_hint = 0x00;
7428 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007429 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007430
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007431 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007432 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007433 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007434 ev.key.enc_size = key->enc_size;
7435 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007436 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007437
Johan Hedberg2ceba532014-06-16 19:25:16 +03007438 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007439 ev.key.master = 1;
7440
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007441 memcpy(ev.key.val, key->val, sizeof(key->val));
7442
Marcel Holtmann083368f2013-10-15 14:26:29 -07007443 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007444}
7445
Johan Hedberg95fbac82014-02-19 15:18:31 +02007446void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7447{
7448 struct mgmt_ev_new_irk ev;
7449
7450 memset(&ev, 0, sizeof(ev));
7451
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007452 /* For identity resolving keys from devices that are already
7453 * using a public address or static random address, do not
7454 * ask for storing this key. The identity resolving key really
7455 * is only mandatory for devices using resovlable random
7456 * addresses.
7457 *
7458 * Storing all identity resolving keys has the downside that
7459 * they will be also loaded on next boot of they system. More
7460 * identity resolving keys, means more time during scanning is
7461 * needed to actually resolve these addresses.
7462 */
7463 if (bacmp(&irk->rpa, BDADDR_ANY))
7464 ev.store_hint = 0x01;
7465 else
7466 ev.store_hint = 0x00;
7467
Johan Hedberg95fbac82014-02-19 15:18:31 +02007468 bacpy(&ev.rpa, &irk->rpa);
7469 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7470 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7471 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7472
7473 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7474}
7475
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007476void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7477 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007478{
7479 struct mgmt_ev_new_csrk ev;
7480
7481 memset(&ev, 0, sizeof(ev));
7482
7483 /* Devices using resolvable or non-resolvable random addresses
7484 * without providing an indentity resolving key don't require
7485 * to store signature resolving keys. Their addresses will change
7486 * the next time around.
7487 *
7488 * Only when a remote device provides an identity address
7489 * make sure the signature resolving key is stored. So allow
7490 * static random and public addresses here.
7491 */
7492 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7493 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7494 ev.store_hint = 0x00;
7495 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007496 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007497
7498 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7499 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007500 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007501 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7502
7503 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7504}
7505
Andre Guedesffb5a8272014-07-01 18:10:11 -03007506void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007507 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7508 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007509{
7510 struct mgmt_ev_new_conn_param ev;
7511
Johan Hedbergc103aea2014-07-02 17:37:34 +03007512 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7513 return;
7514
Andre Guedesffb5a8272014-07-01 18:10:11 -03007515 memset(&ev, 0, sizeof(ev));
7516 bacpy(&ev.addr.bdaddr, bdaddr);
7517 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007518 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007519 ev.min_interval = cpu_to_le16(min_interval);
7520 ev.max_interval = cpu_to_le16(max_interval);
7521 ev.latency = cpu_to_le16(latency);
7522 ev.timeout = cpu_to_le16(timeout);
7523
7524 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7525}
7526
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007527void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7528 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007529{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007530 char buf[512];
7531 struct mgmt_ev_device_connected *ev = (void *) buf;
7532 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007533
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007534 bacpy(&ev->addr.bdaddr, &conn->dst);
7535 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007536
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007537 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007538
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007539 /* We must ensure that the EIR Data fields are ordered and
7540 * unique. Keep it simple for now and avoid the problem by not
7541 * adding any BR/EDR data to the LE adv.
7542 */
7543 if (conn->le_adv_data_len > 0) {
7544 memcpy(&ev->eir[eir_len],
7545 conn->le_adv_data, conn->le_adv_data_len);
7546 eir_len = conn->le_adv_data_len;
7547 } else {
7548 if (name_len > 0)
7549 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7550 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007551
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007552 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007553 eir_len = eir_append_data(ev->eir, eir_len,
7554 EIR_CLASS_OF_DEV,
7555 conn->dev_class, 3);
7556 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007557
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007558 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007559
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007560 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7561 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007562}
7563
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007564static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007565{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007566 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007567
Johan Hedbergf5818c22014-12-05 13:36:02 +02007568 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007569
7570 *sk = cmd->sk;
7571 sock_hold(*sk);
7572
Johan Hedberga664b5b2011-02-19 12:06:02 -03007573 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007574}
7575
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007576static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007577{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007578 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007579 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007580
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007581 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7582
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007583 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007584 mgmt_pending_remove(cmd);
7585}
7586
Johan Hedberg84c61d92014-08-01 11:13:30 +03007587bool mgmt_powering_down(struct hci_dev *hdev)
7588{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007589 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007590 struct mgmt_mode *cp;
7591
Johan Hedberg333ae952015-03-17 13:48:47 +02007592 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007593 if (!cmd)
7594 return false;
7595
7596 cp = cmd->param;
7597 if (!cp->val)
7598 return true;
7599
7600 return false;
7601}
7602
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007603void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007604 u8 link_type, u8 addr_type, u8 reason,
7605 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007606{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007607 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007608 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007609
Johan Hedberg84c61d92014-08-01 11:13:30 +03007610 /* The connection is still in hci_conn_hash so test for 1
7611 * instead of 0 to know if this is the last one.
7612 */
7613 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7614 cancel_delayed_work(&hdev->power_off);
7615 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007616 }
7617
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007618 if (!mgmt_connected)
7619 return;
7620
Andre Guedes57eb7762013-10-30 19:01:41 -03007621 if (link_type != ACL_LINK && link_type != LE_LINK)
7622 return;
7623
Johan Hedberg744cf192011-11-08 20:40:14 +02007624 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007625
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007626 bacpy(&ev.addr.bdaddr, bdaddr);
7627 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7628 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007629
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007630 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007631
7632 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007633 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007634
Johan Hedberg124f6e32012-02-09 13:50:12 +02007635 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007636 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007637}
7638
Marcel Holtmann78929242013-10-06 23:55:47 -07007639void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7640 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007641{
Andre Guedes3655bba2013-10-30 19:01:40 -03007642 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7643 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007644 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007645
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007646 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7647 hdev);
7648
Johan Hedberg333ae952015-03-17 13:48:47 +02007649 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007650 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007651 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007652
Andre Guedes3655bba2013-10-30 19:01:40 -03007653 cp = cmd->param;
7654
7655 if (bacmp(bdaddr, &cp->addr.bdaddr))
7656 return;
7657
7658 if (cp->addr.type != bdaddr_type)
7659 return;
7660
Johan Hedbergf5818c22014-12-05 13:36:02 +02007661 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007662 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007663}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007664
Marcel Holtmann445608d2013-10-06 23:55:48 -07007665void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7666 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007667{
7668 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007669
Johan Hedberg84c61d92014-08-01 11:13:30 +03007670 /* The connection is still in hci_conn_hash so test for 1
7671 * instead of 0 to know if this is the last one.
7672 */
7673 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7674 cancel_delayed_work(&hdev->power_off);
7675 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007676 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007677
Johan Hedberg4c659c32011-11-07 23:13:39 +02007678 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007679 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007680 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007681
Marcel Holtmann445608d2013-10-06 23:55:48 -07007682 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007683}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007684
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007685void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007686{
7687 struct mgmt_ev_pin_code_request ev;
7688
Johan Hedbergd8457692012-02-17 14:24:57 +02007689 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007690 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007691 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007692
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007693 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007694}
7695
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007696void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7697 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007698{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007699 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007700
Johan Hedberg333ae952015-03-17 13:48:47 +02007701 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007702 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007703 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007704
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007705 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007706 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007707}
7708
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007709void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7710 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007711{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007712 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007713
Johan Hedberg333ae952015-03-17 13:48:47 +02007714 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007715 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007716 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007717
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007718 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007719 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007720}
Johan Hedberga5c29682011-02-19 12:05:57 -03007721
Johan Hedberg744cf192011-11-08 20:40:14 +02007722int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007723 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007724 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007725{
7726 struct mgmt_ev_user_confirm_request ev;
7727
Johan Hedberg744cf192011-11-08 20:40:14 +02007728 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007729
Johan Hedberg272d90d2012-02-09 15:26:12 +02007730 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007731 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007732 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007733 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007734
Johan Hedberg744cf192011-11-08 20:40:14 +02007735 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007736 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007737}
7738
Johan Hedberg272d90d2012-02-09 15:26:12 +02007739int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007740 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007741{
7742 struct mgmt_ev_user_passkey_request ev;
7743
7744 BT_DBG("%s", hdev->name);
7745
Johan Hedberg272d90d2012-02-09 15:26:12 +02007746 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007747 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007748
7749 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007750 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007751}
7752
Brian Gix0df4c182011-11-16 13:53:13 -08007753static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007754 u8 link_type, u8 addr_type, u8 status,
7755 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007756{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007757 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007758
Johan Hedberg333ae952015-03-17 13:48:47 +02007759 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007760 if (!cmd)
7761 return -ENOENT;
7762
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007763 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007764 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007765
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007766 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007767}
7768
Johan Hedberg744cf192011-11-08 20:40:14 +02007769int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007770 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007771{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007772 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007773 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007774}
7775
Johan Hedberg272d90d2012-02-09 15:26:12 +02007776int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007777 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007778{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007779 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007780 status,
7781 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007782}
Johan Hedberg2a611692011-02-19 12:06:00 -03007783
Brian Gix604086b2011-11-23 08:28:33 -08007784int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007785 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007786{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007787 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007788 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007789}
7790
Johan Hedberg272d90d2012-02-09 15:26:12 +02007791int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007792 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007793{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007794 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007795 status,
7796 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007797}
7798
Johan Hedberg92a25252012-09-06 18:39:26 +03007799int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7800 u8 link_type, u8 addr_type, u32 passkey,
7801 u8 entered)
7802{
7803 struct mgmt_ev_passkey_notify ev;
7804
7805 BT_DBG("%s", hdev->name);
7806
7807 bacpy(&ev.addr.bdaddr, bdaddr);
7808 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7809 ev.passkey = __cpu_to_le32(passkey);
7810 ev.entered = entered;
7811
7812 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7813}
7814
Johan Hedberge1e930f2014-09-08 17:09:49 -07007815void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007816{
7817 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007818 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007819 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007820
Johan Hedberge1e930f2014-09-08 17:09:49 -07007821 bacpy(&ev.addr.bdaddr, &conn->dst);
7822 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7823 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007824
Johan Hedberge1e930f2014-09-08 17:09:49 -07007825 cmd = find_pairing(conn);
7826
7827 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7828 cmd ? cmd->sk : NULL);
7829
Johan Hedberga511b352014-12-11 21:45:45 +02007830 if (cmd) {
7831 cmd->cmd_complete(cmd, status);
7832 mgmt_pending_remove(cmd);
7833 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007834}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007835
Marcel Holtmann464996a2013-10-15 14:26:24 -07007836void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007837{
7838 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007839 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007840
7841 if (status) {
7842 u8 mgmt_err = mgmt_status(status);
7843 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007844 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007845 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007846 }
7847
Marcel Holtmann464996a2013-10-15 14:26:24 -07007848 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007849 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007850 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007851 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007852
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007853 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007854 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007855
Johan Hedberg47990ea2012-02-22 11:58:37 +02007856 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007857 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007858
7859 if (match.sk)
7860 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007861}
7862
Johan Hedberg890ea892013-03-15 17:06:52 -05007863static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007864{
Johan Hedberg890ea892013-03-15 17:06:52 -05007865 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007866 struct hci_cp_write_eir cp;
7867
Johan Hedberg976eb202012-10-24 21:12:01 +03007868 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007869 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007870
Johan Hedbergc80da272012-02-22 15:38:48 +02007871 memset(hdev->eir, 0, sizeof(hdev->eir));
7872
Johan Hedbergcacaf522012-02-21 00:52:42 +02007873 memset(&cp, 0, sizeof(cp));
7874
Johan Hedberg890ea892013-03-15 17:06:52 -05007875 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007876}
7877
Marcel Holtmann3e248562013-10-15 14:26:25 -07007878void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007879{
7880 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007881 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007882 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007883
7884 if (status) {
7885 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007886
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007887 if (enable && hci_dev_test_and_clear_flag(hdev,
7888 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007889 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007890 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007891 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007892
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007893 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7894 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007895 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007896 }
7897
7898 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007899 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007900 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007901 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007902 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007903 changed = hci_dev_test_and_clear_flag(hdev,
7904 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007905 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007906 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007907 }
7908
7909 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7910
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007911 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007912 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007913
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007914 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007915 sock_put(match.sk);
7916
Johan Hedberg890ea892013-03-15 17:06:52 -05007917 hci_req_init(&req, hdev);
7918
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007919 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7920 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007921 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7922 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007923 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007924 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007925 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007926 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007927
7928 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007929}
7930
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007931static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007932{
7933 struct cmd_lookup *match = data;
7934
Johan Hedberg90e70452012-02-23 23:09:40 +02007935 if (match->sk == NULL) {
7936 match->sk = cmd->sk;
7937 sock_hold(match->sk);
7938 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007939}
7940
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007941void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7942 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007943{
Johan Hedberg90e70452012-02-23 23:09:40 +02007944 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007945
Johan Hedberg92da6092013-03-15 17:06:55 -05007946 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7947 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7948 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007949
7950 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007951 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7952 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007953
7954 if (match.sk)
7955 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007956}
7957
Marcel Holtmann7667da32013-10-15 14:26:27 -07007958void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007959{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007960 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007961 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007962
Johan Hedberg13928972013-03-15 17:07:00 -05007963 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007964 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007965
7966 memset(&ev, 0, sizeof(ev));
7967 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007968 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007969
Johan Hedberg333ae952015-03-17 13:48:47 +02007970 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007971 if (!cmd) {
7972 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007973
Johan Hedberg13928972013-03-15 17:07:00 -05007974 /* If this is a HCI command related to powering on the
7975 * HCI dev don't send any mgmt signals.
7976 */
Johan Hedberg333ae952015-03-17 13:48:47 +02007977 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007978 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007979 }
7980
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007981 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7982 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007983}
Szymon Jancc35938b2011-03-22 13:12:21 +01007984
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007985static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7986{
7987 int i;
7988
7989 for (i = 0; i < uuid_count; i++) {
7990 if (!memcmp(uuid, uuids[i], 16))
7991 return true;
7992 }
7993
7994 return false;
7995}
7996
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007997static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7998{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007999 u16 parsed = 0;
8000
8001 while (parsed < eir_len) {
8002 u8 field_len = eir[0];
8003 u8 uuid[16];
8004 int i;
8005
8006 if (field_len == 0)
8007 break;
8008
8009 if (eir_len - parsed < field_len + 1)
8010 break;
8011
8012 switch (eir[1]) {
8013 case EIR_UUID16_ALL:
8014 case EIR_UUID16_SOME:
8015 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008016 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008017 uuid[13] = eir[i + 3];
8018 uuid[12] = eir[i + 2];
8019 if (has_uuid(uuid, uuid_count, uuids))
8020 return true;
8021 }
8022 break;
8023 case EIR_UUID32_ALL:
8024 case EIR_UUID32_SOME:
8025 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008026 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008027 uuid[15] = eir[i + 5];
8028 uuid[14] = eir[i + 4];
8029 uuid[13] = eir[i + 3];
8030 uuid[12] = eir[i + 2];
8031 if (has_uuid(uuid, uuid_count, uuids))
8032 return true;
8033 }
8034 break;
8035 case EIR_UUID128_ALL:
8036 case EIR_UUID128_SOME:
8037 for (i = 0; i + 17 <= field_len; i += 16) {
8038 memcpy(uuid, eir + i + 2, 16);
8039 if (has_uuid(uuid, uuid_count, uuids))
8040 return true;
8041 }
8042 break;
8043 }
8044
8045 parsed += field_len + 1;
8046 eir += field_len + 1;
8047 }
8048
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008049 return false;
8050}
8051
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008052static void restart_le_scan(struct hci_dev *hdev)
8053{
8054 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008055 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008056 return;
8057
8058 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8059 hdev->discovery.scan_start +
8060 hdev->discovery.scan_duration))
8061 return;
8062
8063 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8064 DISCOV_LE_RESTART_DELAY);
8065}
8066
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008067static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8068 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8069{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008070 /* If a RSSI threshold has been specified, and
8071 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8072 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8073 * is set, let it through for further processing, as we might need to
8074 * restart the scan.
8075 *
8076 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8077 * the results are also dropped.
8078 */
8079 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8080 (rssi == HCI_RSSI_INVALID ||
8081 (rssi < hdev->discovery.rssi &&
8082 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8083 return false;
8084
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008085 if (hdev->discovery.uuid_count != 0) {
8086 /* If a list of UUIDs is provided in filter, results with no
8087 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008088 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008089 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8090 hdev->discovery.uuids) &&
8091 !eir_has_uuids(scan_rsp, scan_rsp_len,
8092 hdev->discovery.uuid_count,
8093 hdev->discovery.uuids))
8094 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008095 }
8096
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008097 /* If duplicate filtering does not report RSSI changes, then restart
8098 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008099 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008100 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8101 restart_le_scan(hdev);
8102
8103 /* Validate RSSI value against the RSSI threshold once more. */
8104 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8105 rssi < hdev->discovery.rssi)
8106 return false;
8107 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008108
8109 return true;
8110}
8111
Marcel Holtmann901801b2013-10-06 23:55:51 -07008112void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008113 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8114 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008115{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008116 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008117 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008118 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008119
Johan Hedberg75ce2082014-07-02 22:42:01 +03008120 /* Don't send events for a non-kernel initiated discovery. With
8121 * LE one exception is if we have pend_le_reports > 0 in which
8122 * case we're doing passive scanning and want these events.
8123 */
8124 if (!hci_discovery_active(hdev)) {
8125 if (link_type == ACL_LINK)
8126 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008127 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008128 return;
8129 }
Andre Guedes12602d02013-04-30 15:29:40 -03008130
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008131 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008132 /* We are using service discovery */
8133 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8134 scan_rsp_len))
8135 return;
8136 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008137
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008138 /* Make sure that the buffer is big enough. The 5 extra bytes
8139 * are for the potential CoD field.
8140 */
8141 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008142 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008143
Johan Hedberg1dc06092012-01-15 21:01:23 +02008144 memset(buf, 0, sizeof(buf));
8145
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008146 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8147 * RSSI value was reported as 0 when not available. This behavior
8148 * is kept when using device discovery. This is required for full
8149 * backwards compatibility with the API.
8150 *
8151 * However when using service discovery, the value 127 will be
8152 * returned when the RSSI is not available.
8153 */
Szymon Janc91200e92015-01-22 16:57:05 +01008154 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8155 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008156 rssi = 0;
8157
Johan Hedberg841c5642014-07-07 12:45:54 +03008158 bacpy(&ev->addr.bdaddr, bdaddr);
8159 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008160 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008161 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008162
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008163 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008164 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008165 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008166
Johan Hedberg1dc06092012-01-15 21:01:23 +02008167 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8168 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008169 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008170
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008171 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008172 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008173 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008174
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008175 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8176 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008177
Marcel Holtmann901801b2013-10-06 23:55:51 -07008178 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008179}
Johan Hedberga88a9652011-03-30 13:18:12 +03008180
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008181void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8182 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008183{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008184 struct mgmt_ev_device_found *ev;
8185 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8186 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008187
Johan Hedbergb644ba32012-01-17 21:48:47 +02008188 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008189
Johan Hedbergb644ba32012-01-17 21:48:47 +02008190 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008191
Johan Hedbergb644ba32012-01-17 21:48:47 +02008192 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008193 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008194 ev->rssi = rssi;
8195
8196 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008197 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008198
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008199 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008200
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008201 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008202}
Johan Hedberg314b2382011-04-27 10:29:57 -04008203
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008204void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008205{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008206 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008207
Andre Guedes343fb142011-11-22 17:14:19 -03008208 BT_DBG("%s discovering %u", hdev->name, discovering);
8209
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008210 memset(&ev, 0, sizeof(ev));
8211 ev.type = hdev->discovery.type;
8212 ev.discovering = discovering;
8213
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008214 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008215}
Antti Julku5e762442011-08-25 16:48:02 +03008216
Marcel Holtmann1904a852015-01-11 13:50:44 -08008217static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008218{
8219 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008220}
8221
8222void mgmt_reenable_advertising(struct hci_dev *hdev)
8223{
8224 struct hci_request req;
8225
Arman Uguray24b4f382015-03-23 15:57:12 -07008226 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8227 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008228 return;
8229
8230 hci_req_init(&req, hdev);
8231 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008232 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008233}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008234
8235static struct hci_mgmt_chan chan = {
8236 .channel = HCI_CHANNEL_CONTROL,
8237 .handler_count = ARRAY_SIZE(mgmt_handlers),
8238 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008239 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008240};
8241
8242int mgmt_init(void)
8243{
8244 return hci_mgmt_chan_register(&chan);
8245}
8246
8247void mgmt_exit(void)
8248{
8249 hci_mgmt_chan_unregister(&chan);
8250}