blob: de321b9087e75c133401dc9fc2a54ecf3317f5cc [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg71290692015-02-20 13:26:23 +020032#include <net/bluetooth/hci_sock.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030033#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020034#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070035
Johan Hedberg0857dd32014-12-19 13:40:20 +020036#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070037#include "smp.h"
Johan Hedberga380b6c2015-03-17 13:48:48 +020038#include "mgmt_util.h"
Johan Hedberg03811012010-12-08 00:21:06 +020039
Johan Hedberg2da9c552012-02-17 14:39:28 +020040#define MGMT_VERSION 1
Marcel Holtmannbeb1c212015-03-10 14:04:52 -070041#define MGMT_REVISION 9
Johan Hedberg02d98122010-12-13 21:07:04 +020042
Johan Hedberge70bb2e2012-02-13 16:59:33 +020043static const u16 mgmt_commands[] = {
44 MGMT_OP_READ_INDEX_LIST,
45 MGMT_OP_READ_INFO,
46 MGMT_OP_SET_POWERED,
47 MGMT_OP_SET_DISCOVERABLE,
48 MGMT_OP_SET_CONNECTABLE,
49 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030050 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020051 MGMT_OP_SET_LINK_SECURITY,
52 MGMT_OP_SET_SSP,
53 MGMT_OP_SET_HS,
54 MGMT_OP_SET_LE,
55 MGMT_OP_SET_DEV_CLASS,
56 MGMT_OP_SET_LOCAL_NAME,
57 MGMT_OP_ADD_UUID,
58 MGMT_OP_REMOVE_UUID,
59 MGMT_OP_LOAD_LINK_KEYS,
60 MGMT_OP_LOAD_LONG_TERM_KEYS,
61 MGMT_OP_DISCONNECT,
62 MGMT_OP_GET_CONNECTIONS,
63 MGMT_OP_PIN_CODE_REPLY,
64 MGMT_OP_PIN_CODE_NEG_REPLY,
65 MGMT_OP_SET_IO_CAPABILITY,
66 MGMT_OP_PAIR_DEVICE,
67 MGMT_OP_CANCEL_PAIR_DEVICE,
68 MGMT_OP_UNPAIR_DEVICE,
69 MGMT_OP_USER_CONFIRM_REPLY,
70 MGMT_OP_USER_CONFIRM_NEG_REPLY,
71 MGMT_OP_USER_PASSKEY_REPLY,
72 MGMT_OP_USER_PASSKEY_NEG_REPLY,
73 MGMT_OP_READ_LOCAL_OOB_DATA,
74 MGMT_OP_ADD_REMOTE_OOB_DATA,
75 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
76 MGMT_OP_START_DISCOVERY,
77 MGMT_OP_STOP_DISCOVERY,
78 MGMT_OP_CONFIRM_NAME,
79 MGMT_OP_BLOCK_DEVICE,
80 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070081 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030082 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030083 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070084 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070085 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080086 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080087 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020088 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020089 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020090 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030091 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020092 MGMT_OP_ADD_DEVICE,
93 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030094 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020095 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020096 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020097 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020098 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010099 MGMT_OP_START_SERVICE_DISCOVERY,
Marcel Holtmann4f0f1552015-03-14 22:43:19 -0700100 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann96f14742015-03-14 19:27:57 -0700101 MGMT_OP_READ_EXT_INDEX_LIST,
Marcel Holtmannd3d53052015-03-14 20:53:25 -0700102 MGMT_OP_READ_ADV_FEATURES,
Arman Uguray24b4f382015-03-23 15:57:12 -0700103 MGMT_OP_ADD_ADVERTISING,
Arman Ugurayda9293352015-03-23 15:57:13 -0700104 MGMT_OP_REMOVE_ADVERTISING,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200105};
106
107static const u16 mgmt_events[] = {
108 MGMT_EV_CONTROLLER_ERROR,
109 MGMT_EV_INDEX_ADDED,
110 MGMT_EV_INDEX_REMOVED,
111 MGMT_EV_NEW_SETTINGS,
112 MGMT_EV_CLASS_OF_DEV_CHANGED,
113 MGMT_EV_LOCAL_NAME_CHANGED,
114 MGMT_EV_NEW_LINK_KEY,
115 MGMT_EV_NEW_LONG_TERM_KEY,
116 MGMT_EV_DEVICE_CONNECTED,
117 MGMT_EV_DEVICE_DISCONNECTED,
118 MGMT_EV_CONNECT_FAILED,
119 MGMT_EV_PIN_CODE_REQUEST,
120 MGMT_EV_USER_CONFIRM_REQUEST,
121 MGMT_EV_USER_PASSKEY_REQUEST,
122 MGMT_EV_AUTH_FAILED,
123 MGMT_EV_DEVICE_FOUND,
124 MGMT_EV_DISCOVERING,
125 MGMT_EV_DEVICE_BLOCKED,
126 MGMT_EV_DEVICE_UNBLOCKED,
127 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300128 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800129 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700130 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200131 MGMT_EV_DEVICE_ADDED,
132 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300133 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200134 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200135 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200136 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700137 MGMT_EV_EXT_INDEX_ADDED,
138 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700139 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Arman Uguray24b4f382015-03-23 15:57:12 -0700140 MGMT_EV_ADVERTISING_ADDED,
141 MGMT_EV_ADVERTISING_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200142};
143
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700144static const u16 mgmt_untrusted_commands[] = {
145 MGMT_OP_READ_INDEX_LIST,
146 MGMT_OP_READ_INFO,
147 MGMT_OP_READ_UNCONF_INDEX_LIST,
148 MGMT_OP_READ_CONFIG_INFO,
149 MGMT_OP_READ_EXT_INDEX_LIST,
150};
151
152static const u16 mgmt_untrusted_events[] = {
153 MGMT_EV_INDEX_ADDED,
154 MGMT_EV_INDEX_REMOVED,
155 MGMT_EV_NEW_SETTINGS,
156 MGMT_EV_CLASS_OF_DEV_CHANGED,
157 MGMT_EV_LOCAL_NAME_CHANGED,
158 MGMT_EV_UNCONF_INDEX_ADDED,
159 MGMT_EV_UNCONF_INDEX_REMOVED,
160 MGMT_EV_NEW_CONFIG_OPTIONS,
161 MGMT_EV_EXT_INDEX_ADDED,
162 MGMT_EV_EXT_INDEX_REMOVED,
163};
164
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800165#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200166
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200167#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
168 "\x00\x00\x00\x00\x00\x00\x00\x00"
169
Johan Hedbergca69b792011-11-11 18:10:00 +0200170/* HCI to MGMT error code conversion table */
171static u8 mgmt_status_table[] = {
172 MGMT_STATUS_SUCCESS,
173 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
174 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
175 MGMT_STATUS_FAILED, /* Hardware Failure */
176 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
177 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200178 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200179 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
180 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
181 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
182 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
183 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
184 MGMT_STATUS_BUSY, /* Command Disallowed */
185 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
186 MGMT_STATUS_REJECTED, /* Rejected Security */
187 MGMT_STATUS_REJECTED, /* Rejected Personal */
188 MGMT_STATUS_TIMEOUT, /* Host Timeout */
189 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
190 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
191 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
192 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
193 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
194 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
195 MGMT_STATUS_BUSY, /* Repeated Attempts */
196 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
197 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
198 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
199 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
200 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
201 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
202 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
203 MGMT_STATUS_FAILED, /* Unspecified Error */
204 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
205 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
206 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
207 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
208 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
209 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
210 MGMT_STATUS_FAILED, /* Unit Link Key Used */
211 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
212 MGMT_STATUS_TIMEOUT, /* Instant Passed */
213 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
214 MGMT_STATUS_FAILED, /* Transaction Collision */
215 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
216 MGMT_STATUS_REJECTED, /* QoS Rejected */
217 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
218 MGMT_STATUS_REJECTED, /* Insufficient Security */
219 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
220 MGMT_STATUS_BUSY, /* Role Switch Pending */
221 MGMT_STATUS_FAILED, /* Slot Violation */
222 MGMT_STATUS_FAILED, /* Role Switch Failed */
223 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
224 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
225 MGMT_STATUS_BUSY, /* Host Busy Pairing */
226 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
227 MGMT_STATUS_BUSY, /* Controller Busy */
228 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
229 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
230 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
231 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
232 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
233};
234
235static u8 mgmt_status(u8 hci_status)
236{
237 if (hci_status < ARRAY_SIZE(mgmt_status_table))
238 return mgmt_status_table[hci_status];
239
240 return MGMT_STATUS_FAILED;
241}
242
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700243static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
244 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700245{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700246 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
247 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700248}
249
Marcel Holtmann72000df2015-03-16 16:11:21 -0700250static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
251 u16 len, int flag, struct sock *skip_sk)
252{
253 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
254 flag, skip_sk);
255}
256
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700257static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
258 u16 len, struct sock *skip_sk)
259{
260 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
261 HCI_MGMT_GENERIC_EVENTS, skip_sk);
262}
263
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200264static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
265 struct sock *skip_sk)
266{
267 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700268 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200269}
270
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300271static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
272 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200273{
274 struct mgmt_rp_read_version rp;
275
276 BT_DBG("sock %p", sk);
277
278 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700279 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200280
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200281 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
282 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200283}
284
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300285static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
286 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200287{
288 struct mgmt_rp_read_commands *rp;
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700289 u16 num_commands, num_events;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200290 size_t rp_size;
291 int i, err;
292
293 BT_DBG("sock %p", sk);
294
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700295 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
296 num_commands = ARRAY_SIZE(mgmt_commands);
297 num_events = ARRAY_SIZE(mgmt_events);
298 } else {
299 num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
300 num_events = ARRAY_SIZE(mgmt_untrusted_events);
301 }
302
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200303 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
304
305 rp = kmalloc(rp_size, GFP_KERNEL);
306 if (!rp)
307 return -ENOMEM;
308
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700309 rp->num_commands = cpu_to_le16(num_commands);
310 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700312 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
313 __le16 *opcode = rp->opcodes;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200314
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700315 for (i = 0; i < num_commands; i++, opcode++)
316 put_unaligned_le16(mgmt_commands[i], opcode);
317
318 for (i = 0; i < num_events; i++, opcode++)
319 put_unaligned_le16(mgmt_events[i], opcode);
320 } else {
321 __le16 *opcode = rp->opcodes;
322
323 for (i = 0; i < num_commands; i++, opcode++)
324 put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
325
326 for (i = 0; i < num_events; i++, opcode++)
327 put_unaligned_le16(mgmt_untrusted_events[i], opcode);
328 }
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200329
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200330 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
331 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 kfree(rp);
333
334 return err;
335}
336
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300337static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
338 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200341 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200342 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200343 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300344 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345
346 BT_DBG("sock %p", sk);
347
348 read_lock(&hci_dev_list_lock);
349
350 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300351 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200352 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700353 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700354 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200355 }
356
Johan Hedberga38528f2011-01-22 06:46:43 +0200357 rp_len = sizeof(*rp) + (2 * count);
358 rp = kmalloc(rp_len, GFP_ATOMIC);
359 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100360 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100362 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363
Johan Hedberg476e44c2012-10-19 20:10:46 +0300364 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200365 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700366 if (hci_dev_test_flag(d, HCI_SETUP) ||
367 hci_dev_test_flag(d, HCI_CONFIG) ||
368 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200369 continue;
370
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200371 /* Devices marked as raw-only are neither configured
372 * nor unconfigured controllers.
373 */
374 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700375 continue;
376
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200377 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700378 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700379 rp->index[count++] = cpu_to_le16(d->id);
380 BT_DBG("Added hci%u", d->id);
381 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 }
383
Johan Hedberg476e44c2012-10-19 20:10:46 +0300384 rp->num_controllers = cpu_to_le16(count);
385 rp_len = sizeof(*rp) + (2 * count);
386
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200387 read_unlock(&hci_dev_list_lock);
388
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200389 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
390 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200391
Johan Hedberga38528f2011-01-22 06:46:43 +0200392 kfree(rp);
393
394 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200395}
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
398 void *data, u16 data_len)
399{
400 struct mgmt_rp_read_unconf_index_list *rp;
401 struct hci_dev *d;
402 size_t rp_len;
403 u16 count;
404 int err;
405
406 BT_DBG("sock %p", sk);
407
408 read_lock(&hci_dev_list_lock);
409
410 count = 0;
411 list_for_each_entry(d, &hci_dev_list, list) {
412 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700413 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200414 count++;
415 }
416
417 rp_len = sizeof(*rp) + (2 * count);
418 rp = kmalloc(rp_len, GFP_ATOMIC);
419 if (!rp) {
420 read_unlock(&hci_dev_list_lock);
421 return -ENOMEM;
422 }
423
424 count = 0;
425 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700426 if (hci_dev_test_flag(d, HCI_SETUP) ||
427 hci_dev_test_flag(d, HCI_CONFIG) ||
428 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200429 continue;
430
431 /* Devices marked as raw-only are neither configured
432 * nor unconfigured controllers.
433 */
434 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
435 continue;
436
437 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700438 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200439 rp->index[count++] = cpu_to_le16(d->id);
440 BT_DBG("Added hci%u", d->id);
441 }
442 }
443
444 rp->num_controllers = cpu_to_le16(count);
445 rp_len = sizeof(*rp) + (2 * count);
446
447 read_unlock(&hci_dev_list_lock);
448
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200449 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
450 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200451
452 kfree(rp);
453
454 return err;
455}
456
Marcel Holtmann96f14742015-03-14 19:27:57 -0700457static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
458 void *data, u16 data_len)
459{
460 struct mgmt_rp_read_ext_index_list *rp;
461 struct hci_dev *d;
462 size_t rp_len;
463 u16 count;
464 int err;
465
466 BT_DBG("sock %p", sk);
467
468 read_lock(&hci_dev_list_lock);
469
470 count = 0;
471 list_for_each_entry(d, &hci_dev_list, list) {
472 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
473 count++;
474 }
475
476 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
477 rp = kmalloc(rp_len, GFP_ATOMIC);
478 if (!rp) {
479 read_unlock(&hci_dev_list_lock);
480 return -ENOMEM;
481 }
482
483 count = 0;
484 list_for_each_entry(d, &hci_dev_list, list) {
485 if (hci_dev_test_flag(d, HCI_SETUP) ||
486 hci_dev_test_flag(d, HCI_CONFIG) ||
487 hci_dev_test_flag(d, HCI_USER_CHANNEL))
488 continue;
489
490 /* Devices marked as raw-only are neither configured
491 * nor unconfigured controllers.
492 */
493 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
494 continue;
495
496 if (d->dev_type == HCI_BREDR) {
497 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
498 rp->entry[count].type = 0x01;
499 else
500 rp->entry[count].type = 0x00;
501 } else if (d->dev_type == HCI_AMP) {
502 rp->entry[count].type = 0x02;
503 } else {
504 continue;
505 }
506
507 rp->entry[count].bus = d->bus;
508 rp->entry[count++].index = cpu_to_le16(d->id);
509 BT_DBG("Added hci%u", d->id);
510 }
511
512 rp->num_controllers = cpu_to_le16(count);
513 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
514
515 read_unlock(&hci_dev_list_lock);
516
517 /* If this command is called at least once, then all the
518 * default index and unconfigured index events are disabled
519 * and from now on only extended index events are used.
520 */
521 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
522 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
523 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
524
525 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
526 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
527
528 kfree(rp);
529
530 return err;
531}
532
Marcel Holtmanndbece372014-07-04 18:11:55 +0200533static bool is_configured(struct hci_dev *hdev)
534{
535 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700536 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200537 return false;
538
539 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
540 !bacmp(&hdev->public_addr, BDADDR_ANY))
541 return false;
542
543 return true;
544}
545
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200546static __le32 get_missing_options(struct hci_dev *hdev)
547{
548 u32 options = 0;
549
Marcel Holtmanndbece372014-07-04 18:11:55 +0200550 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700551 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200552 options |= MGMT_OPTION_EXTERNAL_CONFIG;
553
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200554 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
555 !bacmp(&hdev->public_addr, BDADDR_ANY))
556 options |= MGMT_OPTION_PUBLIC_ADDRESS;
557
558 return cpu_to_le32(options);
559}
560
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200561static int new_options(struct hci_dev *hdev, struct sock *skip)
562{
563 __le32 options = get_missing_options(hdev);
564
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700565 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
566 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200567}
568
Marcel Holtmanndbece372014-07-04 18:11:55 +0200569static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
570{
571 __le32 options = get_missing_options(hdev);
572
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200573 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
574 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200575}
576
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200577static int read_config_info(struct sock *sk, struct hci_dev *hdev,
578 void *data, u16 data_len)
579{
580 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200581 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200582
583 BT_DBG("sock %p %s", sk, hdev->name);
584
585 hci_dev_lock(hdev);
586
587 memset(&rp, 0, sizeof(rp));
588 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200589
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200590 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
591 options |= MGMT_OPTION_EXTERNAL_CONFIG;
592
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200593 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200594 options |= MGMT_OPTION_PUBLIC_ADDRESS;
595
596 rp.supported_options = cpu_to_le32(options);
597 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200598
599 hci_dev_unlock(hdev);
600
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200601 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
602 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200603}
604
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200606{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200608
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300610 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800611 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300612 settings |= MGMT_SETTING_CONNECTABLE;
613 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200614
Andre Guedesed3fa312012-07-24 15:03:46 -0300615 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500616 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
617 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_BREDR;
619 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700620
621 if (lmp_ssp_capable(hdev)) {
622 settings |= MGMT_SETTING_SSP;
623 settings |= MGMT_SETTING_HS;
624 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800625
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800626 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700628 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100629
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300630 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200631 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300632 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300633 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800635 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300636 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200637
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200638 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
639 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200640 settings |= MGMT_SETTING_CONFIGURATION;
641
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200642 return settings;
643}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200644
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200645static u32 get_current_settings(struct hci_dev *hdev)
646{
647 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200648
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200649 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100650 settings |= MGMT_SETTING_POWERED;
651
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700652 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200653 settings |= MGMT_SETTING_CONNECTABLE;
654
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700655 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500656 settings |= MGMT_SETTING_FAST_CONNECTABLE;
657
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700658 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200659 settings |= MGMT_SETTING_DISCOVERABLE;
660
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700661 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300662 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200663
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700664 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200665 settings |= MGMT_SETTING_BREDR;
666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700667 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200668 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700670 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200672
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700673 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200674 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200675
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700676 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200677 settings |= MGMT_SETTING_HS;
678
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700679 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300680 settings |= MGMT_SETTING_ADVERTISING;
681
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700682 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800683 settings |= MGMT_SETTING_SECURE_CONN;
684
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700685 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800686 settings |= MGMT_SETTING_DEBUG_KEYS;
687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700688 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200689 settings |= MGMT_SETTING_PRIVACY;
690
Marcel Holtmann93690c22015-03-06 10:11:21 -0800691 /* The current setting for static address has two purposes. The
692 * first is to indicate if the static address will be used and
693 * the second is to indicate if it is actually set.
694 *
695 * This means if the static address is not configured, this flag
Marcel Holtmann08dc0e92015-03-25 18:32:13 -0700696 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800697 * address is actually used decides if the flag is set or not.
698 *
699 * For single mode LE only controllers and dual-mode controllers
700 * with BR/EDR disabled, the existence of the static address will
701 * be evaluated.
702 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700703 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700704 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
706 if (bacmp(&hdev->static_addr, BDADDR_ANY))
707 settings |= MGMT_SETTING_STATIC_ADDRESS;
708 }
709
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200710 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200711}
712
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300713#define PNP_INFO_SVCLASS_ID 0x1200
714
Johan Hedberg213202e2013-01-27 00:31:33 +0200715static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 4)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 u16 uuid16;
725
726 if (uuid->size != 16)
727 continue;
728
729 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
730 if (uuid16 < 0x1100)
731 continue;
732
733 if (uuid16 == PNP_INFO_SVCLASS_ID)
734 continue;
735
736 if (!uuids_start) {
737 uuids_start = ptr;
738 uuids_start[0] = 1;
739 uuids_start[1] = EIR_UUID16_ALL;
740 ptr += 2;
741 }
742
743 /* Stop if not enough space to put next UUID */
744 if ((ptr - data) + sizeof(u16) > len) {
745 uuids_start[1] = EIR_UUID16_SOME;
746 break;
747 }
748
749 *ptr++ = (uuid16 & 0x00ff);
750 *ptr++ = (uuid16 & 0xff00) >> 8;
751 uuids_start[0] += sizeof(uuid16);
752 }
753
754 return ptr;
755}
756
Johan Hedbergcdf19632013-01-27 00:31:34 +0200757static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
758{
759 u8 *ptr = data, *uuids_start = NULL;
760 struct bt_uuid *uuid;
761
762 if (len < 6)
763 return ptr;
764
765 list_for_each_entry(uuid, &hdev->uuids, list) {
766 if (uuid->size != 32)
767 continue;
768
769 if (!uuids_start) {
770 uuids_start = ptr;
771 uuids_start[0] = 1;
772 uuids_start[1] = EIR_UUID32_ALL;
773 ptr += 2;
774 }
775
776 /* Stop if not enough space to put next UUID */
777 if ((ptr - data) + sizeof(u32) > len) {
778 uuids_start[1] = EIR_UUID32_SOME;
779 break;
780 }
781
782 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
783 ptr += sizeof(u32);
784 uuids_start[0] += sizeof(u32);
785 }
786
787 return ptr;
788}
789
Johan Hedbergc00d5752013-01-27 00:31:35 +0200790static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
791{
792 u8 *ptr = data, *uuids_start = NULL;
793 struct bt_uuid *uuid;
794
795 if (len < 18)
796 return ptr;
797
798 list_for_each_entry(uuid, &hdev->uuids, list) {
799 if (uuid->size != 128)
800 continue;
801
802 if (!uuids_start) {
803 uuids_start = ptr;
804 uuids_start[0] = 1;
805 uuids_start[1] = EIR_UUID128_ALL;
806 ptr += 2;
807 }
808
809 /* Stop if not enough space to put next UUID */
810 if ((ptr - data) + 16 > len) {
811 uuids_start[1] = EIR_UUID128_SOME;
812 break;
813 }
814
815 memcpy(ptr, uuid->uuid, 16);
816 ptr += 16;
817 uuids_start[0] += 16;
818 }
819
820 return ptr;
821}
822
Johan Hedberg333ae952015-03-17 13:48:47 +0200823static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
824{
825 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
826}
827
Johan Hedberg333ae952015-03-17 13:48:47 +0200828static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
829 struct hci_dev *hdev,
830 const void *data)
831{
832 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
833}
834
Arman Uguray4117ed72015-03-23 15:57:14 -0700835static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700836{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700837 u8 ad_len = 0;
838 size_t name_len;
839
840 name_len = strlen(hdev->dev_name);
841 if (name_len > 0) {
842 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
843
844 if (name_len > max_len) {
845 name_len = max_len;
846 ptr[1] = EIR_NAME_SHORT;
847 } else
848 ptr[1] = EIR_NAME_COMPLETE;
849
850 ptr[0] = name_len + 1;
851
852 memcpy(ptr + 2, hdev->dev_name, name_len);
853
854 ad_len += (name_len + 2);
855 ptr += (name_len + 2);
856 }
857
858 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700859}
860
Arman Uguray4117ed72015-03-23 15:57:14 -0700861static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
862{
863 /* TODO: Set the appropriate entries based on advertising instance flags
864 * here once flags other than 0 are supported.
865 */
866 memcpy(ptr, hdev->adv_instance.scan_rsp_data,
867 hdev->adv_instance.scan_rsp_len);
868
869 return hdev->adv_instance.scan_rsp_len;
870}
871
872static void update_scan_rsp_data_for_instance(struct hci_request *req,
873 u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700874{
875 struct hci_dev *hdev = req->hdev;
876 struct hci_cp_le_set_scan_rsp_data cp;
877 u8 len;
878
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700880 return;
881
882 memset(&cp, 0, sizeof(cp));
883
Arman Uguray4117ed72015-03-23 15:57:14 -0700884 if (instance)
885 len = create_instance_scan_rsp_data(hdev, cp.data);
886 else
887 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700888
Johan Hedbergeb438b52013-10-16 15:31:07 +0300889 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700890 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700891 return;
892
Johan Hedbergeb438b52013-10-16 15:31:07 +0300893 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
894 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700895
896 cp.length = len;
897
898 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
899}
900
Arman Uguray4117ed72015-03-23 15:57:14 -0700901static void update_scan_rsp_data(struct hci_request *req)
902{
903 struct hci_dev *hdev = req->hdev;
904 u8 instance;
905
906 /* The "Set Advertising" setting supersedes the "Add Advertising"
907 * setting. Here we set the scan response data based on which
908 * setting was set. When neither apply, default to the global settings,
909 * represented by instance "0".
910 */
911 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
912 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
913 instance = 0x01;
914 else
915 instance = 0x00;
916
917 update_scan_rsp_data_for_instance(req, instance);
918}
919
Johan Hedberg9a43e252013-10-20 19:00:07 +0300920static u8 get_adv_discov_flags(struct hci_dev *hdev)
921{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200922 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300923
924 /* If there's a pending mgmt command the flags will not yet have
925 * their final values, so check for this first.
926 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200927 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300928 if (cmd) {
929 struct mgmt_mode *cp = cmd->param;
930 if (cp->val == 0x01)
931 return LE_AD_GENERAL;
932 else if (cp->val == 0x02)
933 return LE_AD_LIMITED;
934 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700935 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300936 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700937 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300938 return LE_AD_GENERAL;
939 }
940
941 return 0;
942}
943
Arman Uguray24b4f382015-03-23 15:57:12 -0700944static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700945{
946 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700947
Johan Hedberg9a43e252013-10-20 19:00:07 +0300948 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700949
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700950 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700951 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700952
953 if (flags) {
954 BT_DBG("adv flags 0x%02x", flags);
955
956 ptr[0] = 2;
957 ptr[1] = EIR_FLAGS;
958 ptr[2] = flags;
959
960 ad_len += 3;
961 ptr += 3;
962 }
963
964 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
965 ptr[0] = 2;
966 ptr[1] = EIR_TX_POWER;
967 ptr[2] = (u8) hdev->adv_tx_power;
968
969 ad_len += 3;
970 ptr += 3;
971 }
972
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700973 return ad_len;
974}
975
Arman Uguray24b4f382015-03-23 15:57:12 -0700976static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
977{
Arman Ugurayb44133f2015-03-25 18:53:41 -0700978 u8 ad_len = 0, flags = 0;
979
Arman Uguray807ec772015-03-25 18:53:42 -0700980 /* The Add Advertising command allows userspace to set both the general
981 * and limited discoverable flags.
982 */
Arman Ugurayb44133f2015-03-25 18:53:41 -0700983 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV)
984 flags |= LE_AD_GENERAL;
985
Arman Uguray807ec772015-03-25 18:53:42 -0700986 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
987 flags |= LE_AD_LIMITED;
988
Arman Uguray67e0c0c2015-03-25 18:53:43 -0700989 if (flags || (hdev->adv_instance.flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
990 /* If a discovery flag wasn't provided, simply use the global
991 * settings.
992 */
993 if (!flags)
994 flags |= get_adv_discov_flags(hdev);
995
Arman Ugurayb44133f2015-03-25 18:53:41 -0700996 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
997 flags |= LE_AD_NO_BREDR;
998
999 ptr[0] = 0x02;
1000 ptr[1] = EIR_FLAGS;
1001 ptr[2] = flags;
1002
1003 ad_len += 3;
1004 ptr += 3;
1005 }
1006
Arman Uguray5507e352015-03-25 18:53:44 -07001007 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1008 (hdev->adv_instance.flags & MGMT_ADV_FLAG_TX_POWER)) {
1009 ptr[0] = 0x02;
1010 ptr[1] = EIR_TX_POWER;
1011 ptr[2] = (u8)hdev->adv_tx_power;
1012
1013 ad_len += 3;
1014 ptr += 3;
1015 }
1016
Arman Uguray24b4f382015-03-23 15:57:12 -07001017 memcpy(ptr, hdev->adv_instance.adv_data,
1018 hdev->adv_instance.adv_data_len);
Arman Ugurayb44133f2015-03-25 18:53:41 -07001019 ad_len += hdev->adv_instance.adv_data_len;
Arman Uguray24b4f382015-03-23 15:57:12 -07001020
Arman Ugurayb44133f2015-03-25 18:53:41 -07001021 return ad_len;
Arman Uguray24b4f382015-03-23 15:57:12 -07001022}
1023
1024static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001025{
1026 struct hci_dev *hdev = req->hdev;
1027 struct hci_cp_le_set_adv_data cp;
1028 u8 len;
1029
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001030 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001031 return;
1032
1033 memset(&cp, 0, sizeof(cp));
1034
Arman Uguray24b4f382015-03-23 15:57:12 -07001035 if (instance)
1036 len = create_instance_adv_data(hdev, cp.data);
1037 else
1038 len = create_default_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001039
Arman Uguray24b4f382015-03-23 15:57:12 -07001040 /* There's nothing to do if the data hasn't changed */
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001041 if (hdev->adv_data_len == len &&
1042 memcmp(cp.data, hdev->adv_data, len) == 0)
1043 return;
1044
1045 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1046 hdev->adv_data_len = len;
1047
1048 cp.length = len;
1049
1050 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1051}
1052
Arman Uguraye7a685d2015-03-25 18:53:40 -07001053static u8 get_current_adv_instance(struct hci_dev *hdev)
Arman Uguray24b4f382015-03-23 15:57:12 -07001054{
Arman Uguray24b4f382015-03-23 15:57:12 -07001055 /* The "Set Advertising" setting supersedes the "Add Advertising"
1056 * setting. Here we set the advertising data based on which
1057 * setting was set. When neither apply, default to the global settings,
1058 * represented by instance "0".
1059 */
1060 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
1061 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Arman Uguraye7a685d2015-03-25 18:53:40 -07001062 return 0x01;
1063
1064 return 0x00;
1065}
1066
1067static bool get_connectable(struct hci_dev *hdev)
1068{
1069 struct mgmt_pending_cmd *cmd;
1070
1071 /* If there's a pending mgmt command the flag will not yet have
1072 * it's final value, so check for this first.
1073 */
1074 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1075 if (cmd) {
1076 struct mgmt_mode *cp = cmd->param;
1077
1078 return cp->val;
1079 }
1080
1081 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
1082}
1083
1084static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
1085{
1086 u32 flags;
1087
1088 if (instance > 0x01)
1089 return 0;
1090
1091 if (instance == 1)
1092 return hdev->adv_instance.flags;
1093
1094 flags = 0;
1095
1096 /* For instance 0, assemble the flags from global settings */
1097 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) ||
1098 get_connectable(hdev))
1099 flags |= MGMT_ADV_FLAG_CONNECTABLE;
1100
1101 /* TODO: Add the rest of the flags */
1102
1103 return flags;
1104}
1105
1106static void update_adv_data(struct hci_request *req)
1107{
1108 struct hci_dev *hdev = req->hdev;
1109 u8 instance = get_current_adv_instance(hdev);
Arman Uguray24b4f382015-03-23 15:57:12 -07001110
1111 update_adv_data_for_instance(req, instance);
1112}
1113
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001114int mgmt_update_adv_data(struct hci_dev *hdev)
1115{
1116 struct hci_request req;
1117
1118 hci_req_init(&req, hdev);
1119 update_adv_data(&req);
1120
1121 return hci_req_run(&req, NULL);
1122}
1123
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001124static void create_eir(struct hci_dev *hdev, u8 *data)
1125{
1126 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001127 size_t name_len;
1128
1129 name_len = strlen(hdev->dev_name);
1130
1131 if (name_len > 0) {
1132 /* EIR Data type */
1133 if (name_len > 48) {
1134 name_len = 48;
1135 ptr[1] = EIR_NAME_SHORT;
1136 } else
1137 ptr[1] = EIR_NAME_COMPLETE;
1138
1139 /* EIR Data length */
1140 ptr[0] = name_len + 1;
1141
1142 memcpy(ptr + 2, hdev->dev_name, name_len);
1143
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001144 ptr += (name_len + 2);
1145 }
1146
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001147 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001148 ptr[0] = 2;
1149 ptr[1] = EIR_TX_POWER;
1150 ptr[2] = (u8) hdev->inq_tx_power;
1151
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001152 ptr += 3;
1153 }
1154
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001155 if (hdev->devid_source > 0) {
1156 ptr[0] = 9;
1157 ptr[1] = EIR_DEVICE_ID;
1158
1159 put_unaligned_le16(hdev->devid_source, ptr + 2);
1160 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1161 put_unaligned_le16(hdev->devid_product, ptr + 6);
1162 put_unaligned_le16(hdev->devid_version, ptr + 8);
1163
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001164 ptr += 10;
1165 }
1166
Johan Hedberg213202e2013-01-27 00:31:33 +02001167 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001168 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001169 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001170}
1171
Johan Hedberg890ea892013-03-15 17:06:52 -05001172static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001173{
Johan Hedberg890ea892013-03-15 17:06:52 -05001174 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001175 struct hci_cp_write_eir cp;
1176
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001177 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001178 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001179
Johan Hedberg976eb202012-10-24 21:12:01 +03001180 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001181 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001182
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001183 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001184 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001185
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001186 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001187 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001188
1189 memset(&cp, 0, sizeof(cp));
1190
1191 create_eir(hdev, cp.data);
1192
1193 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001194 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001195
1196 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1197
Johan Hedberg890ea892013-03-15 17:06:52 -05001198 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001199}
1200
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001201static u8 get_service_classes(struct hci_dev *hdev)
1202{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001203 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001204 u8 val = 0;
1205
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001206 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001207 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001208
1209 return val;
1210}
1211
Johan Hedberg890ea892013-03-15 17:06:52 -05001212static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001213{
Johan Hedberg890ea892013-03-15 17:06:52 -05001214 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001215 u8 cod[3];
1216
1217 BT_DBG("%s", hdev->name);
1218
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001219 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001220 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001221
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001222 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001223 return;
1224
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001225 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001226 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001227
1228 cod[0] = hdev->minor_class;
1229 cod[1] = hdev->major_class;
1230 cod[2] = get_service_classes(hdev);
1231
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001232 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001233 cod[1] |= 0x20;
1234
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001235 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001236 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001237
Johan Hedberg890ea892013-03-15 17:06:52 -05001238 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001239}
1240
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001241static void disable_advertising(struct hci_request *req)
1242{
1243 u8 enable = 0x00;
1244
1245 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1246}
1247
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001248static void enable_advertising(struct hci_request *req)
1249{
1250 struct hci_dev *hdev = req->hdev;
1251 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001252 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001253 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001254 u8 instance;
1255 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001256
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001257 if (hci_conn_num(hdev, LE_LINK) > 0)
1258 return;
1259
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001260 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001261 disable_advertising(req);
1262
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001263 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001264 * hci_update_random_address knows that it's safe to go ahead
1265 * and write a new random address. The flag will be set back on
1266 * as soon as the SET_ADV_ENABLE HCI command completes.
1267 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001268 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001269
Arman Uguraye7a685d2015-03-25 18:53:40 -07001270 instance = get_current_adv_instance(hdev);
1271 flags = get_adv_instance_flags(hdev, instance);
1272 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001273
Johan Hedberga4858cb2014-02-25 19:56:31 +02001274 /* Set require_privacy to true only when non-connectable
1275 * advertising is used. In that case it is fine to use a
1276 * non-resolvable private address.
1277 */
1278 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001279 return;
1280
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001281 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001282 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1283 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001284 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001285 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001286 cp.channel_map = hdev->le_adv_channel_map;
1287
1288 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1289
1290 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1291}
1292
Johan Hedberg7d785252011-12-15 00:47:39 +02001293static void service_cache_off(struct work_struct *work)
1294{
1295 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001296 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001297 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001298
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001299 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001300 return;
1301
Johan Hedberg890ea892013-03-15 17:06:52 -05001302 hci_req_init(&req, hdev);
1303
Johan Hedberg7d785252011-12-15 00:47:39 +02001304 hci_dev_lock(hdev);
1305
Johan Hedberg890ea892013-03-15 17:06:52 -05001306 update_eir(&req);
1307 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001308
1309 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001310
1311 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001312}
1313
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001314static void rpa_expired(struct work_struct *work)
1315{
1316 struct hci_dev *hdev = container_of(work, struct hci_dev,
1317 rpa_expired.work);
1318 struct hci_request req;
1319
1320 BT_DBG("");
1321
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001322 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001323
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001324 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001325 return;
1326
1327 /* The generation of a new RPA and programming it into the
1328 * controller happens in the enable_advertising() function.
1329 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001330 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001331 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001332 hci_req_run(&req, NULL);
1333}
1334
Johan Hedberg6a919082012-02-28 06:17:26 +02001335static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001336{
Marcel Holtmann238be782015-03-13 02:11:06 -07001337 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001338 return;
1339
Johan Hedberg4f87da82012-03-02 19:55:56 +02001340 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001341 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001342
Johan Hedberg4f87da82012-03-02 19:55:56 +02001343 /* Non-mgmt controlled devices get this bit set
1344 * implicitly so that pairing works for them, however
1345 * for mgmt we require user-space to explicitly enable
1346 * it
1347 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001348 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001349}
1350
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001351static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001352 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001353{
1354 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001355
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001356 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001357
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001358 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001359
Johan Hedberg03811012010-12-08 00:21:06 +02001360 memset(&rp, 0, sizeof(rp));
1361
Johan Hedberg03811012010-12-08 00:21:06 +02001362 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001363
1364 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001365 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001366
1367 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1368 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1369
1370 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001371
1372 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001373 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001374
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001375 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001376
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001377 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1378 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001379}
1380
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001381static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001382{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001383 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001385 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1386 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001387}
1388
Marcel Holtmann1904a852015-01-11 13:50:44 -08001389static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001390{
1391 BT_DBG("%s status 0x%02x", hdev->name, status);
1392
Johan Hedberga3172b72014-02-28 09:33:44 +02001393 if (hci_conn_count(hdev) == 0) {
1394 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001395 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001396 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001397}
1398
Johan Hedberg23a48092014-07-08 16:05:06 +03001399static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001400{
1401 struct hci_dev *hdev = req->hdev;
1402 struct hci_cp_remote_name_req_cancel cp;
1403 struct inquiry_entry *e;
1404
1405 switch (hdev->discovery.state) {
1406 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001407 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001408 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001409
1410 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001411 cancel_delayed_work(&hdev->le_scan_disable);
1412 hci_req_add_le_scan_disable(req);
1413 }
1414
Johan Hedberg23a48092014-07-08 16:05:06 +03001415 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001416
1417 case DISCOVERY_RESOLVING:
1418 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1419 NAME_PENDING);
1420 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001421 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001422
1423 bacpy(&cp.bdaddr, &e->data.bdaddr);
1424 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1425 &cp);
1426
Johan Hedberg23a48092014-07-08 16:05:06 +03001427 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001428
1429 default:
1430 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001431 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001432 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001433 return true;
1434 }
1435
Johan Hedberg21a60d32014-06-10 14:05:58 +03001436 break;
1437 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001438
1439 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001440}
1441
Arman Uguray912098a2015-03-23 15:57:15 -07001442static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1443 u8 instance)
1444{
1445 struct mgmt_ev_advertising_added ev;
1446
1447 ev.instance = instance;
1448
1449 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1450}
1451
1452static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1453 u8 instance)
1454{
1455 struct mgmt_ev_advertising_removed ev;
1456
1457 ev.instance = instance;
1458
1459 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1460}
1461
1462static void clear_adv_instance(struct hci_dev *hdev)
1463{
1464 struct hci_request req;
1465
1466 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1467 return;
1468
1469 if (hdev->adv_instance.timeout)
1470 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
1471
1472 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1473 advertising_removed(NULL, hdev, 1);
1474 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1475
1476 if (!hdev_is_powered(hdev) ||
1477 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1478 return;
1479
1480 hci_req_init(&req, hdev);
1481 disable_advertising(&req);
1482 hci_req_run(&req, NULL);
1483}
1484
Johan Hedberg8b064a32014-02-24 14:52:22 +02001485static int clean_up_hci_state(struct hci_dev *hdev)
1486{
1487 struct hci_request req;
1488 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001489 bool discov_stopped;
1490 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001491
1492 hci_req_init(&req, hdev);
1493
1494 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1495 test_bit(HCI_PSCAN, &hdev->flags)) {
1496 u8 scan = 0x00;
1497 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1498 }
1499
Arman Uguray912098a2015-03-23 15:57:15 -07001500 if (hdev->adv_instance.timeout)
1501 clear_adv_instance(hdev);
1502
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001503 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001504 disable_advertising(&req);
1505
Johan Hedberg23a48092014-07-08 16:05:06 +03001506 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001507
1508 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1509 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001510 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001511
Johan Hedbergc9910d02014-02-27 14:35:12 +02001512 switch (conn->state) {
1513 case BT_CONNECTED:
1514 case BT_CONFIG:
1515 dc.handle = cpu_to_le16(conn->handle);
1516 dc.reason = 0x15; /* Terminated due to Power Off */
1517 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1518 break;
1519 case BT_CONNECT:
1520 if (conn->type == LE_LINK)
1521 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1522 0, NULL);
1523 else if (conn->type == ACL_LINK)
1524 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1525 6, &conn->dst);
1526 break;
1527 case BT_CONNECT2:
1528 bacpy(&rej.bdaddr, &conn->dst);
1529 rej.reason = 0x15; /* Terminated due to Power Off */
1530 if (conn->type == ACL_LINK)
1531 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1532 sizeof(rej), &rej);
1533 else if (conn->type == SCO_LINK)
1534 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1535 sizeof(rej), &rej);
1536 break;
1537 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001538 }
1539
Johan Hedberg23a48092014-07-08 16:05:06 +03001540 err = hci_req_run(&req, clean_up_hci_complete);
1541 if (!err && discov_stopped)
1542 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1543
1544 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001545}
1546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001547static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001548 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001549{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001550 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001551 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001552 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001554 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001555
Johan Hedberga7e80f22013-01-09 16:05:19 +02001556 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001557 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1558 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001559
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001560 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001561
Johan Hedberg333ae952015-03-17 13:48:47 +02001562 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001563 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1564 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001565 goto failed;
1566 }
1567
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001568 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001569 cancel_delayed_work(&hdev->power_off);
1570
1571 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001572 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1573 data, len);
1574 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001575 goto failed;
1576 }
1577 }
1578
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001579 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001580 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001581 goto failed;
1582 }
1583
Johan Hedberg03811012010-12-08 00:21:06 +02001584 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1585 if (!cmd) {
1586 err = -ENOMEM;
1587 goto failed;
1588 }
1589
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001591 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001592 err = 0;
1593 } else {
1594 /* Disconnect connections, stop scans, etc */
1595 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001596 if (!err)
1597 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1598 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001599
Johan Hedberg8b064a32014-02-24 14:52:22 +02001600 /* ENODATA means there were no HCI commands queued */
1601 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001602 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001603 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1604 err = 0;
1605 }
1606 }
Johan Hedberg03811012010-12-08 00:21:06 +02001607
1608failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001609 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001610 return err;
1611}
1612
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001613static int new_settings(struct hci_dev *hdev, struct sock *skip)
1614{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001615 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001616
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001617 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1618 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001619}
1620
Johan Hedberg91a668b2014-07-09 13:28:26 +03001621int mgmt_new_settings(struct hci_dev *hdev)
1622{
1623 return new_settings(hdev, NULL);
1624}
1625
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001626struct cmd_lookup {
1627 struct sock *sk;
1628 struct hci_dev *hdev;
1629 u8 mgmt_status;
1630};
1631
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001632static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001633{
1634 struct cmd_lookup *match = data;
1635
1636 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1637
1638 list_del(&cmd->list);
1639
1640 if (match->sk == NULL) {
1641 match->sk = cmd->sk;
1642 sock_hold(match->sk);
1643 }
1644
1645 mgmt_pending_free(cmd);
1646}
1647
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001648static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001649{
1650 u8 *status = data;
1651
Johan Hedberga69e8372015-03-06 21:08:53 +02001652 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001653 mgmt_pending_remove(cmd);
1654}
1655
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001656static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001657{
1658 if (cmd->cmd_complete) {
1659 u8 *status = data;
1660
1661 cmd->cmd_complete(cmd, *status);
1662 mgmt_pending_remove(cmd);
1663
1664 return;
1665 }
1666
1667 cmd_status_rsp(cmd, data);
1668}
1669
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001670static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001671{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001672 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1673 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001674}
1675
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001676static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001677{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001678 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1679 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001680}
1681
Johan Hedberge6fe7982013-10-02 15:45:22 +03001682static u8 mgmt_bredr_support(struct hci_dev *hdev)
1683{
1684 if (!lmp_bredr_capable(hdev))
1685 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001686 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001687 return MGMT_STATUS_REJECTED;
1688 else
1689 return MGMT_STATUS_SUCCESS;
1690}
1691
1692static u8 mgmt_le_support(struct hci_dev *hdev)
1693{
1694 if (!lmp_le_capable(hdev))
1695 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001696 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001697 return MGMT_STATUS_REJECTED;
1698 else
1699 return MGMT_STATUS_SUCCESS;
1700}
1701
Marcel Holtmann1904a852015-01-11 13:50:44 -08001702static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1703 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001704{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001705 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001706 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001707 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001708 bool changed;
1709
1710 BT_DBG("status 0x%02x", status);
1711
1712 hci_dev_lock(hdev);
1713
Johan Hedberg333ae952015-03-17 13:48:47 +02001714 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001715 if (!cmd)
1716 goto unlock;
1717
1718 if (status) {
1719 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001720 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001721 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001722 goto remove_cmd;
1723 }
1724
1725 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001726 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001727 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001728
1729 if (hdev->discov_timeout > 0) {
1730 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1731 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1732 to);
1733 }
1734 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001735 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001736 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737
1738 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1739
1740 if (changed)
1741 new_settings(hdev, cmd->sk);
1742
Marcel Holtmann970ba522013-10-15 06:33:57 -07001743 /* When the discoverable mode gets changed, make sure
1744 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001745 * bit correctly set. Also update page scan based on whitelist
1746 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001747 */
1748 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001749 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001750 update_class(&req);
1751 hci_req_run(&req, NULL);
1752
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001753remove_cmd:
1754 mgmt_pending_remove(cmd);
1755
1756unlock:
1757 hci_dev_unlock(hdev);
1758}
1759
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001760static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001761 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001762{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001763 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001764 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001765 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001766 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001767 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001768 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001769
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001770 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001771
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001772 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1773 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001774 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1775 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001776
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001777 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001778 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1779 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001780
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001781 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001782
1783 /* Disabling discoverable requires that no timeout is set,
1784 * and enabling limited discoverable requires a timeout.
1785 */
1786 if ((cp->val == 0x00 && timeout > 0) ||
1787 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001788 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1789 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001790
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001791 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001792
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001793 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001794 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1795 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001796 goto failed;
1797 }
1798
Johan Hedberg333ae952015-03-17 13:48:47 +02001799 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1800 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001801 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1802 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001803 goto failed;
1804 }
1805
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001806 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001807 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1808 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001809 goto failed;
1810 }
1811
1812 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001813 bool changed = false;
1814
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001815 /* Setting limited discoverable when powered off is
1816 * not a valid operation since it requires a timeout
1817 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1818 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001819 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001820 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001821 changed = true;
1822 }
1823
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001824 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001825 if (err < 0)
1826 goto failed;
1827
1828 if (changed)
1829 err = new_settings(hdev, sk);
1830
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001831 goto failed;
1832 }
1833
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001834 /* If the current mode is the same, then just update the timeout
1835 * value with the new value. And if only the timeout gets updated,
1836 * then no need for any HCI transactions.
1837 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001838 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1839 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1840 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001841 cancel_delayed_work(&hdev->discov_off);
1842 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001843
Marcel Holtmann36261542013-10-15 08:28:51 -07001844 if (cp->val && hdev->discov_timeout > 0) {
1845 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001846 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001847 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001848 }
1849
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001850 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001851 goto failed;
1852 }
1853
1854 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1855 if (!cmd) {
1856 err = -ENOMEM;
1857 goto failed;
1858 }
1859
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001860 /* Cancel any potential discoverable timeout that might be
1861 * still active and store new timeout value. The arming of
1862 * the timeout happens in the complete handler.
1863 */
1864 cancel_delayed_work(&hdev->discov_off);
1865 hdev->discov_timeout = timeout;
1866
Johan Hedbergb456f872013-10-19 23:38:22 +03001867 /* Limited discoverable mode */
1868 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001869 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001870 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001871 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001872
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001873 hci_req_init(&req, hdev);
1874
Johan Hedberg9a43e252013-10-20 19:00:07 +03001875 /* The procedure for LE-only controllers is much simpler - just
1876 * update the advertising data.
1877 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001878 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001879 goto update_ad;
1880
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001881 scan = SCAN_PAGE;
1882
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001883 if (cp->val) {
1884 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001885
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001886 if (cp->val == 0x02) {
1887 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001888 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001889 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1890 hci_cp.iac_lap[1] = 0x8b;
1891 hci_cp.iac_lap[2] = 0x9e;
1892 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1893 hci_cp.iac_lap[4] = 0x8b;
1894 hci_cp.iac_lap[5] = 0x9e;
1895 } else {
1896 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001897 hci_cp.num_iac = 1;
1898 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1899 hci_cp.iac_lap[1] = 0x8b;
1900 hci_cp.iac_lap[2] = 0x9e;
1901 }
1902
1903 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1904 (hci_cp.num_iac * 3) + 1, &hci_cp);
1905
1906 scan |= SCAN_INQUIRY;
1907 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001908 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001909 }
1910
1911 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001912
Johan Hedberg9a43e252013-10-20 19:00:07 +03001913update_ad:
1914 update_adv_data(&req);
1915
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001916 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001917 if (err < 0)
1918 mgmt_pending_remove(cmd);
1919
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001920failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001921 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001922 return err;
1923}
1924
Johan Hedberg406d7802013-03-15 17:07:09 -05001925static void write_fast_connectable(struct hci_request *req, bool enable)
1926{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001927 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001928 struct hci_cp_write_page_scan_activity acp;
1929 u8 type;
1930
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001931 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001932 return;
1933
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001934 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1935 return;
1936
Johan Hedberg406d7802013-03-15 17:07:09 -05001937 if (enable) {
1938 type = PAGE_SCAN_TYPE_INTERLACED;
1939
1940 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001941 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001942 } else {
1943 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1944
1945 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001946 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001947 }
1948
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001949 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001950
Johan Hedbergbd98b992013-03-15 17:07:13 -05001951 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1952 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1953 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1954 sizeof(acp), &acp);
1955
1956 if (hdev->page_scan_type != type)
1957 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001958}
1959
Marcel Holtmann1904a852015-01-11 13:50:44 -08001960static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1961 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001962{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001963 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001964 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001965 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001966
1967 BT_DBG("status 0x%02x", status);
1968
1969 hci_dev_lock(hdev);
1970
Johan Hedberg333ae952015-03-17 13:48:47 +02001971 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001972 if (!cmd)
1973 goto unlock;
1974
Johan Hedberg37438c12013-10-14 16:20:05 +03001975 if (status) {
1976 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001977 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001978 goto remove_cmd;
1979 }
1980
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001981 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001982 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001983 conn_changed = !hci_dev_test_and_set_flag(hdev,
1984 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001985 discov_changed = false;
1986 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001987 conn_changed = hci_dev_test_and_clear_flag(hdev,
1988 HCI_CONNECTABLE);
1989 discov_changed = hci_dev_test_and_clear_flag(hdev,
1990 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001991 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001992
Johan Hedberg2b76f452013-03-15 17:07:04 -05001993 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1994
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001995 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001996 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001997 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001998 if (discov_changed)
1999 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03002000 hci_update_background_scan(hdev);
2001 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002002
Johan Hedberg37438c12013-10-14 16:20:05 +03002003remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002004 mgmt_pending_remove(cmd);
2005
2006unlock:
2007 hci_dev_unlock(hdev);
2008}
2009
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002010static int set_connectable_update_settings(struct hci_dev *hdev,
2011 struct sock *sk, u8 val)
2012{
2013 bool changed = false;
2014 int err;
2015
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002016 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002017 changed = true;
2018
2019 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002020 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002021 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002022 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2023 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002024 }
2025
2026 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2027 if (err < 0)
2028 return err;
2029
Johan Hedberg562064e2014-07-08 16:35:34 +03002030 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002031 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002032 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002033 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002034 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002035
2036 return 0;
2037}
2038
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002039static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002040 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002041{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002042 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002043 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002044 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002045 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002046 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002047
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002048 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002049
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002050 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2051 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002052 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2053 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002054
Johan Hedberga7e80f22013-01-09 16:05:19 +02002055 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002056 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2057 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002058
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002059 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002060
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002061 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002062 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002063 goto failed;
2064 }
2065
Johan Hedberg333ae952015-03-17 13:48:47 +02002066 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2067 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002068 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2069 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002070 goto failed;
2071 }
2072
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002073 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2074 if (!cmd) {
2075 err = -ENOMEM;
2076 goto failed;
2077 }
2078
Johan Hedberg2b76f452013-03-15 17:07:04 -05002079 hci_req_init(&req, hdev);
2080
Johan Hedberg9a43e252013-10-20 19:00:07 +03002081 /* If BR/EDR is not enabled and we disable advertising as a
2082 * by-product of disabling connectable, we need to update the
2083 * advertising flags.
2084 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002085 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002086 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002087 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2088 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002089 }
2090 update_adv_data(&req);
2091 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002092 if (cp->val) {
2093 scan = SCAN_PAGE;
2094 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002095 /* If we don't have any whitelist entries just
2096 * disable all scanning. If there are entries
2097 * and we had both page and inquiry scanning
2098 * enabled then fall back to only page scanning.
2099 * Otherwise no changes are needed.
2100 */
2101 if (list_empty(&hdev->whitelist))
2102 scan = SCAN_DISABLED;
2103 else if (test_bit(HCI_ISCAN, &hdev->flags))
2104 scan = SCAN_PAGE;
2105 else
2106 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002107
2108 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002109 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002110 cancel_delayed_work(&hdev->discov_off);
2111 }
2112
2113 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2114 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002115
Johan Hedberg3bd27242014-07-28 20:53:58 +03002116no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002117 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002118 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002119 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002120
Johan Hedberg2b76f452013-03-15 17:07:04 -05002121 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002122 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002123 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002124 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002125 err = set_connectable_update_settings(hdev, sk,
2126 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002127 goto failed;
2128 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002129
2130failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002131 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002132 return err;
2133}
2134
Johan Hedbergb2939472014-07-30 09:22:23 +03002135static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002136 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002137{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002138 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002139 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002140 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002141
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002142 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002143
Johan Hedberga7e80f22013-01-09 16:05:19 +02002144 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002145 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2146 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002147
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002148 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002149
2150 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002151 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002152 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002153 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002154
Johan Hedbergb2939472014-07-30 09:22:23 +03002155 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002156 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002157 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002158
Marcel Holtmann55594352013-10-06 16:11:57 -07002159 if (changed)
2160 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002161
Marcel Holtmann55594352013-10-06 16:11:57 -07002162unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002163 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002164 return err;
2165}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002166
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002167static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2168 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002169{
2170 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002171 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002172 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002173 int err;
2174
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002175 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002176
Johan Hedberge6fe7982013-10-02 15:45:22 +03002177 status = mgmt_bredr_support(hdev);
2178 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002179 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2180 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002181
Johan Hedberga7e80f22013-01-09 16:05:19 +02002182 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002183 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2184 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002185
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002186 hci_dev_lock(hdev);
2187
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002188 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002189 bool changed = false;
2190
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002191 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002192 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002193 changed = true;
2194 }
2195
2196 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2197 if (err < 0)
2198 goto failed;
2199
2200 if (changed)
2201 err = new_settings(hdev, sk);
2202
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002203 goto failed;
2204 }
2205
Johan Hedberg333ae952015-03-17 13:48:47 +02002206 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002207 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2208 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002209 goto failed;
2210 }
2211
2212 val = !!cp->val;
2213
2214 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2215 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2216 goto failed;
2217 }
2218
2219 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2220 if (!cmd) {
2221 err = -ENOMEM;
2222 goto failed;
2223 }
2224
2225 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2226 if (err < 0) {
2227 mgmt_pending_remove(cmd);
2228 goto failed;
2229 }
2230
2231failed:
2232 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002233 return err;
2234}
2235
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002236static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002237{
2238 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002239 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002240 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002241 int err;
2242
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002243 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002244
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002245 status = mgmt_bredr_support(hdev);
2246 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002247 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002248
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002249 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002250 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2251 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002252
Johan Hedberga7e80f22013-01-09 16:05:19 +02002253 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002254 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2255 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002256
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002257 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002258
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002259 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002260 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002261
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002262 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002263 changed = !hci_dev_test_and_set_flag(hdev,
2264 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002265 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002266 changed = hci_dev_test_and_clear_flag(hdev,
2267 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002268 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002269 changed = hci_dev_test_and_clear_flag(hdev,
2270 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002271 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002272 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002273 }
2274
2275 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2276 if (err < 0)
2277 goto failed;
2278
2279 if (changed)
2280 err = new_settings(hdev, sk);
2281
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002282 goto failed;
2283 }
2284
Johan Hedberg333ae952015-03-17 13:48:47 +02002285 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002286 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2287 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002288 goto failed;
2289 }
2290
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002291 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002292 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2293 goto failed;
2294 }
2295
2296 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2297 if (!cmd) {
2298 err = -ENOMEM;
2299 goto failed;
2300 }
2301
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002302 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002303 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2304 sizeof(cp->val), &cp->val);
2305
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002306 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002307 if (err < 0) {
2308 mgmt_pending_remove(cmd);
2309 goto failed;
2310 }
2311
2312failed:
2313 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002314 return err;
2315}
2316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002317static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002318{
2319 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002320 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002321 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002322 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002323
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002324 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002325
Johan Hedberge6fe7982013-10-02 15:45:22 +03002326 status = mgmt_bredr_support(hdev);
2327 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002328 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002329
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002330 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002331 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2332 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002333
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002334 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002335 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2336 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002337
Johan Hedberga7e80f22013-01-09 16:05:19 +02002338 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002339 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2340 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002341
Marcel Holtmannee392692013-10-01 22:59:23 -07002342 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002343
Johan Hedberg333ae952015-03-17 13:48:47 +02002344 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002345 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2346 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002347 goto unlock;
2348 }
2349
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002350 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002351 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002352 } else {
2353 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002354 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2355 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002356 goto unlock;
2357 }
2358
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002359 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002360 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002361
2362 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2363 if (err < 0)
2364 goto unlock;
2365
2366 if (changed)
2367 err = new_settings(hdev, sk);
2368
2369unlock:
2370 hci_dev_unlock(hdev);
2371 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002372}
2373
Marcel Holtmann1904a852015-01-11 13:50:44 -08002374static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002375{
2376 struct cmd_lookup match = { NULL, hdev };
2377
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302378 hci_dev_lock(hdev);
2379
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002380 if (status) {
2381 u8 mgmt_err = mgmt_status(status);
2382
2383 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2384 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302385 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002386 }
2387
2388 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2389
2390 new_settings(hdev, match.sk);
2391
2392 if (match.sk)
2393 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002394
2395 /* Make sure the controller has a good default for
2396 * advertising data. Restrict the update to when LE
2397 * has actually been enabled. During power on, the
2398 * update in powered_update_hci will take care of it.
2399 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002400 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002401 struct hci_request req;
2402
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002403 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002404 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002405 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002406 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002407 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002408 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302409
2410unlock:
2411 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002412}
2413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002414static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002415{
2416 struct mgmt_mode *cp = data;
2417 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002418 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002419 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002420 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002421 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002422
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002423 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002424
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002425 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002426 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2427 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002428
Johan Hedberga7e80f22013-01-09 16:05:19 +02002429 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002430 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2431 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002432
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002433 /* Bluetooth single mode LE only controllers or dual-mode
2434 * controllers configured as LE only devices, do not allow
2435 * switching LE off. These have either LE enabled explicitly
2436 * or BR/EDR has been previously switched off.
2437 *
2438 * When trying to enable an already enabled LE, then gracefully
2439 * send a positive response. Trying to disable it however will
2440 * result into rejection.
2441 */
2442 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2443 if (cp->val == 0x01)
2444 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2445
Johan Hedberga69e8372015-03-06 21:08:53 +02002446 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2447 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002448 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002449
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002450 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002451
2452 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002453 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002454
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002455 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002456 bool changed = false;
2457
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002458 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002459 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002460 changed = true;
2461 }
2462
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002463 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002464 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002465 changed = true;
2466 }
2467
Johan Hedberg06199cf2012-02-22 16:37:11 +02002468 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2469 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002470 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002471
2472 if (changed)
2473 err = new_settings(hdev, sk);
2474
Johan Hedberg1de028c2012-02-29 19:55:35 -08002475 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002476 }
2477
Johan Hedberg333ae952015-03-17 13:48:47 +02002478 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2479 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002480 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2481 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002482 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002483 }
2484
2485 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2486 if (!cmd) {
2487 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002488 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002489 }
2490
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002491 hci_req_init(&req, hdev);
2492
Johan Hedberg06199cf2012-02-22 16:37:11 +02002493 memset(&hci_cp, 0, sizeof(hci_cp));
2494
2495 if (val) {
2496 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002497 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002498 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002499 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002500 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002501 }
2502
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002503 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2504 &hci_cp);
2505
2506 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302507 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002508 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002509
Johan Hedberg1de028c2012-02-29 19:55:35 -08002510unlock:
2511 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002512 return err;
2513}
2514
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002515/* This is a helper function to test for pending mgmt commands that can
2516 * cause CoD or EIR HCI commands. We can only allow one such pending
2517 * mgmt command at a time since otherwise we cannot easily track what
2518 * the current values are, will be, and based on that calculate if a new
2519 * HCI command needs to be sent and if yes with what value.
2520 */
2521static bool pending_eir_or_class(struct hci_dev *hdev)
2522{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002523 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002524
2525 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2526 switch (cmd->opcode) {
2527 case MGMT_OP_ADD_UUID:
2528 case MGMT_OP_REMOVE_UUID:
2529 case MGMT_OP_SET_DEV_CLASS:
2530 case MGMT_OP_SET_POWERED:
2531 return true;
2532 }
2533 }
2534
2535 return false;
2536}
2537
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002538static const u8 bluetooth_base_uuid[] = {
2539 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2540 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2541};
2542
2543static u8 get_uuid_size(const u8 *uuid)
2544{
2545 u32 val;
2546
2547 if (memcmp(uuid, bluetooth_base_uuid, 12))
2548 return 128;
2549
2550 val = get_unaligned_le32(&uuid[12]);
2551 if (val > 0xffff)
2552 return 32;
2553
2554 return 16;
2555}
2556
Johan Hedberg92da6092013-03-15 17:06:55 -05002557static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2558{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002559 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002560
2561 hci_dev_lock(hdev);
2562
Johan Hedberg333ae952015-03-17 13:48:47 +02002563 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002564 if (!cmd)
2565 goto unlock;
2566
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002567 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2568 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002569
2570 mgmt_pending_remove(cmd);
2571
2572unlock:
2573 hci_dev_unlock(hdev);
2574}
2575
Marcel Holtmann1904a852015-01-11 13:50:44 -08002576static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002577{
2578 BT_DBG("status 0x%02x", status);
2579
2580 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2581}
2582
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002583static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002584{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002585 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002586 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002587 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002588 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002589 int err;
2590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002591 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002592
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002593 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002594
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002595 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002596 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2597 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002598 goto failed;
2599 }
2600
Andre Guedes92c4c202012-06-07 19:05:44 -03002601 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002602 if (!uuid) {
2603 err = -ENOMEM;
2604 goto failed;
2605 }
2606
2607 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002608 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002609 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002610
Johan Hedbergde66aa62013-01-27 00:31:27 +02002611 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002612
Johan Hedberg890ea892013-03-15 17:06:52 -05002613 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002614
Johan Hedberg890ea892013-03-15 17:06:52 -05002615 update_class(&req);
2616 update_eir(&req);
2617
Johan Hedberg92da6092013-03-15 17:06:55 -05002618 err = hci_req_run(&req, add_uuid_complete);
2619 if (err < 0) {
2620 if (err != -ENODATA)
2621 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002622
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002623 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2624 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002625 goto failed;
2626 }
2627
2628 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002629 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002630 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002631 goto failed;
2632 }
2633
2634 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002635
2636failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002637 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002638 return err;
2639}
2640
Johan Hedberg24b78d02012-02-23 23:24:30 +02002641static bool enable_service_cache(struct hci_dev *hdev)
2642{
2643 if (!hdev_is_powered(hdev))
2644 return false;
2645
Marcel Holtmann238be782015-03-13 02:11:06 -07002646 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002647 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2648 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002649 return true;
2650 }
2651
2652 return false;
2653}
2654
Marcel Holtmann1904a852015-01-11 13:50:44 -08002655static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002656{
2657 BT_DBG("status 0x%02x", status);
2658
2659 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2660}
2661
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002662static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002663 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002664{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002665 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002666 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002667 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002668 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 -05002669 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002670 int err, found;
2671
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002672 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002673
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002674 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002675
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002676 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002677 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2678 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002679 goto unlock;
2680 }
2681
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002682 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002683 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002684
Johan Hedberg24b78d02012-02-23 23:24:30 +02002685 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002686 err = mgmt_cmd_complete(sk, hdev->id,
2687 MGMT_OP_REMOVE_UUID,
2688 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002689 goto unlock;
2690 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002691
Johan Hedberg9246a862012-02-23 21:33:16 +02002692 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002693 }
2694
2695 found = 0;
2696
Johan Hedberg056341c2013-01-27 00:31:30 +02002697 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002698 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2699 continue;
2700
2701 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002702 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002703 found++;
2704 }
2705
2706 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002707 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2708 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002709 goto unlock;
2710 }
2711
Johan Hedberg9246a862012-02-23 21:33:16 +02002712update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002713 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002714
Johan Hedberg890ea892013-03-15 17:06:52 -05002715 update_class(&req);
2716 update_eir(&req);
2717
Johan Hedberg92da6092013-03-15 17:06:55 -05002718 err = hci_req_run(&req, remove_uuid_complete);
2719 if (err < 0) {
2720 if (err != -ENODATA)
2721 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002722
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002723 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2724 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002725 goto unlock;
2726 }
2727
2728 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002729 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002730 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002731 goto unlock;
2732 }
2733
2734 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002735
2736unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002737 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002738 return err;
2739}
2740
Marcel Holtmann1904a852015-01-11 13:50:44 -08002741static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002742{
2743 BT_DBG("status 0x%02x", status);
2744
2745 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2746}
2747
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002748static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002749 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002750{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002751 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002752 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002753 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002754 int err;
2755
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002756 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002757
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002758 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002759 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2760 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002761
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002762 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002763
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002764 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002765 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2766 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002767 goto unlock;
2768 }
2769
2770 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002771 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2772 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002773 goto unlock;
2774 }
2775
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002776 hdev->major_class = cp->major;
2777 hdev->minor_class = cp->minor;
2778
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002779 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002780 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2781 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002782 goto unlock;
2783 }
2784
Johan Hedberg890ea892013-03-15 17:06:52 -05002785 hci_req_init(&req, hdev);
2786
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002787 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002788 hci_dev_unlock(hdev);
2789 cancel_delayed_work_sync(&hdev->service_cache);
2790 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002791 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002792 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002793
Johan Hedberg890ea892013-03-15 17:06:52 -05002794 update_class(&req);
2795
Johan Hedberg92da6092013-03-15 17:06:55 -05002796 err = hci_req_run(&req, set_class_complete);
2797 if (err < 0) {
2798 if (err != -ENODATA)
2799 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002800
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002801 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2802 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002803 goto unlock;
2804 }
2805
2806 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002807 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002808 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002809 goto unlock;
2810 }
2811
2812 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002813
Johan Hedbergb5235a62012-02-21 14:32:24 +02002814unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002815 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002816 return err;
2817}
2818
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002819static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002820 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002821{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002822 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002823 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2824 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002825 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002826 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002827 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002828
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002829 BT_DBG("request for %s", hdev->name);
2830
2831 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002832 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2833 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002834
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002835 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002836 if (key_count > max_key_count) {
2837 BT_ERR("load_link_keys: too big key_count value %u",
2838 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002839 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2840 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002841 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002842
Johan Hedberg86742e12011-11-07 23:13:38 +02002843 expected_len = sizeof(*cp) + key_count *
2844 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002845 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002846 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002847 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002848 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2849 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002850 }
2851
Johan Hedberg4ae14302013-01-20 14:27:13 +02002852 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002853 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2854 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002855
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002856 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002857 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002858
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002859 for (i = 0; i < key_count; i++) {
2860 struct mgmt_link_key_info *key = &cp->keys[i];
2861
Marcel Holtmann8e991132014-01-10 02:07:25 -08002862 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002863 return mgmt_cmd_status(sk, hdev->id,
2864 MGMT_OP_LOAD_LINK_KEYS,
2865 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002866 }
2867
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002868 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002869
2870 hci_link_keys_clear(hdev);
2871
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002872 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002873 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002874 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002875 changed = hci_dev_test_and_clear_flag(hdev,
2876 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002877
2878 if (changed)
2879 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002880
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002881 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002882 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002883
Johan Hedberg58e92932014-06-24 14:00:26 +03002884 /* Always ignore debug keys and require a new pairing if
2885 * the user wants to use them.
2886 */
2887 if (key->type == HCI_LK_DEBUG_COMBINATION)
2888 continue;
2889
Johan Hedberg7652ff62014-06-24 13:15:49 +03002890 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2891 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002892 }
2893
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002894 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002895
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002896 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002897
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002898 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002899}
2900
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002901static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002902 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002903{
2904 struct mgmt_ev_device_unpaired ev;
2905
2906 bacpy(&ev.addr.bdaddr, bdaddr);
2907 ev.addr.type = addr_type;
2908
2909 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002910 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002911}
2912
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002913static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002914 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002915{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002916 struct mgmt_cp_unpair_device *cp = data;
2917 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002918 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002919 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002920 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002921 int err;
2922
Johan Hedberga8a1d192011-11-10 15:54:38 +02002923 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002924 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2925 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002926
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002927 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002928 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2929 MGMT_STATUS_INVALID_PARAMS,
2930 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002931
Johan Hedberg118da702013-01-20 14:27:20 +02002932 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002933 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2934 MGMT_STATUS_INVALID_PARAMS,
2935 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002936
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002937 hci_dev_lock(hdev);
2938
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002939 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002940 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2941 MGMT_STATUS_NOT_POWERED, &rp,
2942 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002943 goto unlock;
2944 }
2945
Johan Hedberge0b2b272014-02-18 17:14:31 +02002946 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002947 /* If disconnection is requested, then look up the
2948 * connection. If the remote device is connected, it
2949 * will be later used to terminate the link.
2950 *
2951 * Setting it to NULL explicitly will cause no
2952 * termination of the link.
2953 */
2954 if (cp->disconnect)
2955 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2956 &cp->addr.bdaddr);
2957 else
2958 conn = NULL;
2959
Johan Hedberg124f6e32012-02-09 13:50:12 +02002960 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002961 } else {
2962 u8 addr_type;
2963
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002964 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2965 &cp->addr.bdaddr);
2966 if (conn) {
2967 /* Defer clearing up the connection parameters
2968 * until closing to give a chance of keeping
2969 * them if a repairing happens.
2970 */
2971 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2972
2973 /* If disconnection is not requested, then
2974 * clear the connection variable so that the
2975 * link is not terminated.
2976 */
2977 if (!cp->disconnect)
2978 conn = NULL;
2979 }
2980
Johan Hedberge0b2b272014-02-18 17:14:31 +02002981 if (cp->addr.type == BDADDR_LE_PUBLIC)
2982 addr_type = ADDR_LE_DEV_PUBLIC;
2983 else
2984 addr_type = ADDR_LE_DEV_RANDOM;
2985
Johan Hedberga7ec7332014-02-18 17:14:35 +02002986 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2987
Johan Hedberge0b2b272014-02-18 17:14:31 +02002988 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2989 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002990
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002991 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002992 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2993 MGMT_STATUS_NOT_PAIRED, &rp,
2994 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002995 goto unlock;
2996 }
2997
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002998 /* If the connection variable is set, then termination of the
2999 * link is requested.
3000 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02003001 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003002 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3003 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003004 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003005 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003006 }
3007
Johan Hedberg124f6e32012-02-09 13:50:12 +02003008 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003009 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003010 if (!cmd) {
3011 err = -ENOMEM;
3012 goto unlock;
3013 }
3014
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003015 cmd->cmd_complete = addr_cmd_complete;
3016
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003017 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003018 dc.reason = 0x13; /* Remote User Terminated Connection */
3019 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3020 if (err < 0)
3021 mgmt_pending_remove(cmd);
3022
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003023unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003024 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003025 return err;
3026}
3027
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003028static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003029 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003030{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003031 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003032 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003033 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003034 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003035 int err;
3036
3037 BT_DBG("");
3038
Johan Hedberg06a63b12013-01-20 14:27:21 +02003039 memset(&rp, 0, sizeof(rp));
3040 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3041 rp.addr.type = cp->addr.type;
3042
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003043 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003044 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3045 MGMT_STATUS_INVALID_PARAMS,
3046 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003047
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003048 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003049
3050 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003051 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3052 MGMT_STATUS_NOT_POWERED, &rp,
3053 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003054 goto failed;
3055 }
3056
Johan Hedberg333ae952015-03-17 13:48:47 +02003057 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003058 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3059 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003060 goto failed;
3061 }
3062
Andre Guedes591f47f2012-04-24 21:02:49 -03003063 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003064 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3065 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003066 else
3067 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003068
Vishal Agarwalf9607272012-06-13 05:32:43 +05303069 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003070 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3071 MGMT_STATUS_NOT_CONNECTED, &rp,
3072 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003073 goto failed;
3074 }
3075
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003076 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003077 if (!cmd) {
3078 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003079 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003080 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003081
Johan Hedbergf5818c22014-12-05 13:36:02 +02003082 cmd->cmd_complete = generic_cmd_complete;
3083
Johan Hedberge3f2f922014-08-18 20:33:33 +03003084 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003085 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003086 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003087
3088failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003089 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003090 return err;
3091}
3092
Andre Guedes57c14772012-04-24 21:02:50 -03003093static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003094{
3095 switch (link_type) {
3096 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003097 switch (addr_type) {
3098 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003099 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003100
Johan Hedberg48264f02011-11-09 13:58:58 +02003101 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003102 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003103 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003104 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003105
Johan Hedberg4c659c32011-11-07 23:13:39 +02003106 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003107 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003108 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003109 }
3110}
3111
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003112static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3113 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003114{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003115 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003116 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003117 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003118 int err;
3119 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003120
3121 BT_DBG("");
3122
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003123 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003124
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003125 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003126 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3127 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003128 goto unlock;
3129 }
3130
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003131 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003132 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3133 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003134 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003135 }
3136
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003137 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003138 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003139 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003140 err = -ENOMEM;
3141 goto unlock;
3142 }
3143
Johan Hedberg2784eb42011-01-21 13:56:35 +02003144 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003145 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003146 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3147 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003148 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003149 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003150 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003151 continue;
3152 i++;
3153 }
3154
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003155 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003156
Johan Hedberg4c659c32011-11-07 23:13:39 +02003157 /* Recalculate length in case of filtered SCO connections, etc */
3158 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003159
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003160 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3161 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003162
Johan Hedberga38528f2011-01-22 06:46:43 +02003163 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003164
3165unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003166 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003167 return err;
3168}
3169
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003170static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003171 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003172{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003173 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003174 int err;
3175
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003176 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003177 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003178 if (!cmd)
3179 return -ENOMEM;
3180
Johan Hedbergd8457692012-02-17 14:24:57 +02003181 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003182 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003183 if (err < 0)
3184 mgmt_pending_remove(cmd);
3185
3186 return err;
3187}
3188
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003189static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003190 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003191{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003192 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003193 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003194 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003195 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003196 int err;
3197
3198 BT_DBG("");
3199
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003200 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003201
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003202 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003203 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3204 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003205 goto failed;
3206 }
3207
Johan Hedbergd8457692012-02-17 14:24:57 +02003208 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003209 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003210 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3211 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003212 goto failed;
3213 }
3214
3215 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003216 struct mgmt_cp_pin_code_neg_reply ncp;
3217
3218 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003219
3220 BT_ERR("PIN code is not 16 bytes long");
3221
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003222 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003223 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003224 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3225 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003226
3227 goto failed;
3228 }
3229
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003230 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003231 if (!cmd) {
3232 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003233 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003234 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003235
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003236 cmd->cmd_complete = addr_cmd_complete;
3237
Johan Hedbergd8457692012-02-17 14:24:57 +02003238 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003239 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003240 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003241
3242 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3243 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003244 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003245
3246failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003247 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003248 return err;
3249}
3250
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003251static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3252 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003253{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003254 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003255
3256 BT_DBG("");
3257
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003258 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003259 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3260 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003261
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003262 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003263
3264 hdev->io_capability = cp->io_capability;
3265
3266 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003267 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003268
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003269 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003270
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003271 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3272 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003273}
3274
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003275static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003276{
3277 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003278 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003279
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003280 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003281 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3282 continue;
3283
Johan Hedberge9a416b2011-02-19 12:05:56 -03003284 if (cmd->user_data != conn)
3285 continue;
3286
3287 return cmd;
3288 }
3289
3290 return NULL;
3291}
3292
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003293static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003294{
3295 struct mgmt_rp_pair_device rp;
3296 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003297 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003298
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003299 bacpy(&rp.addr.bdaddr, &conn->dst);
3300 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003301
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003302 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3303 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003304
3305 /* So we don't get further callbacks for this connection */
3306 conn->connect_cfm_cb = NULL;
3307 conn->security_cfm_cb = NULL;
3308 conn->disconn_cfm_cb = NULL;
3309
David Herrmann76a68ba2013-04-06 20:28:37 +02003310 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003311
3312 /* The device is paired so there is no need to remove
3313 * its connection parameters anymore.
3314 */
3315 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003316
3317 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003318
3319 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003320}
3321
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003322void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3323{
3324 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003325 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003326
3327 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003328 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003329 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003330 mgmt_pending_remove(cmd);
3331 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003332}
3333
Johan Hedberge9a416b2011-02-19 12:05:56 -03003334static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3335{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003336 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003337
3338 BT_DBG("status %u", status);
3339
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003340 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003341 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003342 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003343 return;
3344 }
3345
3346 cmd->cmd_complete(cmd, mgmt_status(status));
3347 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003348}
3349
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003350static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303351{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003352 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303353
3354 BT_DBG("status %u", status);
3355
3356 if (!status)
3357 return;
3358
3359 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003360 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303361 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003362 return;
3363 }
3364
3365 cmd->cmd_complete(cmd, mgmt_status(status));
3366 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303367}
3368
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003369static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003370 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003371{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003372 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003373 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003374 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003375 u8 sec_level, auth_type;
3376 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003377 int err;
3378
3379 BT_DBG("");
3380
Szymon Jancf950a30e2013-01-18 12:48:07 +01003381 memset(&rp, 0, sizeof(rp));
3382 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3383 rp.addr.type = cp->addr.type;
3384
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003385 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003386 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3387 MGMT_STATUS_INVALID_PARAMS,
3388 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003389
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003390 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003391 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3392 MGMT_STATUS_INVALID_PARAMS,
3393 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003394
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003395 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003396
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003397 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003398 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3399 MGMT_STATUS_NOT_POWERED, &rp,
3400 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003401 goto unlock;
3402 }
3403
Johan Hedberg55e76b32015-03-10 22:34:40 +02003404 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3405 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3406 MGMT_STATUS_ALREADY_PAIRED, &rp,
3407 sizeof(rp));
3408 goto unlock;
3409 }
3410
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003411 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003412 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003413
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003414 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003415 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3416 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003417 } else {
3418 u8 addr_type;
3419
3420 /* Convert from L2CAP channel address type to HCI address type
3421 */
3422 if (cp->addr.type == BDADDR_LE_PUBLIC)
3423 addr_type = ADDR_LE_DEV_PUBLIC;
3424 else
3425 addr_type = ADDR_LE_DEV_RANDOM;
3426
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003427 /* When pairing a new device, it is expected to remember
3428 * this device for future connections. Adding the connection
3429 * parameter information ahead of time allows tracking
3430 * of the slave preferred values and will speed up any
3431 * further connection establishment.
3432 *
3433 * If connection parameters already exist, then they
3434 * will be kept and this function does nothing.
3435 */
3436 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3437
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003438 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003439 sec_level, HCI_LE_CONN_TIMEOUT,
3440 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003441 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003442
Ville Tervo30e76272011-02-22 16:10:53 -03003443 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003444 int status;
3445
3446 if (PTR_ERR(conn) == -EBUSY)
3447 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003448 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3449 status = MGMT_STATUS_NOT_SUPPORTED;
3450 else if (PTR_ERR(conn) == -ECONNREFUSED)
3451 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003452 else
3453 status = MGMT_STATUS_CONNECT_FAILED;
3454
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003455 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3456 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003457 goto unlock;
3458 }
3459
3460 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003461 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003462 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3463 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003464 goto unlock;
3465 }
3466
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003467 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003468 if (!cmd) {
3469 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003470 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003471 goto unlock;
3472 }
3473
Johan Hedberg04ab2742014-12-05 13:36:04 +02003474 cmd->cmd_complete = pairing_complete;
3475
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003476 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003477 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003478 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003479 conn->security_cfm_cb = pairing_complete_cb;
3480 conn->disconn_cfm_cb = pairing_complete_cb;
3481 } else {
3482 conn->connect_cfm_cb = le_pairing_complete_cb;
3483 conn->security_cfm_cb = le_pairing_complete_cb;
3484 conn->disconn_cfm_cb = le_pairing_complete_cb;
3485 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003486
Johan Hedberge9a416b2011-02-19 12:05:56 -03003487 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003488 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003489
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003490 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003491 hci_conn_security(conn, sec_level, auth_type, true)) {
3492 cmd->cmd_complete(cmd, 0);
3493 mgmt_pending_remove(cmd);
3494 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003495
3496 err = 0;
3497
3498unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003499 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003500 return err;
3501}
3502
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003503static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3504 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003505{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003506 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003507 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003508 struct hci_conn *conn;
3509 int err;
3510
3511 BT_DBG("");
3512
Johan Hedberg28424702012-02-02 04:02:29 +02003513 hci_dev_lock(hdev);
3514
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003515 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003516 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3517 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003518 goto unlock;
3519 }
3520
Johan Hedberg333ae952015-03-17 13:48:47 +02003521 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003522 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003523 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3524 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003525 goto unlock;
3526 }
3527
3528 conn = cmd->user_data;
3529
3530 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003531 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3532 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003533 goto unlock;
3534 }
3535
Johan Hedberga511b352014-12-11 21:45:45 +02003536 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3537 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003538
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003539 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3540 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003541unlock:
3542 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003543 return err;
3544}
3545
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003546static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003547 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003548 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003549{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003550 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003551 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003552 int err;
3553
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003554 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003555
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003556 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003557 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3558 MGMT_STATUS_NOT_POWERED, addr,
3559 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003560 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003561 }
3562
Johan Hedberg1707c602013-03-15 17:07:15 -05003563 if (addr->type == BDADDR_BREDR)
3564 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003565 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003566 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003567
Johan Hedberg272d90d2012-02-09 15:26:12 +02003568 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003569 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3570 MGMT_STATUS_NOT_CONNECTED, addr,
3571 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003572 goto done;
3573 }
3574
Johan Hedberg1707c602013-03-15 17:07:15 -05003575 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003576 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003577 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003578 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3579 MGMT_STATUS_SUCCESS, addr,
3580 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003581 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003582 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3583 MGMT_STATUS_FAILED, addr,
3584 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003585
Brian Gix47c15e22011-11-16 13:53:14 -08003586 goto done;
3587 }
3588
Johan Hedberg1707c602013-03-15 17:07:15 -05003589 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003590 if (!cmd) {
3591 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003592 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003593 }
3594
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003595 cmd->cmd_complete = addr_cmd_complete;
3596
Brian Gix0df4c182011-11-16 13:53:13 -08003597 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003598 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3599 struct hci_cp_user_passkey_reply cp;
3600
Johan Hedberg1707c602013-03-15 17:07:15 -05003601 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003602 cp.passkey = passkey;
3603 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3604 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003605 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3606 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003607
Johan Hedberga664b5b2011-02-19 12:06:02 -03003608 if (err < 0)
3609 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003610
Brian Gix0df4c182011-11-16 13:53:13 -08003611done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003612 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003613 return err;
3614}
3615
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303616static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3617 void *data, u16 len)
3618{
3619 struct mgmt_cp_pin_code_neg_reply *cp = data;
3620
3621 BT_DBG("");
3622
Johan Hedberg1707c602013-03-15 17:07:15 -05003623 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303624 MGMT_OP_PIN_CODE_NEG_REPLY,
3625 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3626}
3627
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003628static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3629 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003630{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003631 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003632
3633 BT_DBG("");
3634
3635 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003636 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3637 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003638
Johan Hedberg1707c602013-03-15 17:07:15 -05003639 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003640 MGMT_OP_USER_CONFIRM_REPLY,
3641 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003642}
3643
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003644static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003645 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003646{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003647 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003648
3649 BT_DBG("");
3650
Johan Hedberg1707c602013-03-15 17:07:15 -05003651 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003652 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3653 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003654}
3655
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003656static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3657 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003658{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003659 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003660
3661 BT_DBG("");
3662
Johan Hedberg1707c602013-03-15 17:07:15 -05003663 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003664 MGMT_OP_USER_PASSKEY_REPLY,
3665 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003666}
3667
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003668static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003669 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003670{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003671 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003672
3673 BT_DBG("");
3674
Johan Hedberg1707c602013-03-15 17:07:15 -05003675 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003676 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3677 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003678}
3679
Johan Hedberg13928972013-03-15 17:07:00 -05003680static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003681{
Johan Hedberg13928972013-03-15 17:07:00 -05003682 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003683 struct hci_cp_write_local_name cp;
3684
Johan Hedberg13928972013-03-15 17:07:00 -05003685 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003686
Johan Hedberg890ea892013-03-15 17:06:52 -05003687 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003688}
3689
Marcel Holtmann1904a852015-01-11 13:50:44 -08003690static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003691{
3692 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003693 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003694
3695 BT_DBG("status 0x%02x", status);
3696
3697 hci_dev_lock(hdev);
3698
Johan Hedberg333ae952015-03-17 13:48:47 +02003699 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003700 if (!cmd)
3701 goto unlock;
3702
3703 cp = cmd->param;
3704
3705 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003706 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3707 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003708 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003709 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3710 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003711
3712 mgmt_pending_remove(cmd);
3713
3714unlock:
3715 hci_dev_unlock(hdev);
3716}
3717
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003718static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003719 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003720{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003721 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003722 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003723 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003724 int err;
3725
3726 BT_DBG("");
3727
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003728 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003729
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003730 /* If the old values are the same as the new ones just return a
3731 * direct command complete event.
3732 */
3733 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3734 !memcmp(hdev->short_name, cp->short_name,
3735 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003736 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3737 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003738 goto failed;
3739 }
3740
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003741 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003742
Johan Hedbergb5235a62012-02-21 14:32:24 +02003743 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003744 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003745
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003746 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3747 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003748 if (err < 0)
3749 goto failed;
3750
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003751 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3752 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003753
Johan Hedbergb5235a62012-02-21 14:32:24 +02003754 goto failed;
3755 }
3756
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003757 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003758 if (!cmd) {
3759 err = -ENOMEM;
3760 goto failed;
3761 }
3762
Johan Hedberg13928972013-03-15 17:07:00 -05003763 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3764
Johan Hedberg890ea892013-03-15 17:06:52 -05003765 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003766
3767 if (lmp_bredr_capable(hdev)) {
3768 update_name(&req);
3769 update_eir(&req);
3770 }
3771
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003772 /* The name is stored in the scan response data and so
3773 * no need to udpate the advertising data here.
3774 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003775 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003776 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003777
Johan Hedberg13928972013-03-15 17:07:00 -05003778 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003779 if (err < 0)
3780 mgmt_pending_remove(cmd);
3781
3782failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003783 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003784 return err;
3785}
3786
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003787static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003788 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003789{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003790 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003791 int err;
3792
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003793 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003794
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003795 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003796
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003797 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003798 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3799 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003800 goto unlock;
3801 }
3802
Andre Guedes9a1a1992012-07-24 15:03:48 -03003803 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003804 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3805 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003806 goto unlock;
3807 }
3808
Johan Hedberg333ae952015-03-17 13:48:47 +02003809 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003810 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3811 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003812 goto unlock;
3813 }
3814
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003815 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003816 if (!cmd) {
3817 err = -ENOMEM;
3818 goto unlock;
3819 }
3820
Johan Hedberg710f11c2014-05-26 11:21:22 +03003821 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003822 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3823 0, NULL);
3824 else
3825 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3826
Szymon Jancc35938b2011-03-22 13:12:21 +01003827 if (err < 0)
3828 mgmt_pending_remove(cmd);
3829
3830unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003831 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003832 return err;
3833}
3834
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003835static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003836 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003837{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003838 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003839 int err;
3840
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003841 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003842
Johan Hedberg5d57e792015-01-23 10:10:38 +02003843 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003844 return mgmt_cmd_complete(sk, hdev->id,
3845 MGMT_OP_ADD_REMOTE_OOB_DATA,
3846 MGMT_STATUS_INVALID_PARAMS,
3847 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003848
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003849 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003850
Marcel Holtmannec109112014-01-10 02:07:30 -08003851 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3852 struct mgmt_cp_add_remote_oob_data *cp = data;
3853 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003854
Johan Hedbergc19a4952014-11-17 20:52:19 +02003855 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003856 err = mgmt_cmd_complete(sk, hdev->id,
3857 MGMT_OP_ADD_REMOTE_OOB_DATA,
3858 MGMT_STATUS_INVALID_PARAMS,
3859 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003860 goto unlock;
3861 }
3862
Marcel Holtmannec109112014-01-10 02:07:30 -08003863 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003864 cp->addr.type, cp->hash,
3865 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003866 if (err < 0)
3867 status = MGMT_STATUS_FAILED;
3868 else
3869 status = MGMT_STATUS_SUCCESS;
3870
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003871 err = mgmt_cmd_complete(sk, hdev->id,
3872 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3873 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003874 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3875 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003876 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003877 u8 status;
3878
Johan Hedberg86df9202014-10-26 20:52:27 +01003879 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003880 /* Enforce zero-valued 192-bit parameters as
3881 * long as legacy SMP OOB isn't implemented.
3882 */
3883 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3884 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003885 err = mgmt_cmd_complete(sk, hdev->id,
3886 MGMT_OP_ADD_REMOTE_OOB_DATA,
3887 MGMT_STATUS_INVALID_PARAMS,
3888 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003889 goto unlock;
3890 }
3891
Johan Hedberg86df9202014-10-26 20:52:27 +01003892 rand192 = NULL;
3893 hash192 = NULL;
3894 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003895 /* In case one of the P-192 values is set to zero,
3896 * then just disable OOB data for P-192.
3897 */
3898 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3899 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3900 rand192 = NULL;
3901 hash192 = NULL;
3902 } else {
3903 rand192 = cp->rand192;
3904 hash192 = cp->hash192;
3905 }
3906 }
3907
3908 /* In case one of the P-256 values is set to zero, then just
3909 * disable OOB data for P-256.
3910 */
3911 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3912 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3913 rand256 = NULL;
3914 hash256 = NULL;
3915 } else {
3916 rand256 = cp->rand256;
3917 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003918 }
3919
Johan Hedberg81328d52014-10-26 20:33:47 +01003920 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003921 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003922 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003923 if (err < 0)
3924 status = MGMT_STATUS_FAILED;
3925 else
3926 status = MGMT_STATUS_SUCCESS;
3927
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003928 err = mgmt_cmd_complete(sk, hdev->id,
3929 MGMT_OP_ADD_REMOTE_OOB_DATA,
3930 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003931 } else {
3932 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003933 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3934 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003935 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003936
Johan Hedbergc19a4952014-11-17 20:52:19 +02003937unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003938 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003939 return err;
3940}
3941
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003942static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003943 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003944{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003945 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003946 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003947 int err;
3948
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003949 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003950
Johan Hedbergc19a4952014-11-17 20:52:19 +02003951 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003952 return mgmt_cmd_complete(sk, hdev->id,
3953 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3954 MGMT_STATUS_INVALID_PARAMS,
3955 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003956
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003957 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003958
Johan Hedbergeedbd582014-11-15 09:34:23 +02003959 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3960 hci_remote_oob_data_clear(hdev);
3961 status = MGMT_STATUS_SUCCESS;
3962 goto done;
3963 }
3964
Johan Hedberg6928a922014-10-26 20:46:09 +01003965 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003966 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003967 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003968 else
Szymon Janca6785be2012-12-13 15:11:21 +01003969 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003970
Johan Hedbergeedbd582014-11-15 09:34:23 +02003971done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003972 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3973 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003974
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003975 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003976 return err;
3977}
3978
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003979static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
3980{
3981 struct hci_dev *hdev = req->hdev;
3982 struct hci_cp_inquiry cp;
3983 /* General inquiry access code (GIAC) */
3984 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3985
3986 *status = mgmt_bredr_support(hdev);
3987 if (*status)
3988 return false;
3989
3990 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
3991 *status = MGMT_STATUS_BUSY;
3992 return false;
3993 }
3994
3995 hci_inquiry_cache_flush(hdev);
3996
3997 memset(&cp, 0, sizeof(cp));
3998 memcpy(&cp.lap, lap, sizeof(cp.lap));
3999 cp.length = DISCOV_BREDR_INQUIRY_LEN;
4000
4001 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4002
4003 return true;
4004}
4005
4006static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004007{
Marcel Holtmann80190442014-12-04 11:36:36 +01004008 struct hci_dev *hdev = req->hdev;
4009 struct hci_cp_le_set_scan_param param_cp;
4010 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004011 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004012 int err;
4013
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004014 *status = mgmt_le_support(hdev);
4015 if (*status)
4016 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004017
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004018 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4019 /* Don't let discovery abort an outgoing connection attempt
4020 * that's using directed advertising.
4021 */
4022 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4023 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004024 return false;
4025 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004026
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004027 disable_advertising(req);
4028 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004029
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004030 /* If controller is scanning, it means the background scanning is
4031 * running. Thus, we should temporarily stop it in order to set the
4032 * discovery scanning parameters.
4033 */
4034 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4035 hci_req_add_le_scan_disable(req);
4036
4037 /* All active scans will be done with either a resolvable private
4038 * address (when privacy feature has been enabled) or non-resolvable
4039 * private address.
4040 */
4041 err = hci_update_random_address(req, true, &own_addr_type);
4042 if (err < 0) {
4043 *status = MGMT_STATUS_FAILED;
4044 return false;
4045 }
4046
4047 memset(&param_cp, 0, sizeof(param_cp));
4048 param_cp.type = LE_SCAN_ACTIVE;
4049 param_cp.interval = cpu_to_le16(interval);
4050 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4051 param_cp.own_address_type = own_addr_type;
4052
4053 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4054 &param_cp);
4055
4056 memset(&enable_cp, 0, sizeof(enable_cp));
4057 enable_cp.enable = LE_SCAN_ENABLE;
4058 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4059
4060 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4061 &enable_cp);
4062
4063 return true;
4064}
4065
4066static bool trigger_discovery(struct hci_request *req, u8 *status)
4067{
4068 struct hci_dev *hdev = req->hdev;
4069
4070 switch (hdev->discovery.type) {
4071 case DISCOV_TYPE_BREDR:
4072 if (!trigger_bredr_inquiry(req, status))
4073 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004074 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004075
Marcel Holtmann80190442014-12-04 11:36:36 +01004076 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004077 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4078 &hdev->quirks)) {
4079 /* During simultaneous discovery, we double LE scan
4080 * interval. We must leave some time for the controller
4081 * to do BR/EDR inquiry.
4082 */
4083 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4084 status))
4085 return false;
4086
4087 if (!trigger_bredr_inquiry(req, status))
4088 return false;
4089
4090 return true;
4091 }
4092
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004093 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004094 *status = MGMT_STATUS_NOT_SUPPORTED;
4095 return false;
4096 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004097 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004098
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004099 case DISCOV_TYPE_LE:
4100 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004101 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004102 break;
4103
4104 default:
4105 *status = MGMT_STATUS_INVALID_PARAMS;
4106 return false;
4107 }
4108
4109 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004110}
4111
Marcel Holtmann1904a852015-01-11 13:50:44 -08004112static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4113 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004114{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004115 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004116 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004117
Andre Guedes7c307722013-04-30 15:29:28 -03004118 BT_DBG("status %d", status);
4119
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004120 hci_dev_lock(hdev);
4121
Johan Hedberg333ae952015-03-17 13:48:47 +02004122 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004123 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004124 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004125
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004126 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004127 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004128 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004129 }
4130
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004131 if (status) {
4132 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4133 goto unlock;
4134 }
4135
Andre Guedes7c307722013-04-30 15:29:28 -03004136 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004137
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004138 /* If the scan involves LE scan, pick proper timeout to schedule
4139 * hdev->le_scan_disable that will stop it.
4140 */
Andre Guedes7c307722013-04-30 15:29:28 -03004141 switch (hdev->discovery.type) {
4142 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004143 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004144 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004145 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004146 /* When running simultaneous discovery, the LE scanning time
4147 * should occupy the whole discovery time sine BR/EDR inquiry
4148 * and LE scanning are scheduled by the controller.
4149 *
4150 * For interleaving discovery in comparison, BR/EDR inquiry
4151 * and LE scanning are done sequentially with separate
4152 * timeouts.
4153 */
4154 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4155 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4156 else
4157 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004158 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004159 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004160 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004161 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004162 default:
4163 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004164 timeout = 0;
4165 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004166 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004167
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004168 if (timeout) {
4169 /* When service discovery is used and the controller has
4170 * a strict duplicate filter, it is important to remember
4171 * the start and duration of the scan. This is required
4172 * for restarting scanning during the discovery phase.
4173 */
4174 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4175 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004176 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004177 hdev->discovery.scan_start = jiffies;
4178 hdev->discovery.scan_duration = timeout;
4179 }
4180
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004181 queue_delayed_work(hdev->workqueue,
4182 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004183 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004184
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004185unlock:
4186 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004187}
4188
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004189static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004190 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004191{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004192 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004193 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004194 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004195 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004196 int err;
4197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004198 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004199
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004200 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004201
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004202 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004203 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4204 MGMT_STATUS_NOT_POWERED,
4205 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004206 goto failed;
4207 }
4208
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004209 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004210 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004211 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4212 MGMT_STATUS_BUSY, &cp->type,
4213 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004214 goto failed;
4215 }
4216
Johan Hedberg2922a942014-12-05 13:36:06 +02004217 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004218 if (!cmd) {
4219 err = -ENOMEM;
4220 goto failed;
4221 }
4222
Johan Hedberg2922a942014-12-05 13:36:06 +02004223 cmd->cmd_complete = generic_cmd_complete;
4224
Marcel Holtmann22078802014-12-05 11:45:22 +01004225 /* Clear the discovery filter first to free any previously
4226 * allocated memory for the UUID list.
4227 */
4228 hci_discovery_filter_clear(hdev);
4229
Andre Guedes4aab14e2012-02-17 20:39:36 -03004230 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004231 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004232
Andre Guedes7c307722013-04-30 15:29:28 -03004233 hci_req_init(&req, hdev);
4234
Marcel Holtmann80190442014-12-04 11:36:36 +01004235 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004236 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4237 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004238 mgmt_pending_remove(cmd);
4239 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004240 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004241
Andre Guedes7c307722013-04-30 15:29:28 -03004242 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004243 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004244 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004245 goto failed;
4246 }
4247
4248 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004249
4250failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004251 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004252 return err;
4253}
4254
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004255static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4256 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004257{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004258 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4259 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004260}
4261
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004262static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4263 void *data, u16 len)
4264{
4265 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004266 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004267 struct hci_request req;
4268 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4269 u16 uuid_count, expected_len;
4270 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004271 int err;
4272
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004273 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004274
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004275 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004276
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004277 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004278 err = mgmt_cmd_complete(sk, hdev->id,
4279 MGMT_OP_START_SERVICE_DISCOVERY,
4280 MGMT_STATUS_NOT_POWERED,
4281 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004282 goto failed;
4283 }
4284
4285 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004286 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004287 err = mgmt_cmd_complete(sk, hdev->id,
4288 MGMT_OP_START_SERVICE_DISCOVERY,
4289 MGMT_STATUS_BUSY, &cp->type,
4290 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004291 goto failed;
4292 }
4293
4294 uuid_count = __le16_to_cpu(cp->uuid_count);
4295 if (uuid_count > max_uuid_count) {
4296 BT_ERR("service_discovery: too big uuid_count value %u",
4297 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004298 err = mgmt_cmd_complete(sk, hdev->id,
4299 MGMT_OP_START_SERVICE_DISCOVERY,
4300 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4301 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004302 goto failed;
4303 }
4304
4305 expected_len = sizeof(*cp) + uuid_count * 16;
4306 if (expected_len != len) {
4307 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4308 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004309 err = mgmt_cmd_complete(sk, hdev->id,
4310 MGMT_OP_START_SERVICE_DISCOVERY,
4311 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4312 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004313 goto failed;
4314 }
4315
4316 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004317 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004318 if (!cmd) {
4319 err = -ENOMEM;
4320 goto failed;
4321 }
4322
Johan Hedberg2922a942014-12-05 13:36:06 +02004323 cmd->cmd_complete = service_discovery_cmd_complete;
4324
Marcel Holtmann22078802014-12-05 11:45:22 +01004325 /* Clear the discovery filter first to free any previously
4326 * allocated memory for the UUID list.
4327 */
4328 hci_discovery_filter_clear(hdev);
4329
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004330 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004331 hdev->discovery.type = cp->type;
4332 hdev->discovery.rssi = cp->rssi;
4333 hdev->discovery.uuid_count = uuid_count;
4334
4335 if (uuid_count > 0) {
4336 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4337 GFP_KERNEL);
4338 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004339 err = mgmt_cmd_complete(sk, hdev->id,
4340 MGMT_OP_START_SERVICE_DISCOVERY,
4341 MGMT_STATUS_FAILED,
4342 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004343 mgmt_pending_remove(cmd);
4344 goto failed;
4345 }
4346 }
4347
4348 hci_req_init(&req, hdev);
4349
4350 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004351 err = mgmt_cmd_complete(sk, hdev->id,
4352 MGMT_OP_START_SERVICE_DISCOVERY,
4353 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004354 mgmt_pending_remove(cmd);
4355 goto failed;
4356 }
4357
4358 err = hci_req_run(&req, start_discovery_complete);
4359 if (err < 0) {
4360 mgmt_pending_remove(cmd);
4361 goto failed;
4362 }
4363
4364 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4365
4366failed:
4367 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004368 return err;
4369}
4370
Marcel Holtmann1904a852015-01-11 13:50:44 -08004371static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004372{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004373 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004374
Andre Guedes0e05bba2013-04-30 15:29:33 -03004375 BT_DBG("status %d", status);
4376
4377 hci_dev_lock(hdev);
4378
Johan Hedberg333ae952015-03-17 13:48:47 +02004379 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004380 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004381 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004382 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004383 }
4384
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004385 if (!status)
4386 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004387
Andre Guedes0e05bba2013-04-30 15:29:33 -03004388 hci_dev_unlock(hdev);
4389}
4390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004391static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004392 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004393{
Johan Hedbergd9306502012-02-20 23:25:18 +02004394 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004395 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004396 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004397 int err;
4398
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004399 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004400
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004401 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004402
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004403 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004404 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4405 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4406 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004407 goto unlock;
4408 }
4409
4410 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004411 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4412 MGMT_STATUS_INVALID_PARAMS,
4413 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004414 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004415 }
4416
Johan Hedberg2922a942014-12-05 13:36:06 +02004417 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004418 if (!cmd) {
4419 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004420 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004421 }
4422
Johan Hedberg2922a942014-12-05 13:36:06 +02004423 cmd->cmd_complete = generic_cmd_complete;
4424
Andre Guedes0e05bba2013-04-30 15:29:33 -03004425 hci_req_init(&req, hdev);
4426
Johan Hedberg21a60d32014-06-10 14:05:58 +03004427 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004428
Johan Hedberg21a60d32014-06-10 14:05:58 +03004429 err = hci_req_run(&req, stop_discovery_complete);
4430 if (!err) {
4431 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004432 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004433 }
4434
Johan Hedberg21a60d32014-06-10 14:05:58 +03004435 mgmt_pending_remove(cmd);
4436
4437 /* If no HCI commands were sent we're done */
4438 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004439 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4440 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004441 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4442 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004443
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004444unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004445 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004446 return err;
4447}
4448
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004449static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004450 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004451{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004452 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004453 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004454 int err;
4455
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004456 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004457
Johan Hedberg561aafb2012-01-04 13:31:59 +02004458 hci_dev_lock(hdev);
4459
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004460 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004461 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4462 MGMT_STATUS_FAILED, &cp->addr,
4463 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004464 goto failed;
4465 }
4466
Johan Hedberga198e7b2012-02-17 14:27:06 +02004467 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004468 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004469 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4470 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4471 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004472 goto failed;
4473 }
4474
4475 if (cp->name_known) {
4476 e->name_state = NAME_KNOWN;
4477 list_del(&e->list);
4478 } else {
4479 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004480 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004481 }
4482
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004483 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4484 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004485
4486failed:
4487 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004488 return err;
4489}
4490
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004491static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004492 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004493{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004494 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004495 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004496 int err;
4497
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004498 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004499
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004500 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004501 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4502 MGMT_STATUS_INVALID_PARAMS,
4503 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004504
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004505 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004506
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004507 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4508 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004509 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004510 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004511 goto done;
4512 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004513
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004514 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4515 sk);
4516 status = MGMT_STATUS_SUCCESS;
4517
4518done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004519 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4520 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004521
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004522 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004523
4524 return err;
4525}
4526
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004527static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004528 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004529{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004530 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004531 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004532 int err;
4533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004534 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004535
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004536 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004537 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4538 MGMT_STATUS_INVALID_PARAMS,
4539 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004540
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004541 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004542
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004543 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4544 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004545 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004546 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004547 goto done;
4548 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004549
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004550 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4551 sk);
4552 status = MGMT_STATUS_SUCCESS;
4553
4554done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004555 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4556 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004557
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004558 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004559
4560 return err;
4561}
4562
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004563static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4564 u16 len)
4565{
4566 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004567 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004568 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004569 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004570
4571 BT_DBG("%s", hdev->name);
4572
Szymon Jancc72d4b82012-03-16 16:02:57 +01004573 source = __le16_to_cpu(cp->source);
4574
4575 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004576 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4577 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004578
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004579 hci_dev_lock(hdev);
4580
Szymon Jancc72d4b82012-03-16 16:02:57 +01004581 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004582 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4583 hdev->devid_product = __le16_to_cpu(cp->product);
4584 hdev->devid_version = __le16_to_cpu(cp->version);
4585
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004586 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4587 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004588
Johan Hedberg890ea892013-03-15 17:06:52 -05004589 hci_req_init(&req, hdev);
4590 update_eir(&req);
4591 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004592
4593 hci_dev_unlock(hdev);
4594
4595 return err;
4596}
4597
Arman Uguray24b4f382015-03-23 15:57:12 -07004598static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4599 u16 opcode)
4600{
4601 BT_DBG("status %d", status);
4602}
4603
Marcel Holtmann1904a852015-01-11 13:50:44 -08004604static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4605 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004606{
4607 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004608 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004609
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304610 hci_dev_lock(hdev);
4611
Johan Hedberg4375f102013-09-25 13:26:10 +03004612 if (status) {
4613 u8 mgmt_err = mgmt_status(status);
4614
4615 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4616 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304617 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004618 }
4619
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004620 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004621 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004622 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004623 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004624
Johan Hedberg4375f102013-09-25 13:26:10 +03004625 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4626 &match);
4627
4628 new_settings(hdev, match.sk);
4629
4630 if (match.sk)
4631 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304632
Arman Uguray24b4f382015-03-23 15:57:12 -07004633 /* If "Set Advertising" was just disabled and instance advertising was
4634 * set up earlier, then enable the advertising instance.
4635 */
4636 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4637 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4638 goto unlock;
4639
4640 hci_req_init(&req, hdev);
4641
4642 update_adv_data(&req);
4643 enable_advertising(&req);
4644
4645 if (hci_req_run(&req, enable_advertising_instance) < 0)
4646 BT_ERR("Failed to re-configure advertising");
4647
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304648unlock:
4649 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004650}
4651
Marcel Holtmann21b51872013-10-10 09:47:53 -07004652static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4653 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004654{
4655 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004656 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004657 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004658 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004659 int err;
4660
4661 BT_DBG("request for %s", hdev->name);
4662
Johan Hedberge6fe7982013-10-02 15:45:22 +03004663 status = mgmt_le_support(hdev);
4664 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004665 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4666 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004667
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004668 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004669 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4670 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004671
4672 hci_dev_lock(hdev);
4673
4674 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004675
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004676 /* The following conditions are ones which mean that we should
4677 * not do any HCI communication but directly send a mgmt
4678 * response to user space (after toggling the flag if
4679 * necessary).
4680 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004681 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004682 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4683 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004684 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004685 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004686 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004687 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004688
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004689 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004690 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004691 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004692 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004693 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004694 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004695 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004696 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004697 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004698 }
4699
4700 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4701 if (err < 0)
4702 goto unlock;
4703
4704 if (changed)
4705 err = new_settings(hdev, sk);
4706
4707 goto unlock;
4708 }
4709
Johan Hedberg333ae952015-03-17 13:48:47 +02004710 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4711 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004712 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4713 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004714 goto unlock;
4715 }
4716
4717 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4718 if (!cmd) {
4719 err = -ENOMEM;
4720 goto unlock;
4721 }
4722
4723 hci_req_init(&req, hdev);
4724
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004725 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004726 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004727 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004728 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004729
Arman Uguray24b4f382015-03-23 15:57:12 -07004730 if (val) {
4731 /* Switch to instance "0" for the Set Advertising setting. */
4732 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004733 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004734 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004735 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004736 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004737 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004738
4739 err = hci_req_run(&req, set_advertising_complete);
4740 if (err < 0)
4741 mgmt_pending_remove(cmd);
4742
4743unlock:
4744 hci_dev_unlock(hdev);
4745 return err;
4746}
4747
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004748static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4749 void *data, u16 len)
4750{
4751 struct mgmt_cp_set_static_address *cp = data;
4752 int err;
4753
4754 BT_DBG("%s", hdev->name);
4755
Marcel Holtmann62af4442013-10-02 22:10:32 -07004756 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004757 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4758 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004759
4760 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004761 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4762 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004763
4764 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4765 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004766 return mgmt_cmd_status(sk, hdev->id,
4767 MGMT_OP_SET_STATIC_ADDRESS,
4768 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004769
4770 /* Two most significant bits shall be set */
4771 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004772 return mgmt_cmd_status(sk, hdev->id,
4773 MGMT_OP_SET_STATIC_ADDRESS,
4774 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004775 }
4776
4777 hci_dev_lock(hdev);
4778
4779 bacpy(&hdev->static_addr, &cp->bdaddr);
4780
Marcel Holtmann93690c22015-03-06 10:11:21 -08004781 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4782 if (err < 0)
4783 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004784
Marcel Holtmann93690c22015-03-06 10:11:21 -08004785 err = new_settings(hdev, sk);
4786
4787unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004788 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004789 return err;
4790}
4791
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004792static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4793 void *data, u16 len)
4794{
4795 struct mgmt_cp_set_scan_params *cp = data;
4796 __u16 interval, window;
4797 int err;
4798
4799 BT_DBG("%s", hdev->name);
4800
4801 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004802 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4803 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004804
4805 interval = __le16_to_cpu(cp->interval);
4806
4807 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004808 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4809 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004810
4811 window = __le16_to_cpu(cp->window);
4812
4813 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004814 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4815 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004816
Marcel Holtmann899e1072013-10-14 09:55:32 -07004817 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004818 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4819 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004820
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004821 hci_dev_lock(hdev);
4822
4823 hdev->le_scan_interval = interval;
4824 hdev->le_scan_window = window;
4825
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004826 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4827 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004828
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004829 /* If background scan is running, restart it so new parameters are
4830 * loaded.
4831 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004832 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004833 hdev->discovery.state == DISCOVERY_STOPPED) {
4834 struct hci_request req;
4835
4836 hci_req_init(&req, hdev);
4837
4838 hci_req_add_le_scan_disable(&req);
4839 hci_req_add_le_passive_scan(&req);
4840
4841 hci_req_run(&req, NULL);
4842 }
4843
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004844 hci_dev_unlock(hdev);
4845
4846 return err;
4847}
4848
Marcel Holtmann1904a852015-01-11 13:50:44 -08004849static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4850 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004851{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004852 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004853
4854 BT_DBG("status 0x%02x", status);
4855
4856 hci_dev_lock(hdev);
4857
Johan Hedberg333ae952015-03-17 13:48:47 +02004858 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004859 if (!cmd)
4860 goto unlock;
4861
4862 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004863 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4864 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004865 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004866 struct mgmt_mode *cp = cmd->param;
4867
4868 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004869 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004870 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004871 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004872
Johan Hedberg33e38b32013-03-15 17:07:05 -05004873 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4874 new_settings(hdev, cmd->sk);
4875 }
4876
4877 mgmt_pending_remove(cmd);
4878
4879unlock:
4880 hci_dev_unlock(hdev);
4881}
4882
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004883static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004884 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004885{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004886 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004887 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004888 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004889 int err;
4890
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004891 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004892
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004893 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004894 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004895 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4896 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004897
Johan Hedberga7e80f22013-01-09 16:05:19 +02004898 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004899 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4900 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004901
Antti Julkuf6422ec2011-06-22 13:11:56 +03004902 hci_dev_lock(hdev);
4903
Johan Hedberg333ae952015-03-17 13:48:47 +02004904 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004905 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4906 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004907 goto unlock;
4908 }
4909
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004910 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004911 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4912 hdev);
4913 goto unlock;
4914 }
4915
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004916 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004917 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004918 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4919 hdev);
4920 new_settings(hdev, sk);
4921 goto unlock;
4922 }
4923
Johan Hedberg33e38b32013-03-15 17:07:05 -05004924 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4925 data, len);
4926 if (!cmd) {
4927 err = -ENOMEM;
4928 goto unlock;
4929 }
4930
4931 hci_req_init(&req, hdev);
4932
Johan Hedberg406d7802013-03-15 17:07:09 -05004933 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004934
4935 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004936 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004937 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4938 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004939 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004940 }
4941
Johan Hedberg33e38b32013-03-15 17:07:05 -05004942unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004943 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004944
Antti Julkuf6422ec2011-06-22 13:11:56 +03004945 return err;
4946}
4947
Marcel Holtmann1904a852015-01-11 13:50:44 -08004948static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004949{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004950 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004951
4952 BT_DBG("status 0x%02x", status);
4953
4954 hci_dev_lock(hdev);
4955
Johan Hedberg333ae952015-03-17 13:48:47 +02004956 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004957 if (!cmd)
4958 goto unlock;
4959
4960 if (status) {
4961 u8 mgmt_err = mgmt_status(status);
4962
4963 /* We need to restore the flag if related HCI commands
4964 * failed.
4965 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004966 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004967
Johan Hedberga69e8372015-03-06 21:08:53 +02004968 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004969 } else {
4970 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4971 new_settings(hdev, cmd->sk);
4972 }
4973
4974 mgmt_pending_remove(cmd);
4975
4976unlock:
4977 hci_dev_unlock(hdev);
4978}
4979
4980static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4981{
4982 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004983 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004984 struct hci_request req;
4985 int err;
4986
4987 BT_DBG("request for %s", hdev->name);
4988
4989 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004990 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4991 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004992
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004993 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004994 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4995 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004996
4997 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004998 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4999 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005000
5001 hci_dev_lock(hdev);
5002
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005003 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005004 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5005 goto unlock;
5006 }
5007
5008 if (!hdev_is_powered(hdev)) {
5009 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005010 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5011 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5012 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5013 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5014 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005015 }
5016
Marcel Holtmannce05d602015-03-13 02:11:03 -07005017 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005018
5019 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5020 if (err < 0)
5021 goto unlock;
5022
5023 err = new_settings(hdev, sk);
5024 goto unlock;
5025 }
5026
5027 /* Reject disabling when powered on */
5028 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005029 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5030 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005031 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005032 } else {
5033 /* When configuring a dual-mode controller to operate
5034 * with LE only and using a static address, then switching
5035 * BR/EDR back on is not allowed.
5036 *
5037 * Dual-mode controllers shall operate with the public
5038 * address as its identity address for BR/EDR and LE. So
5039 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005040 *
5041 * The same restrictions applies when secure connections
5042 * has been enabled. For BR/EDR this is a controller feature
5043 * while for LE it is a host stack feature. This means that
5044 * switching BR/EDR back on when secure connections has been
5045 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005046 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005047 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005048 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005049 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005050 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5051 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005052 goto unlock;
5053 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005054 }
5055
Johan Hedberg333ae952015-03-17 13:48:47 +02005056 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005057 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5058 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005059 goto unlock;
5060 }
5061
5062 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5063 if (!cmd) {
5064 err = -ENOMEM;
5065 goto unlock;
5066 }
5067
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005068 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005069 * generates the correct flags.
5070 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005071 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005072
5073 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005074
Johan Hedberg432df052014-08-01 11:13:31 +03005075 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005076 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005077
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005078 /* Since only the advertising data flags will change, there
5079 * is no need to update the scan response data.
5080 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005081 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005082
Johan Hedberg0663ca22013-10-02 13:43:14 +03005083 err = hci_req_run(&req, set_bredr_complete);
5084 if (err < 0)
5085 mgmt_pending_remove(cmd);
5086
5087unlock:
5088 hci_dev_unlock(hdev);
5089 return err;
5090}
5091
Johan Hedberga1443f52015-01-23 15:42:46 +02005092static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5093{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005094 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005095 struct mgmt_mode *cp;
5096
5097 BT_DBG("%s status %u", hdev->name, status);
5098
5099 hci_dev_lock(hdev);
5100
Johan Hedberg333ae952015-03-17 13:48:47 +02005101 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005102 if (!cmd)
5103 goto unlock;
5104
5105 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005106 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5107 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005108 goto remove;
5109 }
5110
5111 cp = cmd->param;
5112
5113 switch (cp->val) {
5114 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005115 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5116 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005117 break;
5118 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005119 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005120 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005121 break;
5122 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005123 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5124 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005125 break;
5126 }
5127
5128 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5129 new_settings(hdev, cmd->sk);
5130
5131remove:
5132 mgmt_pending_remove(cmd);
5133unlock:
5134 hci_dev_unlock(hdev);
5135}
5136
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005137static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5138 void *data, u16 len)
5139{
5140 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005141 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005142 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005143 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005144 int err;
5145
5146 BT_DBG("request for %s", hdev->name);
5147
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005148 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005149 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005150 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5151 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005152
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005153 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005154 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005155 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005156 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5157 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005158
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005159 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005160 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005161 MGMT_STATUS_INVALID_PARAMS);
5162
5163 hci_dev_lock(hdev);
5164
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005165 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005166 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005167 bool changed;
5168
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005169 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005170 changed = !hci_dev_test_and_set_flag(hdev,
5171 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005172 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005173 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005174 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005175 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005176 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005177 changed = hci_dev_test_and_clear_flag(hdev,
5178 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005179 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005180 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005181
5182 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5183 if (err < 0)
5184 goto failed;
5185
5186 if (changed)
5187 err = new_settings(hdev, sk);
5188
5189 goto failed;
5190 }
5191
Johan Hedberg333ae952015-03-17 13:48:47 +02005192 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005193 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5194 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005195 goto failed;
5196 }
5197
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005198 val = !!cp->val;
5199
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005200 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5201 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005202 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5203 goto failed;
5204 }
5205
5206 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5207 if (!cmd) {
5208 err = -ENOMEM;
5209 goto failed;
5210 }
5211
Johan Hedberga1443f52015-01-23 15:42:46 +02005212 hci_req_init(&req, hdev);
5213 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5214 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005215 if (err < 0) {
5216 mgmt_pending_remove(cmd);
5217 goto failed;
5218 }
5219
5220failed:
5221 hci_dev_unlock(hdev);
5222 return err;
5223}
5224
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005225static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5226 void *data, u16 len)
5227{
5228 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005229 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005230 int err;
5231
5232 BT_DBG("request for %s", hdev->name);
5233
Johan Hedbergb97109792014-06-24 14:00:28 +03005234 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005235 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5236 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005237
5238 hci_dev_lock(hdev);
5239
5240 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005241 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005242 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005243 changed = hci_dev_test_and_clear_flag(hdev,
5244 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005245
Johan Hedbergb97109792014-06-24 14:00:28 +03005246 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005247 use_changed = !hci_dev_test_and_set_flag(hdev,
5248 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005249 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005250 use_changed = hci_dev_test_and_clear_flag(hdev,
5251 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005252
5253 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005254 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005255 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5256 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5257 sizeof(mode), &mode);
5258 }
5259
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005260 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5261 if (err < 0)
5262 goto unlock;
5263
5264 if (changed)
5265 err = new_settings(hdev, sk);
5266
5267unlock:
5268 hci_dev_unlock(hdev);
5269 return err;
5270}
5271
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005272static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5273 u16 len)
5274{
5275 struct mgmt_cp_set_privacy *cp = cp_data;
5276 bool changed;
5277 int err;
5278
5279 BT_DBG("request for %s", hdev->name);
5280
5281 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005282 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5283 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005284
5285 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005286 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5287 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005288
5289 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005290 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5291 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005292
5293 hci_dev_lock(hdev);
5294
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005295 /* If user space supports this command it is also expected to
5296 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5297 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005298 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005299
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005300 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005301 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005302 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005303 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005304 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005305 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005306 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005307 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005308 }
5309
5310 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5311 if (err < 0)
5312 goto unlock;
5313
5314 if (changed)
5315 err = new_settings(hdev, sk);
5316
5317unlock:
5318 hci_dev_unlock(hdev);
5319 return err;
5320}
5321
Johan Hedberg41edf162014-02-18 10:19:35 +02005322static bool irk_is_valid(struct mgmt_irk_info *irk)
5323{
5324 switch (irk->addr.type) {
5325 case BDADDR_LE_PUBLIC:
5326 return true;
5327
5328 case BDADDR_LE_RANDOM:
5329 /* Two most significant bits shall be set */
5330 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5331 return false;
5332 return true;
5333 }
5334
5335 return false;
5336}
5337
5338static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5339 u16 len)
5340{
5341 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005342 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5343 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005344 u16 irk_count, expected_len;
5345 int i, err;
5346
5347 BT_DBG("request for %s", hdev->name);
5348
5349 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005350 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5351 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005352
5353 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005354 if (irk_count > max_irk_count) {
5355 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005356 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5357 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005358 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005359
5360 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5361 if (expected_len != len) {
5362 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005363 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005364 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5365 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005366 }
5367
5368 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5369
5370 for (i = 0; i < irk_count; i++) {
5371 struct mgmt_irk_info *key = &cp->irks[i];
5372
5373 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005374 return mgmt_cmd_status(sk, hdev->id,
5375 MGMT_OP_LOAD_IRKS,
5376 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005377 }
5378
5379 hci_dev_lock(hdev);
5380
5381 hci_smp_irks_clear(hdev);
5382
5383 for (i = 0; i < irk_count; i++) {
5384 struct mgmt_irk_info *irk = &cp->irks[i];
5385 u8 addr_type;
5386
5387 if (irk->addr.type == BDADDR_LE_PUBLIC)
5388 addr_type = ADDR_LE_DEV_PUBLIC;
5389 else
5390 addr_type = ADDR_LE_DEV_RANDOM;
5391
5392 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5393 BDADDR_ANY);
5394 }
5395
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005396 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005397
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005398 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005399
5400 hci_dev_unlock(hdev);
5401
5402 return err;
5403}
5404
Johan Hedberg3f706b72013-01-20 14:27:16 +02005405static bool ltk_is_valid(struct mgmt_ltk_info *key)
5406{
5407 if (key->master != 0x00 && key->master != 0x01)
5408 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005409
5410 switch (key->addr.type) {
5411 case BDADDR_LE_PUBLIC:
5412 return true;
5413
5414 case BDADDR_LE_RANDOM:
5415 /* Two most significant bits shall be set */
5416 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5417 return false;
5418 return true;
5419 }
5420
5421 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005422}
5423
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005424static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005425 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005426{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005427 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005428 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5429 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005430 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005431 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005432
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005433 BT_DBG("request for %s", hdev->name);
5434
5435 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005436 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5437 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005438
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005439 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005440 if (key_count > max_key_count) {
5441 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005442 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5443 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005444 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005445
5446 expected_len = sizeof(*cp) + key_count *
5447 sizeof(struct mgmt_ltk_info);
5448 if (expected_len != len) {
5449 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005450 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005451 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5452 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005453 }
5454
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005455 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005456
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005457 for (i = 0; i < key_count; i++) {
5458 struct mgmt_ltk_info *key = &cp->keys[i];
5459
Johan Hedberg3f706b72013-01-20 14:27:16 +02005460 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005461 return mgmt_cmd_status(sk, hdev->id,
5462 MGMT_OP_LOAD_LONG_TERM_KEYS,
5463 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005464 }
5465
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005466 hci_dev_lock(hdev);
5467
5468 hci_smp_ltks_clear(hdev);
5469
5470 for (i = 0; i < key_count; i++) {
5471 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005472 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005473
5474 if (key->addr.type == BDADDR_LE_PUBLIC)
5475 addr_type = ADDR_LE_DEV_PUBLIC;
5476 else
5477 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005478
Johan Hedberg61b43352014-05-29 19:36:53 +03005479 switch (key->type) {
5480 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005481 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005482 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005483 break;
5484 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005485 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005486 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005487 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005488 case MGMT_LTK_P256_UNAUTH:
5489 authenticated = 0x00;
5490 type = SMP_LTK_P256;
5491 break;
5492 case MGMT_LTK_P256_AUTH:
5493 authenticated = 0x01;
5494 type = SMP_LTK_P256;
5495 break;
5496 case MGMT_LTK_P256_DEBUG:
5497 authenticated = 0x00;
5498 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005499 default:
5500 continue;
5501 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005502
Johan Hedberg35d70272014-02-19 14:57:47 +02005503 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005504 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005505 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005506 }
5507
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005508 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005509 NULL, 0);
5510
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005511 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005512
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005513 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005514}
5515
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005516static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005517{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005518 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005519 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005520 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005521
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005522 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005523
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005524 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005525 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005526 rp.tx_power = conn->tx_power;
5527 rp.max_tx_power = conn->max_tx_power;
5528 } else {
5529 rp.rssi = HCI_RSSI_INVALID;
5530 rp.tx_power = HCI_TX_POWER_INVALID;
5531 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005532 }
5533
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005534 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5535 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005536
5537 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005538 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005539
5540 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005541}
5542
Marcel Holtmann1904a852015-01-11 13:50:44 -08005543static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5544 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005545{
5546 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005547 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005548 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005549 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005550 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005551
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005552 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005553
5554 hci_dev_lock(hdev);
5555
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005556 /* Commands sent in request are either Read RSSI or Read Transmit Power
5557 * Level so we check which one was last sent to retrieve connection
5558 * handle. Both commands have handle as first parameter so it's safe to
5559 * cast data on the same command struct.
5560 *
5561 * First command sent is always Read RSSI and we fail only if it fails.
5562 * In other case we simply override error to indicate success as we
5563 * already remembered if TX power value is actually valid.
5564 */
5565 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5566 if (!cp) {
5567 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005568 status = MGMT_STATUS_SUCCESS;
5569 } else {
5570 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005571 }
5572
5573 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005574 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005575 goto unlock;
5576 }
5577
5578 handle = __le16_to_cpu(cp->handle);
5579 conn = hci_conn_hash_lookup_handle(hdev, handle);
5580 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005581 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005582 goto unlock;
5583 }
5584
Johan Hedberg333ae952015-03-17 13:48:47 +02005585 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005586 if (!cmd)
5587 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005588
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005589 cmd->cmd_complete(cmd, status);
5590 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005591
5592unlock:
5593 hci_dev_unlock(hdev);
5594}
5595
5596static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5597 u16 len)
5598{
5599 struct mgmt_cp_get_conn_info *cp = data;
5600 struct mgmt_rp_get_conn_info rp;
5601 struct hci_conn *conn;
5602 unsigned long conn_info_age;
5603 int err = 0;
5604
5605 BT_DBG("%s", hdev->name);
5606
5607 memset(&rp, 0, sizeof(rp));
5608 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5609 rp.addr.type = cp->addr.type;
5610
5611 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005612 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5613 MGMT_STATUS_INVALID_PARAMS,
5614 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005615
5616 hci_dev_lock(hdev);
5617
5618 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005619 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5620 MGMT_STATUS_NOT_POWERED, &rp,
5621 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005622 goto unlock;
5623 }
5624
5625 if (cp->addr.type == BDADDR_BREDR)
5626 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5627 &cp->addr.bdaddr);
5628 else
5629 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5630
5631 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005632 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5633 MGMT_STATUS_NOT_CONNECTED, &rp,
5634 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005635 goto unlock;
5636 }
5637
Johan Hedberg333ae952015-03-17 13:48:47 +02005638 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005639 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5640 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005641 goto unlock;
5642 }
5643
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005644 /* To avoid client trying to guess when to poll again for information we
5645 * calculate conn info age as random value between min/max set in hdev.
5646 */
5647 conn_info_age = hdev->conn_info_min_age +
5648 prandom_u32_max(hdev->conn_info_max_age -
5649 hdev->conn_info_min_age);
5650
5651 /* Query controller to refresh cached values if they are too old or were
5652 * never read.
5653 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005654 if (time_after(jiffies, conn->conn_info_timestamp +
5655 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005656 !conn->conn_info_timestamp) {
5657 struct hci_request req;
5658 struct hci_cp_read_tx_power req_txp_cp;
5659 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005660 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005661
5662 hci_req_init(&req, hdev);
5663 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5664 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5665 &req_rssi_cp);
5666
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005667 /* For LE links TX power does not change thus we don't need to
5668 * query for it once value is known.
5669 */
5670 if (!bdaddr_type_is_le(cp->addr.type) ||
5671 conn->tx_power == HCI_TX_POWER_INVALID) {
5672 req_txp_cp.handle = cpu_to_le16(conn->handle);
5673 req_txp_cp.type = 0x00;
5674 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5675 sizeof(req_txp_cp), &req_txp_cp);
5676 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005677
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005678 /* Max TX power needs to be read only once per connection */
5679 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5680 req_txp_cp.handle = cpu_to_le16(conn->handle);
5681 req_txp_cp.type = 0x01;
5682 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5683 sizeof(req_txp_cp), &req_txp_cp);
5684 }
5685
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005686 err = hci_req_run(&req, conn_info_refresh_complete);
5687 if (err < 0)
5688 goto unlock;
5689
5690 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5691 data, len);
5692 if (!cmd) {
5693 err = -ENOMEM;
5694 goto unlock;
5695 }
5696
5697 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005698 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005699 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005700
5701 conn->conn_info_timestamp = jiffies;
5702 } else {
5703 /* Cache is valid, just reply with values cached in hci_conn */
5704 rp.rssi = conn->rssi;
5705 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005706 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005707
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005708 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5709 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005710 }
5711
5712unlock:
5713 hci_dev_unlock(hdev);
5714 return err;
5715}
5716
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005717static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005718{
5719 struct hci_conn *conn = cmd->user_data;
5720 struct mgmt_rp_get_clock_info rp;
5721 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005722 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005723
5724 memset(&rp, 0, sizeof(rp));
5725 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5726
5727 if (status)
5728 goto complete;
5729
5730 hdev = hci_dev_get(cmd->index);
5731 if (hdev) {
5732 rp.local_clock = cpu_to_le32(hdev->clock);
5733 hci_dev_put(hdev);
5734 }
5735
5736 if (conn) {
5737 rp.piconet_clock = cpu_to_le32(conn->clock);
5738 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5739 }
5740
5741complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005742 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5743 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005744
5745 if (conn) {
5746 hci_conn_drop(conn);
5747 hci_conn_put(conn);
5748 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005749
5750 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005751}
5752
Marcel Holtmann1904a852015-01-11 13:50:44 -08005753static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005754{
Johan Hedberg95868422014-06-28 17:54:07 +03005755 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005756 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005757 struct hci_conn *conn;
5758
5759 BT_DBG("%s status %u", hdev->name, status);
5760
5761 hci_dev_lock(hdev);
5762
5763 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5764 if (!hci_cp)
5765 goto unlock;
5766
5767 if (hci_cp->which) {
5768 u16 handle = __le16_to_cpu(hci_cp->handle);
5769 conn = hci_conn_hash_lookup_handle(hdev, handle);
5770 } else {
5771 conn = NULL;
5772 }
5773
Johan Hedberg333ae952015-03-17 13:48:47 +02005774 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005775 if (!cmd)
5776 goto unlock;
5777
Johan Hedberg69487372014-12-05 13:36:07 +02005778 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005779 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005780
5781unlock:
5782 hci_dev_unlock(hdev);
5783}
5784
5785static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5786 u16 len)
5787{
5788 struct mgmt_cp_get_clock_info *cp = data;
5789 struct mgmt_rp_get_clock_info rp;
5790 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005791 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005792 struct hci_request req;
5793 struct hci_conn *conn;
5794 int err;
5795
5796 BT_DBG("%s", hdev->name);
5797
5798 memset(&rp, 0, sizeof(rp));
5799 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5800 rp.addr.type = cp->addr.type;
5801
5802 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005803 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5804 MGMT_STATUS_INVALID_PARAMS,
5805 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005806
5807 hci_dev_lock(hdev);
5808
5809 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005810 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5811 MGMT_STATUS_NOT_POWERED, &rp,
5812 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005813 goto unlock;
5814 }
5815
5816 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5817 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5818 &cp->addr.bdaddr);
5819 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005820 err = mgmt_cmd_complete(sk, hdev->id,
5821 MGMT_OP_GET_CLOCK_INFO,
5822 MGMT_STATUS_NOT_CONNECTED,
5823 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005824 goto unlock;
5825 }
5826 } else {
5827 conn = NULL;
5828 }
5829
5830 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5831 if (!cmd) {
5832 err = -ENOMEM;
5833 goto unlock;
5834 }
5835
Johan Hedberg69487372014-12-05 13:36:07 +02005836 cmd->cmd_complete = clock_info_cmd_complete;
5837
Johan Hedberg95868422014-06-28 17:54:07 +03005838 hci_req_init(&req, hdev);
5839
5840 memset(&hci_cp, 0, sizeof(hci_cp));
5841 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5842
5843 if (conn) {
5844 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005845 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005846
5847 hci_cp.handle = cpu_to_le16(conn->handle);
5848 hci_cp.which = 0x01; /* Piconet clock */
5849 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5850 }
5851
5852 err = hci_req_run(&req, get_clock_info_complete);
5853 if (err < 0)
5854 mgmt_pending_remove(cmd);
5855
5856unlock:
5857 hci_dev_unlock(hdev);
5858 return err;
5859}
5860
Johan Hedberg5a154e62014-12-19 22:26:02 +02005861static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5862{
5863 struct hci_conn *conn;
5864
5865 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5866 if (!conn)
5867 return false;
5868
5869 if (conn->dst_type != type)
5870 return false;
5871
5872 if (conn->state != BT_CONNECTED)
5873 return false;
5874
5875 return true;
5876}
5877
5878/* This function requires the caller holds hdev->lock */
5879static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5880 u8 addr_type, u8 auto_connect)
5881{
5882 struct hci_dev *hdev = req->hdev;
5883 struct hci_conn_params *params;
5884
5885 params = hci_conn_params_add(hdev, addr, addr_type);
5886 if (!params)
5887 return -EIO;
5888
5889 if (params->auto_connect == auto_connect)
5890 return 0;
5891
5892 list_del_init(&params->action);
5893
5894 switch (auto_connect) {
5895 case HCI_AUTO_CONN_DISABLED:
5896 case HCI_AUTO_CONN_LINK_LOSS:
5897 __hci_update_background_scan(req);
5898 break;
5899 case HCI_AUTO_CONN_REPORT:
5900 list_add(&params->action, &hdev->pend_le_reports);
5901 __hci_update_background_scan(req);
5902 break;
5903 case HCI_AUTO_CONN_DIRECT:
5904 case HCI_AUTO_CONN_ALWAYS:
5905 if (!is_connected(hdev, addr, addr_type)) {
5906 list_add(&params->action, &hdev->pend_le_conns);
5907 __hci_update_background_scan(req);
5908 }
5909 break;
5910 }
5911
5912 params->auto_connect = auto_connect;
5913
5914 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5915 auto_connect);
5916
5917 return 0;
5918}
5919
Marcel Holtmann8afef092014-06-29 22:28:34 +02005920static void device_added(struct sock *sk, struct hci_dev *hdev,
5921 bdaddr_t *bdaddr, u8 type, u8 action)
5922{
5923 struct mgmt_ev_device_added ev;
5924
5925 bacpy(&ev.addr.bdaddr, bdaddr);
5926 ev.addr.type = type;
5927 ev.action = action;
5928
5929 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5930}
5931
Marcel Holtmann1904a852015-01-11 13:50:44 -08005932static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005933{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005934 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005935
5936 BT_DBG("status 0x%02x", status);
5937
5938 hci_dev_lock(hdev);
5939
Johan Hedberg333ae952015-03-17 13:48:47 +02005940 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005941 if (!cmd)
5942 goto unlock;
5943
5944 cmd->cmd_complete(cmd, mgmt_status(status));
5945 mgmt_pending_remove(cmd);
5946
5947unlock:
5948 hci_dev_unlock(hdev);
5949}
5950
Marcel Holtmann2faade52014-06-29 19:44:03 +02005951static int add_device(struct sock *sk, struct hci_dev *hdev,
5952 void *data, u16 len)
5953{
5954 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005955 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005956 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005957 u8 auto_conn, addr_type;
5958 int err;
5959
5960 BT_DBG("%s", hdev->name);
5961
Johan Hedberg66593582014-07-09 12:59:14 +03005962 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005963 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005964 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5965 MGMT_STATUS_INVALID_PARAMS,
5966 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005967
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005968 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005969 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5970 MGMT_STATUS_INVALID_PARAMS,
5971 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005972
Johan Hedberg5a154e62014-12-19 22:26:02 +02005973 hci_req_init(&req, hdev);
5974
Marcel Holtmann2faade52014-06-29 19:44:03 +02005975 hci_dev_lock(hdev);
5976
Johan Hedberg5a154e62014-12-19 22:26:02 +02005977 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5978 if (!cmd) {
5979 err = -ENOMEM;
5980 goto unlock;
5981 }
5982
5983 cmd->cmd_complete = addr_cmd_complete;
5984
Johan Hedberg66593582014-07-09 12:59:14 +03005985 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005986 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005987 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005988 err = cmd->cmd_complete(cmd,
5989 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005990 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005991 goto unlock;
5992 }
5993
5994 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5995 cp->addr.type);
5996 if (err)
5997 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005998
Johan Hedberg5a154e62014-12-19 22:26:02 +02005999 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006000
Johan Hedberg66593582014-07-09 12:59:14 +03006001 goto added;
6002 }
6003
Marcel Holtmann2faade52014-06-29 19:44:03 +02006004 if (cp->addr.type == BDADDR_LE_PUBLIC)
6005 addr_type = ADDR_LE_DEV_PUBLIC;
6006 else
6007 addr_type = ADDR_LE_DEV_RANDOM;
6008
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006009 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006010 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006011 else if (cp->action == 0x01)
6012 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006013 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006014 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006015
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006016 /* If the connection parameters don't exist for this device,
6017 * they will be created and configured with defaults.
6018 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006019 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006020 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006021 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006022 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006023 goto unlock;
6024 }
6025
Johan Hedberg66593582014-07-09 12:59:14 +03006026added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006027 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6028
Johan Hedberg5a154e62014-12-19 22:26:02 +02006029 err = hci_req_run(&req, add_device_complete);
6030 if (err < 0) {
6031 /* ENODATA means no HCI commands were needed (e.g. if
6032 * the adapter is powered off).
6033 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006034 if (err == -ENODATA)
6035 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006036 mgmt_pending_remove(cmd);
6037 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006038
6039unlock:
6040 hci_dev_unlock(hdev);
6041 return err;
6042}
6043
Marcel Holtmann8afef092014-06-29 22:28:34 +02006044static void device_removed(struct sock *sk, struct hci_dev *hdev,
6045 bdaddr_t *bdaddr, u8 type)
6046{
6047 struct mgmt_ev_device_removed ev;
6048
6049 bacpy(&ev.addr.bdaddr, bdaddr);
6050 ev.addr.type = type;
6051
6052 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6053}
6054
Marcel Holtmann1904a852015-01-11 13:50:44 -08006055static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006056{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006057 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006058
6059 BT_DBG("status 0x%02x", status);
6060
6061 hci_dev_lock(hdev);
6062
Johan Hedberg333ae952015-03-17 13:48:47 +02006063 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006064 if (!cmd)
6065 goto unlock;
6066
6067 cmd->cmd_complete(cmd, mgmt_status(status));
6068 mgmt_pending_remove(cmd);
6069
6070unlock:
6071 hci_dev_unlock(hdev);
6072}
6073
Marcel Holtmann2faade52014-06-29 19:44:03 +02006074static int remove_device(struct sock *sk, struct hci_dev *hdev,
6075 void *data, u16 len)
6076{
6077 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006078 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006079 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006080 int err;
6081
6082 BT_DBG("%s", hdev->name);
6083
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006084 hci_req_init(&req, hdev);
6085
Marcel Holtmann2faade52014-06-29 19:44:03 +02006086 hci_dev_lock(hdev);
6087
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006088 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6089 if (!cmd) {
6090 err = -ENOMEM;
6091 goto unlock;
6092 }
6093
6094 cmd->cmd_complete = addr_cmd_complete;
6095
Marcel Holtmann2faade52014-06-29 19:44:03 +02006096 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006097 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006098 u8 addr_type;
6099
Johan Hedberg66593582014-07-09 12:59:14 +03006100 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006101 err = cmd->cmd_complete(cmd,
6102 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006103 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006104 goto unlock;
6105 }
6106
Johan Hedberg66593582014-07-09 12:59:14 +03006107 if (cp->addr.type == BDADDR_BREDR) {
6108 err = hci_bdaddr_list_del(&hdev->whitelist,
6109 &cp->addr.bdaddr,
6110 cp->addr.type);
6111 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006112 err = cmd->cmd_complete(cmd,
6113 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006114 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006115 goto unlock;
6116 }
6117
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006118 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006119
Johan Hedberg66593582014-07-09 12:59:14 +03006120 device_removed(sk, hdev, &cp->addr.bdaddr,
6121 cp->addr.type);
6122 goto complete;
6123 }
6124
Marcel Holtmann2faade52014-06-29 19:44:03 +02006125 if (cp->addr.type == BDADDR_LE_PUBLIC)
6126 addr_type = ADDR_LE_DEV_PUBLIC;
6127 else
6128 addr_type = ADDR_LE_DEV_RANDOM;
6129
Johan Hedbergc71593d2014-07-02 17:37:28 +03006130 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6131 addr_type);
6132 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006133 err = cmd->cmd_complete(cmd,
6134 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006135 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006136 goto unlock;
6137 }
6138
6139 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006140 err = cmd->cmd_complete(cmd,
6141 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006142 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006143 goto unlock;
6144 }
6145
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006146 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006147 list_del(&params->list);
6148 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006149 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006150
6151 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006152 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006153 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006154 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006155
Marcel Holtmann2faade52014-06-29 19:44:03 +02006156 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006157 err = cmd->cmd_complete(cmd,
6158 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006159 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006160 goto unlock;
6161 }
6162
Johan Hedberg66593582014-07-09 12:59:14 +03006163 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6164 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6165 list_del(&b->list);
6166 kfree(b);
6167 }
6168
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006169 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006170
Johan Hedberg19de0822014-07-06 13:06:51 +03006171 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6172 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6173 continue;
6174 device_removed(sk, hdev, &p->addr, p->addr_type);
6175 list_del(&p->action);
6176 list_del(&p->list);
6177 kfree(p);
6178 }
6179
6180 BT_DBG("All LE connection parameters were removed");
6181
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006182 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006183 }
6184
Johan Hedberg66593582014-07-09 12:59:14 +03006185complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006186 err = hci_req_run(&req, remove_device_complete);
6187 if (err < 0) {
6188 /* ENODATA means no HCI commands were needed (e.g. if
6189 * the adapter is powered off).
6190 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006191 if (err == -ENODATA)
6192 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006193 mgmt_pending_remove(cmd);
6194 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006195
6196unlock:
6197 hci_dev_unlock(hdev);
6198 return err;
6199}
6200
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006201static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6202 u16 len)
6203{
6204 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006205 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6206 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006207 u16 param_count, expected_len;
6208 int i;
6209
6210 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006211 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6212 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006213
6214 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006215 if (param_count > max_param_count) {
6216 BT_ERR("load_conn_param: too big param_count value %u",
6217 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006218 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6219 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006220 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006221
6222 expected_len = sizeof(*cp) + param_count *
6223 sizeof(struct mgmt_conn_param);
6224 if (expected_len != len) {
6225 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6226 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006227 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6228 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006229 }
6230
6231 BT_DBG("%s param_count %u", hdev->name, param_count);
6232
6233 hci_dev_lock(hdev);
6234
6235 hci_conn_params_clear_disabled(hdev);
6236
6237 for (i = 0; i < param_count; i++) {
6238 struct mgmt_conn_param *param = &cp->params[i];
6239 struct hci_conn_params *hci_param;
6240 u16 min, max, latency, timeout;
6241 u8 addr_type;
6242
6243 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6244 param->addr.type);
6245
6246 if (param->addr.type == BDADDR_LE_PUBLIC) {
6247 addr_type = ADDR_LE_DEV_PUBLIC;
6248 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6249 addr_type = ADDR_LE_DEV_RANDOM;
6250 } else {
6251 BT_ERR("Ignoring invalid connection parameters");
6252 continue;
6253 }
6254
6255 min = le16_to_cpu(param->min_interval);
6256 max = le16_to_cpu(param->max_interval);
6257 latency = le16_to_cpu(param->latency);
6258 timeout = le16_to_cpu(param->timeout);
6259
6260 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6261 min, max, latency, timeout);
6262
6263 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6264 BT_ERR("Ignoring invalid connection parameters");
6265 continue;
6266 }
6267
6268 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6269 addr_type);
6270 if (!hci_param) {
6271 BT_ERR("Failed to add connection parameters");
6272 continue;
6273 }
6274
6275 hci_param->conn_min_interval = min;
6276 hci_param->conn_max_interval = max;
6277 hci_param->conn_latency = latency;
6278 hci_param->supervision_timeout = timeout;
6279 }
6280
6281 hci_dev_unlock(hdev);
6282
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006283 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6284 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006285}
6286
Marcel Holtmanndbece372014-07-04 18:11:55 +02006287static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6288 void *data, u16 len)
6289{
6290 struct mgmt_cp_set_external_config *cp = data;
6291 bool changed;
6292 int err;
6293
6294 BT_DBG("%s", hdev->name);
6295
6296 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006297 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6298 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006299
6300 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006301 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6302 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006303
6304 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006305 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6306 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006307
6308 hci_dev_lock(hdev);
6309
6310 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006311 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006312 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006313 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006314
6315 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6316 if (err < 0)
6317 goto unlock;
6318
6319 if (!changed)
6320 goto unlock;
6321
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006322 err = new_options(hdev, sk);
6323
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006324 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006325 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006326
Marcel Holtmann516018a2015-03-13 02:11:04 -07006327 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006328 hci_dev_set_flag(hdev, HCI_CONFIG);
6329 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006330
6331 queue_work(hdev->req_workqueue, &hdev->power_on);
6332 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006333 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006334 mgmt_index_added(hdev);
6335 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006336 }
6337
6338unlock:
6339 hci_dev_unlock(hdev);
6340 return err;
6341}
6342
Marcel Holtmann9713c172014-07-06 12:11:15 +02006343static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6344 void *data, u16 len)
6345{
6346 struct mgmt_cp_set_public_address *cp = data;
6347 bool changed;
6348 int err;
6349
6350 BT_DBG("%s", hdev->name);
6351
6352 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006353 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6354 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006355
6356 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006357 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6358 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006359
6360 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006361 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6362 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006363
6364 hci_dev_lock(hdev);
6365
6366 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6367 bacpy(&hdev->public_addr, &cp->bdaddr);
6368
6369 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6370 if (err < 0)
6371 goto unlock;
6372
6373 if (!changed)
6374 goto unlock;
6375
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006376 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006377 err = new_options(hdev, sk);
6378
6379 if (is_configured(hdev)) {
6380 mgmt_index_removed(hdev);
6381
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006382 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006383
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006384 hci_dev_set_flag(hdev, HCI_CONFIG);
6385 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006386
6387 queue_work(hdev->req_workqueue, &hdev->power_on);
6388 }
6389
6390unlock:
6391 hci_dev_unlock(hdev);
6392 return err;
6393}
6394
Marcel Holtmannbea41602015-03-14 22:43:17 -07006395static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6396 u8 data_len)
6397{
6398 eir[eir_len++] = sizeof(type) + data_len;
6399 eir[eir_len++] = type;
6400 memcpy(&eir[eir_len], data, data_len);
6401 eir_len += data_len;
6402
6403 return eir_len;
6404}
6405
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006406static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6407 void *data, u16 data_len)
6408{
6409 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6410 struct mgmt_rp_read_local_oob_ext_data *rp;
6411 size_t rp_len;
6412 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006413 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006414 int err;
6415
6416 BT_DBG("%s", hdev->name);
6417
6418 if (!hdev_is_powered(hdev))
6419 return mgmt_cmd_complete(sk, hdev->id,
6420 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6421 MGMT_STATUS_NOT_POWERED,
6422 &cp->type, sizeof(cp->type));
6423
6424 switch (cp->type) {
6425 case BIT(BDADDR_BREDR):
6426 status = mgmt_bredr_support(hdev);
6427 if (status)
6428 return mgmt_cmd_complete(sk, hdev->id,
6429 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6430 status, &cp->type,
6431 sizeof(cp->type));
6432 eir_len = 5;
6433 break;
6434 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6435 status = mgmt_le_support(hdev);
6436 if (status)
6437 return mgmt_cmd_complete(sk, hdev->id,
6438 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6439 status, &cp->type,
6440 sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006441 eir_len = 9 + 3 + 18 + 18 + 3;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006442 break;
6443 default:
6444 return mgmt_cmd_complete(sk, hdev->id,
6445 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6446 MGMT_STATUS_INVALID_PARAMS,
6447 &cp->type, sizeof(cp->type));
6448 }
6449
6450 hci_dev_lock(hdev);
6451
6452 rp_len = sizeof(*rp) + eir_len;
6453 rp = kmalloc(rp_len, GFP_ATOMIC);
6454 if (!rp) {
6455 hci_dev_unlock(hdev);
6456 return -ENOMEM;
6457 }
6458
6459 eir_len = 0;
6460 switch (cp->type) {
6461 case BIT(BDADDR_BREDR):
6462 eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
6463 hdev->dev_class, 3);
6464 break;
6465 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006466 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6467 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006468 hci_dev_unlock(hdev);
6469 err = mgmt_cmd_complete(sk, hdev->id,
Marcel Holtmann5082a592015-03-16 12:39:00 -07006470 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6471 MGMT_STATUS_FAILED,
6472 &cp->type, sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006473 goto done;
6474 }
6475
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006476 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
6477 memcpy(addr, &hdev->rpa, 6);
6478 addr[6] = 0x01;
6479 } else if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6480 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6481 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6482 bacmp(&hdev->static_addr, BDADDR_ANY))) {
6483 memcpy(addr, &hdev->static_addr, 6);
6484 addr[6] = 0x01;
6485 } else {
6486 memcpy(addr, &hdev->bdaddr, 6);
6487 addr[6] = 0x00;
6488 }
6489
6490 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6491 addr, sizeof(addr));
6492
6493 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6494 role = 0x02;
6495 else
6496 role = 0x01;
6497
6498 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6499 &role, sizeof(role));
6500
Marcel Holtmann5082a592015-03-16 12:39:00 -07006501 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6502 eir_len = eir_append_data(rp->eir, eir_len,
6503 EIR_LE_SC_CONFIRM,
6504 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006505
Marcel Holtmann5082a592015-03-16 12:39:00 -07006506 eir_len = eir_append_data(rp->eir, eir_len,
6507 EIR_LE_SC_RANDOM,
6508 rand, sizeof(rand));
6509 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006510
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006511 flags = get_adv_discov_flags(hdev);
6512
6513 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6514 flags |= LE_AD_NO_BREDR;
6515
6516 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6517 &flags, sizeof(flags));
6518 break;
6519 }
6520
6521 rp->type = cp->type;
6522 rp->eir_len = cpu_to_le16(eir_len);
6523
6524 hci_dev_unlock(hdev);
6525
Marcel Holtmann72000df2015-03-16 16:11:21 -07006526 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6527
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006528 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann5425f982015-03-16 16:05:44 -07006529 MGMT_STATUS_SUCCESS, rp, sizeof(*rp) + eir_len);
Marcel Holtmann72000df2015-03-16 16:11:21 -07006530 if (err < 0)
6531 goto done;
6532
6533 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6534 rp, sizeof(*rp) + eir_len,
6535 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006536
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006537done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006538 kfree(rp);
6539
6540 return err;
6541}
6542
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006543static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6544 void *data, u16 data_len)
6545{
6546 struct mgmt_rp_read_adv_features *rp;
6547 size_t rp_len;
6548 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006549 bool instance;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006550
6551 BT_DBG("%s", hdev->name);
6552
6553 hci_dev_lock(hdev);
6554
6555 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006556
6557 /* Currently only one instance is supported, so just add 1 to the
6558 * response length.
6559 */
6560 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6561 if (instance)
6562 rp_len++;
6563
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006564 rp = kmalloc(rp_len, GFP_ATOMIC);
6565 if (!rp) {
6566 hci_dev_unlock(hdev);
6567 return -ENOMEM;
6568 }
6569
6570 rp->supported_flags = cpu_to_le32(0);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006571 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6572 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006573 rp->max_instances = 1;
6574
6575 /* Currently only one instance is supported, so simply return the
6576 * current instance number.
6577 */
6578 if (instance) {
6579 rp->num_instances = 1;
6580 rp->instance[0] = 1;
6581 } else {
6582 rp->num_instances = 0;
6583 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006584
6585 hci_dev_unlock(hdev);
6586
6587 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6588 MGMT_STATUS_SUCCESS, rp, rp_len);
6589
6590 kfree(rp);
6591
6592 return err;
6593}
6594
Arman Uguray4117ed72015-03-23 15:57:14 -07006595static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006596 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006597{
Arman Uguray4117ed72015-03-23 15:57:14 -07006598 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006599 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006600 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006601 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006602 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6603 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006604
Arman Uguray807ec772015-03-25 18:53:42 -07006605 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006606 flags_managed = true;
6607 max_len -= 3;
6608 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006609
Arman Uguray5507e352015-03-25 18:53:44 -07006610 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6611 tx_power_managed = true;
6612 max_len -= 3;
6613 }
6614
Arman Uguray4117ed72015-03-23 15:57:14 -07006615 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006616 return false;
6617
Arman Uguray4117ed72015-03-23 15:57:14 -07006618 /* Make sure that the data is correctly formatted. */
6619 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6620 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006621
Arman Ugurayb44133f2015-03-25 18:53:41 -07006622 if (flags_managed && data[i + 1] == EIR_FLAGS)
6623 return false;
6624
Arman Uguray5507e352015-03-25 18:53:44 -07006625 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6626 return false;
6627
Arman Uguray24b4f382015-03-23 15:57:12 -07006628 /* If the current field length would exceed the total data
6629 * length, then it's invalid.
6630 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006631 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006632 return false;
6633 }
6634
6635 return true;
6636}
6637
Arman Uguray24b4f382015-03-23 15:57:12 -07006638static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6639 u16 opcode)
6640{
6641 struct mgmt_pending_cmd *cmd;
6642 struct mgmt_rp_add_advertising rp;
6643
6644 BT_DBG("status %d", status);
6645
6646 hci_dev_lock(hdev);
6647
6648 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6649
6650 if (status) {
6651 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6652 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6653 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6654 }
6655
6656 if (!cmd)
6657 goto unlock;
6658
6659 rp.instance = 0x01;
6660
6661 if (status)
6662 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6663 mgmt_status(status));
6664 else
6665 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6666 mgmt_status(status), &rp, sizeof(rp));
6667
6668 mgmt_pending_remove(cmd);
6669
6670unlock:
6671 hci_dev_unlock(hdev);
6672}
6673
Arman Uguray912098a2015-03-23 15:57:15 -07006674static void adv_timeout_expired(struct work_struct *work)
6675{
6676 struct hci_dev *hdev = container_of(work, struct hci_dev,
6677 adv_instance.timeout_exp.work);
6678
6679 hdev->adv_instance.timeout = 0;
6680
6681 hci_dev_lock(hdev);
6682 clear_adv_instance(hdev);
6683 hci_dev_unlock(hdev);
6684}
6685
Arman Uguray24b4f382015-03-23 15:57:12 -07006686static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6687 void *data, u16 data_len)
6688{
6689 struct mgmt_cp_add_advertising *cp = data;
6690 struct mgmt_rp_add_advertising rp;
6691 u32 flags;
6692 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006693 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006694 int err;
6695 struct mgmt_pending_cmd *cmd;
6696 struct hci_request req;
6697
6698 BT_DBG("%s", hdev->name);
6699
6700 status = mgmt_le_support(hdev);
6701 if (status)
6702 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6703 status);
6704
6705 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006706 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006707
Arman Uguraye7a685d2015-03-25 18:53:40 -07006708 /* The current implementation only supports adding one instance */
6709 if (cp->instance != 0x01)
Arman Uguray24b4f382015-03-23 15:57:12 -07006710 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6711 MGMT_STATUS_INVALID_PARAMS);
6712
6713 hci_dev_lock(hdev);
6714
Arman Uguray912098a2015-03-23 15:57:15 -07006715 if (timeout && !hdev_is_powered(hdev)) {
6716 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6717 MGMT_STATUS_REJECTED);
6718 goto unlock;
6719 }
6720
Arman Uguray24b4f382015-03-23 15:57:12 -07006721 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006722 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006723 pending_find(MGMT_OP_SET_LE, hdev)) {
6724 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6725 MGMT_STATUS_BUSY);
6726 goto unlock;
6727 }
6728
Arman Ugurayb44133f2015-03-25 18:53:41 -07006729 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006730 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006731 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006732 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6733 MGMT_STATUS_INVALID_PARAMS);
6734 goto unlock;
6735 }
6736
Arman Uguray912098a2015-03-23 15:57:15 -07006737 INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
6738
Arman Uguray24b4f382015-03-23 15:57:12 -07006739 hdev->adv_instance.flags = flags;
6740 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6741 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6742
6743 if (cp->adv_data_len)
6744 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6745
6746 if (cp->scan_rsp_len)
6747 memcpy(hdev->adv_instance.scan_rsp_data,
6748 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6749
Arman Uguray912098a2015-03-23 15:57:15 -07006750 if (hdev->adv_instance.timeout)
6751 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6752
6753 hdev->adv_instance.timeout = timeout;
6754
6755 if (timeout)
6756 queue_delayed_work(hdev->workqueue,
6757 &hdev->adv_instance.timeout_exp,
6758 msecs_to_jiffies(timeout * 1000));
6759
Arman Uguray24b4f382015-03-23 15:57:12 -07006760 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6761 advertising_added(sk, hdev, 1);
6762
6763 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6764 * we have no HCI communication to make. Simply return.
6765 */
6766 if (!hdev_is_powered(hdev) ||
6767 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6768 rp.instance = 0x01;
6769 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6770 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6771 goto unlock;
6772 }
6773
6774 /* We're good to go, update advertising data, parameters, and start
6775 * advertising.
6776 */
6777 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6778 data_len);
6779 if (!cmd) {
6780 err = -ENOMEM;
6781 goto unlock;
6782 }
6783
6784 hci_req_init(&req, hdev);
6785
6786 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07006787 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07006788 enable_advertising(&req);
6789
6790 err = hci_req_run(&req, add_advertising_complete);
6791 if (err < 0)
6792 mgmt_pending_remove(cmd);
6793
6794unlock:
6795 hci_dev_unlock(hdev);
6796
6797 return err;
6798}
6799
Arman Ugurayda9293352015-03-23 15:57:13 -07006800static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6801 u16 opcode)
6802{
6803 struct mgmt_pending_cmd *cmd;
6804 struct mgmt_rp_remove_advertising rp;
6805
6806 BT_DBG("status %d", status);
6807
6808 hci_dev_lock(hdev);
6809
6810 /* A failure status here only means that we failed to disable
6811 * advertising. Otherwise, the advertising instance has been removed,
6812 * so report success.
6813 */
6814 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6815 if (!cmd)
6816 goto unlock;
6817
6818 rp.instance = 1;
6819
6820 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6821 &rp, sizeof(rp));
6822 mgmt_pending_remove(cmd);
6823
6824unlock:
6825 hci_dev_unlock(hdev);
6826}
6827
6828static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6829 void *data, u16 data_len)
6830{
6831 struct mgmt_cp_remove_advertising *cp = data;
6832 struct mgmt_rp_remove_advertising rp;
6833 int err;
6834 struct mgmt_pending_cmd *cmd;
6835 struct hci_request req;
6836
6837 BT_DBG("%s", hdev->name);
6838
6839 /* The current implementation only allows modifying instance no 1. A
6840 * value of 0 indicates that all instances should be cleared.
6841 */
6842 if (cp->instance > 1)
6843 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6844 MGMT_STATUS_INVALID_PARAMS);
6845
6846 hci_dev_lock(hdev);
6847
6848 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
6849 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
6850 pending_find(MGMT_OP_SET_LE, hdev)) {
6851 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6852 MGMT_STATUS_BUSY);
6853 goto unlock;
6854 }
6855
6856 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
6857 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6858 MGMT_STATUS_INVALID_PARAMS);
6859 goto unlock;
6860 }
6861
Arman Uguray912098a2015-03-23 15:57:15 -07006862 if (hdev->adv_instance.timeout)
6863 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6864
Arman Ugurayda9293352015-03-23 15:57:13 -07006865 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6866
6867 advertising_removed(sk, hdev, 1);
6868
6869 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6870
6871 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6872 * we have no HCI communication to make. Simply return.
6873 */
6874 if (!hdev_is_powered(hdev) ||
6875 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6876 rp.instance = 1;
6877 err = mgmt_cmd_complete(sk, hdev->id,
6878 MGMT_OP_REMOVE_ADVERTISING,
6879 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6880 goto unlock;
6881 }
6882
6883 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
6884 data_len);
6885 if (!cmd) {
6886 err = -ENOMEM;
6887 goto unlock;
6888 }
6889
6890 hci_req_init(&req, hdev);
6891 disable_advertising(&req);
6892
6893 err = hci_req_run(&req, remove_advertising_complete);
6894 if (err < 0)
6895 mgmt_pending_remove(cmd);
6896
6897unlock:
6898 hci_dev_unlock(hdev);
6899
6900 return err;
6901}
6902
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006903static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006904 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006905 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006906 HCI_MGMT_NO_HDEV |
6907 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006908 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006909 HCI_MGMT_NO_HDEV |
6910 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006911 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006912 HCI_MGMT_NO_HDEV |
6913 HCI_MGMT_UNTRUSTED },
6914 { read_controller_info, MGMT_READ_INFO_SIZE,
6915 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006916 { set_powered, MGMT_SETTING_SIZE },
6917 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
6918 { set_connectable, MGMT_SETTING_SIZE },
6919 { set_fast_connectable, MGMT_SETTING_SIZE },
6920 { set_bondable, MGMT_SETTING_SIZE },
6921 { set_link_security, MGMT_SETTING_SIZE },
6922 { set_ssp, MGMT_SETTING_SIZE },
6923 { set_hs, MGMT_SETTING_SIZE },
6924 { set_le, MGMT_SETTING_SIZE },
6925 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
6926 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
6927 { add_uuid, MGMT_ADD_UUID_SIZE },
6928 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006929 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6930 HCI_MGMT_VAR_LEN },
6931 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6932 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006933 { disconnect, MGMT_DISCONNECT_SIZE },
6934 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
6935 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
6936 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6937 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
6938 { pair_device, MGMT_PAIR_DEVICE_SIZE },
6939 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6940 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
6941 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
6942 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6943 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
6944 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006945 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6946 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6947 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006948 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6949 { start_discovery, MGMT_START_DISCOVERY_SIZE },
6950 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
6951 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
6952 { block_device, MGMT_BLOCK_DEVICE_SIZE },
6953 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
6954 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
6955 { set_advertising, MGMT_SETTING_SIZE },
6956 { set_bredr, MGMT_SETTING_SIZE },
6957 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
6958 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
6959 { set_secure_conn, MGMT_SETTING_SIZE },
6960 { set_debug_keys, MGMT_SETTING_SIZE },
6961 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006962 { load_irks, MGMT_LOAD_IRKS_SIZE,
6963 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006964 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
6965 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
6966 { add_device, MGMT_ADD_DEVICE_SIZE },
6967 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006968 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6969 HCI_MGMT_VAR_LEN },
6970 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006971 HCI_MGMT_NO_HDEV |
6972 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006973 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006974 HCI_MGMT_UNCONFIGURED |
6975 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006976 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6977 HCI_MGMT_UNCONFIGURED },
6978 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6979 HCI_MGMT_UNCONFIGURED },
6980 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6981 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006982 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07006983 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006984 HCI_MGMT_NO_HDEV |
6985 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006986 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07006987 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
6988 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07006989 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006990};
6991
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006992void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006993{
Marcel Holtmannced85542015-03-14 19:27:56 -07006994 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006995
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006996 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6997 return;
6998
Marcel Holtmannf9207332015-03-14 19:27:55 -07006999 switch (hdev->dev_type) {
7000 case HCI_BREDR:
7001 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7002 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7003 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007004 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007005 } else {
7006 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7007 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007008 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007009 }
7010 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007011 case HCI_AMP:
7012 ev.type = 0x02;
7013 break;
7014 default:
7015 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007016 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007017
7018 ev.bus = hdev->bus;
7019
7020 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7021 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007022}
7023
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007024void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007025{
Marcel Holtmannced85542015-03-14 19:27:56 -07007026 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007027 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007028
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007029 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7030 return;
7031
Marcel Holtmannf9207332015-03-14 19:27:55 -07007032 switch (hdev->dev_type) {
7033 case HCI_BREDR:
7034 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007035
Marcel Holtmannf9207332015-03-14 19:27:55 -07007036 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7037 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7038 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007039 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007040 } else {
7041 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7042 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007043 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007044 }
7045 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007046 case HCI_AMP:
7047 ev.type = 0x02;
7048 break;
7049 default:
7050 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007051 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007052
7053 ev.bus = hdev->bus;
7054
7055 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7056 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007057}
7058
Andre Guedes6046dc32014-02-26 20:21:51 -03007059/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007060static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007061{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007062 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007063 struct hci_conn_params *p;
7064
7065 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007066 /* Needed for AUTO_OFF case where might not "really"
7067 * have been powered off.
7068 */
7069 list_del_init(&p->action);
7070
7071 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007072 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007073 case HCI_AUTO_CONN_ALWAYS:
7074 list_add(&p->action, &hdev->pend_le_conns);
7075 break;
7076 case HCI_AUTO_CONN_REPORT:
7077 list_add(&p->action, &hdev->pend_le_reports);
7078 break;
7079 default:
7080 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007081 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007082 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007083
Johan Hedberg2cf22212014-12-19 22:26:00 +02007084 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007085}
7086
Marcel Holtmann1904a852015-01-11 13:50:44 -08007087static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007088{
7089 struct cmd_lookup match = { NULL, hdev };
7090
7091 BT_DBG("status 0x%02x", status);
7092
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007093 if (!status) {
7094 /* Register the available SMP channels (BR/EDR and LE) only
7095 * when successfully powering on the controller. This late
7096 * registration is required so that LE SMP can clearly
7097 * decide if the public address or static address is used.
7098 */
7099 smp_register(hdev);
7100 }
7101
Johan Hedberg229ab392013-03-15 17:06:53 -05007102 hci_dev_lock(hdev);
7103
7104 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7105
7106 new_settings(hdev, match.sk);
7107
7108 hci_dev_unlock(hdev);
7109
7110 if (match.sk)
7111 sock_put(match.sk);
7112}
7113
Johan Hedberg70da6242013-03-15 17:06:51 -05007114static int powered_update_hci(struct hci_dev *hdev)
7115{
Johan Hedberg890ea892013-03-15 17:06:52 -05007116 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007117 u8 link_sec;
7118
Johan Hedberg890ea892013-03-15 17:06:52 -05007119 hci_req_init(&req, hdev);
7120
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007121 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007122 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007123 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007124
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007125 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007126
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007127 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7128 u8 support = 0x01;
7129
7130 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7131 sizeof(support), &support);
7132 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007133 }
7134
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007135 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007136 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007137 struct hci_cp_write_le_host_supported cp;
7138
Marcel Holtmann32226e42014-07-24 20:04:16 +02007139 cp.le = 0x01;
7140 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007141
7142 /* Check first if we already have the right
7143 * host state (host features set)
7144 */
7145 if (cp.le != lmp_host_le_capable(hdev) ||
7146 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007147 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7148 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007149 }
7150
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007151 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007152 /* Make sure the controller has a good default for
7153 * advertising data. This also applies to the case
7154 * where BR/EDR was toggled during the AUTO_OFF phase.
7155 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007156 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007157 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007158 update_scan_rsp_data(&req);
7159 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007160
Arman Uguray24b4f382015-03-23 15:57:12 -07007161 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7162 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007163 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007164
7165 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007166 }
7167
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007168 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007169 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007170 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7171 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007172
7173 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007174 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007175 write_fast_connectable(&req, true);
7176 else
7177 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007178 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007179 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007180 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007181 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007182 }
7183
Johan Hedberg229ab392013-03-15 17:06:53 -05007184 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007185}
7186
Johan Hedberg744cf192011-11-08 20:40:14 +02007187int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007188{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007189 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007190 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007191 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007192
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007193 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007194 return 0;
7195
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007196 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007197 if (powered_update_hci(hdev) == 0)
7198 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007199
Johan Hedberg229ab392013-03-15 17:06:53 -05007200 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7201 &match);
7202 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007203 }
7204
Johan Hedberg229ab392013-03-15 17:06:53 -05007205 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007206
7207 /* If the power off is because of hdev unregistration let
7208 * use the appropriate INVALID_INDEX status. Otherwise use
7209 * NOT_POWERED. We cover both scenarios here since later in
7210 * mgmt_index_removed() any hci_conn callbacks will have already
7211 * been triggered, potentially causing misleading DISCONNECTED
7212 * status responses.
7213 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007214 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007215 status = MGMT_STATUS_INVALID_INDEX;
7216 else
7217 status = MGMT_STATUS_NOT_POWERED;
7218
7219 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007220
7221 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007222 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7223 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007224
7225new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007226 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007227
7228 if (match.sk)
7229 sock_put(match.sk);
7230
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007231 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007232}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007233
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007234void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007235{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007236 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007237 u8 status;
7238
Johan Hedberg333ae952015-03-17 13:48:47 +02007239 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007240 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007241 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007242
7243 if (err == -ERFKILL)
7244 status = MGMT_STATUS_RFKILLED;
7245 else
7246 status = MGMT_STATUS_FAILED;
7247
Johan Hedberga69e8372015-03-06 21:08:53 +02007248 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007249
7250 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007251}
7252
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007253void mgmt_discoverable_timeout(struct hci_dev *hdev)
7254{
7255 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007256
7257 hci_dev_lock(hdev);
7258
7259 /* When discoverable timeout triggers, then just make sure
7260 * the limited discoverable flag is cleared. Even in the case
7261 * of a timeout triggered from general discoverable, it is
7262 * safe to unconditionally clear the flag.
7263 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007264 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7265 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007266
7267 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007268 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007269 u8 scan = SCAN_PAGE;
7270 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7271 sizeof(scan), &scan);
7272 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007273 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007274
7275 /* Advertising instances don't use the global discoverable setting, so
7276 * only update AD if advertising was enabled using Set Advertising.
7277 */
7278 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7279 update_adv_data(&req);
7280
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007281 hci_req_run(&req, NULL);
7282
7283 hdev->discov_timeout = 0;
7284
Johan Hedberg9a43e252013-10-20 19:00:07 +03007285 new_settings(hdev, NULL);
7286
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007287 hci_dev_unlock(hdev);
7288}
7289
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007290void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7291 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007292{
Johan Hedberg86742e12011-11-07 23:13:38 +02007293 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007294
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007295 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007296
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007297 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007298 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007299 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007300 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007301 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007302 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007303
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007304 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007305}
Johan Hedbergf7520542011-01-20 12:34:39 +02007306
Johan Hedbergd7b25452014-05-23 13:19:53 +03007307static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7308{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007309 switch (ltk->type) {
7310 case SMP_LTK:
7311 case SMP_LTK_SLAVE:
7312 if (ltk->authenticated)
7313 return MGMT_LTK_AUTHENTICATED;
7314 return MGMT_LTK_UNAUTHENTICATED;
7315 case SMP_LTK_P256:
7316 if (ltk->authenticated)
7317 return MGMT_LTK_P256_AUTH;
7318 return MGMT_LTK_P256_UNAUTH;
7319 case SMP_LTK_P256_DEBUG:
7320 return MGMT_LTK_P256_DEBUG;
7321 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007322
7323 return MGMT_LTK_UNAUTHENTICATED;
7324}
7325
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007326void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007327{
7328 struct mgmt_ev_new_long_term_key ev;
7329
7330 memset(&ev, 0, sizeof(ev));
7331
Marcel Holtmann5192d302014-02-19 17:11:58 -08007332 /* Devices using resolvable or non-resolvable random addresses
7333 * without providing an indentity resolving key don't require
7334 * to store long term keys. Their addresses will change the
7335 * next time around.
7336 *
7337 * Only when a remote device provides an identity address
7338 * make sure the long term key is stored. If the remote
7339 * identity is known, the long term keys are internally
7340 * mapped to the identity address. So allow static random
7341 * and public addresses here.
7342 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007343 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7344 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7345 ev.store_hint = 0x00;
7346 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007347 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007348
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007349 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007350 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007351 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007352 ev.key.enc_size = key->enc_size;
7353 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007354 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007355
Johan Hedberg2ceba532014-06-16 19:25:16 +03007356 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007357 ev.key.master = 1;
7358
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007359 memcpy(ev.key.val, key->val, sizeof(key->val));
7360
Marcel Holtmann083368f2013-10-15 14:26:29 -07007361 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007362}
7363
Johan Hedberg95fbac82014-02-19 15:18:31 +02007364void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7365{
7366 struct mgmt_ev_new_irk ev;
7367
7368 memset(&ev, 0, sizeof(ev));
7369
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007370 /* For identity resolving keys from devices that are already
7371 * using a public address or static random address, do not
7372 * ask for storing this key. The identity resolving key really
7373 * is only mandatory for devices using resovlable random
7374 * addresses.
7375 *
7376 * Storing all identity resolving keys has the downside that
7377 * they will be also loaded on next boot of they system. More
7378 * identity resolving keys, means more time during scanning is
7379 * needed to actually resolve these addresses.
7380 */
7381 if (bacmp(&irk->rpa, BDADDR_ANY))
7382 ev.store_hint = 0x01;
7383 else
7384 ev.store_hint = 0x00;
7385
Johan Hedberg95fbac82014-02-19 15:18:31 +02007386 bacpy(&ev.rpa, &irk->rpa);
7387 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7388 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7389 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7390
7391 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7392}
7393
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007394void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7395 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007396{
7397 struct mgmt_ev_new_csrk ev;
7398
7399 memset(&ev, 0, sizeof(ev));
7400
7401 /* Devices using resolvable or non-resolvable random addresses
7402 * without providing an indentity resolving key don't require
7403 * to store signature resolving keys. Their addresses will change
7404 * the next time around.
7405 *
7406 * Only when a remote device provides an identity address
7407 * make sure the signature resolving key is stored. So allow
7408 * static random and public addresses here.
7409 */
7410 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7411 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7412 ev.store_hint = 0x00;
7413 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007414 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007415
7416 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7417 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007418 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007419 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7420
7421 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7422}
7423
Andre Guedesffb5a8272014-07-01 18:10:11 -03007424void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007425 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7426 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007427{
7428 struct mgmt_ev_new_conn_param ev;
7429
Johan Hedbergc103aea2014-07-02 17:37:34 +03007430 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7431 return;
7432
Andre Guedesffb5a8272014-07-01 18:10:11 -03007433 memset(&ev, 0, sizeof(ev));
7434 bacpy(&ev.addr.bdaddr, bdaddr);
7435 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007436 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007437 ev.min_interval = cpu_to_le16(min_interval);
7438 ev.max_interval = cpu_to_le16(max_interval);
7439 ev.latency = cpu_to_le16(latency);
7440 ev.timeout = cpu_to_le16(timeout);
7441
7442 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7443}
7444
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007445void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7446 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007447{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007448 char buf[512];
7449 struct mgmt_ev_device_connected *ev = (void *) buf;
7450 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007451
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007452 bacpy(&ev->addr.bdaddr, &conn->dst);
7453 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007454
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007455 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007456
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007457 /* We must ensure that the EIR Data fields are ordered and
7458 * unique. Keep it simple for now and avoid the problem by not
7459 * adding any BR/EDR data to the LE adv.
7460 */
7461 if (conn->le_adv_data_len > 0) {
7462 memcpy(&ev->eir[eir_len],
7463 conn->le_adv_data, conn->le_adv_data_len);
7464 eir_len = conn->le_adv_data_len;
7465 } else {
7466 if (name_len > 0)
7467 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7468 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007469
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007470 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007471 eir_len = eir_append_data(ev->eir, eir_len,
7472 EIR_CLASS_OF_DEV,
7473 conn->dev_class, 3);
7474 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007475
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007476 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007477
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007478 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7479 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007480}
7481
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007482static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007483{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007484 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007485
Johan Hedbergf5818c22014-12-05 13:36:02 +02007486 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007487
7488 *sk = cmd->sk;
7489 sock_hold(*sk);
7490
Johan Hedberga664b5b2011-02-19 12:06:02 -03007491 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007492}
7493
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007494static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007495{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007496 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007497 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007498
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007499 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7500
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007501 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007502 mgmt_pending_remove(cmd);
7503}
7504
Johan Hedberg84c61d92014-08-01 11:13:30 +03007505bool mgmt_powering_down(struct hci_dev *hdev)
7506{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007507 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007508 struct mgmt_mode *cp;
7509
Johan Hedberg333ae952015-03-17 13:48:47 +02007510 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007511 if (!cmd)
7512 return false;
7513
7514 cp = cmd->param;
7515 if (!cp->val)
7516 return true;
7517
7518 return false;
7519}
7520
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007521void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007522 u8 link_type, u8 addr_type, u8 reason,
7523 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007524{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007525 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007526 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007527
Johan Hedberg84c61d92014-08-01 11:13:30 +03007528 /* The connection is still in hci_conn_hash so test for 1
7529 * instead of 0 to know if this is the last one.
7530 */
7531 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7532 cancel_delayed_work(&hdev->power_off);
7533 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007534 }
7535
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007536 if (!mgmt_connected)
7537 return;
7538
Andre Guedes57eb7762013-10-30 19:01:41 -03007539 if (link_type != ACL_LINK && link_type != LE_LINK)
7540 return;
7541
Johan Hedberg744cf192011-11-08 20:40:14 +02007542 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007543
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007544 bacpy(&ev.addr.bdaddr, bdaddr);
7545 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7546 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007547
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007548 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007549
7550 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007551 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007552
Johan Hedberg124f6e32012-02-09 13:50:12 +02007553 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007554 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007555}
7556
Marcel Holtmann78929242013-10-06 23:55:47 -07007557void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7558 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007559{
Andre Guedes3655bba2013-10-30 19:01:40 -03007560 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7561 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007562 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007563
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007564 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7565 hdev);
7566
Johan Hedberg333ae952015-03-17 13:48:47 +02007567 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007568 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007569 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007570
Andre Guedes3655bba2013-10-30 19:01:40 -03007571 cp = cmd->param;
7572
7573 if (bacmp(bdaddr, &cp->addr.bdaddr))
7574 return;
7575
7576 if (cp->addr.type != bdaddr_type)
7577 return;
7578
Johan Hedbergf5818c22014-12-05 13:36:02 +02007579 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007580 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007581}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007582
Marcel Holtmann445608d2013-10-06 23:55:48 -07007583void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7584 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007585{
7586 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007587
Johan Hedberg84c61d92014-08-01 11:13:30 +03007588 /* The connection is still in hci_conn_hash so test for 1
7589 * instead of 0 to know if this is the last one.
7590 */
7591 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7592 cancel_delayed_work(&hdev->power_off);
7593 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007594 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007595
Johan Hedberg4c659c32011-11-07 23:13:39 +02007596 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007597 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007598 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007599
Marcel Holtmann445608d2013-10-06 23:55:48 -07007600 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007601}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007602
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007603void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007604{
7605 struct mgmt_ev_pin_code_request ev;
7606
Johan Hedbergd8457692012-02-17 14:24:57 +02007607 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007608 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007609 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007610
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007611 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007612}
7613
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007614void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7615 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007616{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007617 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007618
Johan Hedberg333ae952015-03-17 13:48:47 +02007619 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007620 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007621 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007622
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007623 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007624 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007625}
7626
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007627void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7628 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007629{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007630 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007631
Johan Hedberg333ae952015-03-17 13:48:47 +02007632 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007633 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007634 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007635
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007636 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007637 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007638}
Johan Hedberga5c29682011-02-19 12:05:57 -03007639
Johan Hedberg744cf192011-11-08 20:40:14 +02007640int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007641 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007642 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007643{
7644 struct mgmt_ev_user_confirm_request ev;
7645
Johan Hedberg744cf192011-11-08 20:40:14 +02007646 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007647
Johan Hedberg272d90d2012-02-09 15:26:12 +02007648 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007649 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007650 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007651 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007652
Johan Hedberg744cf192011-11-08 20:40:14 +02007653 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007654 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007655}
7656
Johan Hedberg272d90d2012-02-09 15:26:12 +02007657int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007658 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007659{
7660 struct mgmt_ev_user_passkey_request ev;
7661
7662 BT_DBG("%s", hdev->name);
7663
Johan Hedberg272d90d2012-02-09 15:26:12 +02007664 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007665 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007666
7667 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007668 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007669}
7670
Brian Gix0df4c182011-11-16 13:53:13 -08007671static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007672 u8 link_type, u8 addr_type, u8 status,
7673 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007674{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007675 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007676
Johan Hedberg333ae952015-03-17 13:48:47 +02007677 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007678 if (!cmd)
7679 return -ENOENT;
7680
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007681 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007682 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007683
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007684 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007685}
7686
Johan Hedberg744cf192011-11-08 20:40:14 +02007687int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007688 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007689{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007690 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007691 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007692}
7693
Johan Hedberg272d90d2012-02-09 15:26:12 +02007694int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007695 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007696{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007697 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007698 status,
7699 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007700}
Johan Hedberg2a611692011-02-19 12:06:00 -03007701
Brian Gix604086b2011-11-23 08:28:33 -08007702int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007703 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007704{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007705 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007706 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007707}
7708
Johan Hedberg272d90d2012-02-09 15:26:12 +02007709int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007710 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007711{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007712 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007713 status,
7714 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007715}
7716
Johan Hedberg92a25252012-09-06 18:39:26 +03007717int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7718 u8 link_type, u8 addr_type, u32 passkey,
7719 u8 entered)
7720{
7721 struct mgmt_ev_passkey_notify ev;
7722
7723 BT_DBG("%s", hdev->name);
7724
7725 bacpy(&ev.addr.bdaddr, bdaddr);
7726 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7727 ev.passkey = __cpu_to_le32(passkey);
7728 ev.entered = entered;
7729
7730 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7731}
7732
Johan Hedberge1e930f2014-09-08 17:09:49 -07007733void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007734{
7735 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007736 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007737 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007738
Johan Hedberge1e930f2014-09-08 17:09:49 -07007739 bacpy(&ev.addr.bdaddr, &conn->dst);
7740 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7741 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007742
Johan Hedberge1e930f2014-09-08 17:09:49 -07007743 cmd = find_pairing(conn);
7744
7745 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7746 cmd ? cmd->sk : NULL);
7747
Johan Hedberga511b352014-12-11 21:45:45 +02007748 if (cmd) {
7749 cmd->cmd_complete(cmd, status);
7750 mgmt_pending_remove(cmd);
7751 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007752}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007753
Marcel Holtmann464996a2013-10-15 14:26:24 -07007754void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007755{
7756 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007757 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007758
7759 if (status) {
7760 u8 mgmt_err = mgmt_status(status);
7761 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007762 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007763 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007764 }
7765
Marcel Holtmann464996a2013-10-15 14:26:24 -07007766 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007767 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007768 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007769 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007770
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007771 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007772 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007773
Johan Hedberg47990ea2012-02-22 11:58:37 +02007774 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007775 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007776
7777 if (match.sk)
7778 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007779}
7780
Johan Hedberg890ea892013-03-15 17:06:52 -05007781static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007782{
Johan Hedberg890ea892013-03-15 17:06:52 -05007783 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007784 struct hci_cp_write_eir cp;
7785
Johan Hedberg976eb202012-10-24 21:12:01 +03007786 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007787 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007788
Johan Hedbergc80da272012-02-22 15:38:48 +02007789 memset(hdev->eir, 0, sizeof(hdev->eir));
7790
Johan Hedbergcacaf522012-02-21 00:52:42 +02007791 memset(&cp, 0, sizeof(cp));
7792
Johan Hedberg890ea892013-03-15 17:06:52 -05007793 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007794}
7795
Marcel Holtmann3e248562013-10-15 14:26:25 -07007796void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007797{
7798 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007799 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007800 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007801
7802 if (status) {
7803 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007804
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007805 if (enable && hci_dev_test_and_clear_flag(hdev,
7806 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007807 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007808 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007809 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007810
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007811 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7812 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007813 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007814 }
7815
7816 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007817 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007818 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007819 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007820 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007821 changed = hci_dev_test_and_clear_flag(hdev,
7822 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007823 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007824 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007825 }
7826
7827 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7828
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007829 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007830 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007831
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007832 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007833 sock_put(match.sk);
7834
Johan Hedberg890ea892013-03-15 17:06:52 -05007835 hci_req_init(&req, hdev);
7836
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007837 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7838 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007839 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7840 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007841 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007842 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007843 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007844 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007845
7846 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007847}
7848
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007849static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007850{
7851 struct cmd_lookup *match = data;
7852
Johan Hedberg90e70452012-02-23 23:09:40 +02007853 if (match->sk == NULL) {
7854 match->sk = cmd->sk;
7855 sock_hold(match->sk);
7856 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007857}
7858
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007859void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7860 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007861{
Johan Hedberg90e70452012-02-23 23:09:40 +02007862 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007863
Johan Hedberg92da6092013-03-15 17:06:55 -05007864 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7865 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7866 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007867
7868 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007869 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7870 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007871
7872 if (match.sk)
7873 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007874}
7875
Marcel Holtmann7667da32013-10-15 14:26:27 -07007876void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007877{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007878 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007879 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007880
Johan Hedberg13928972013-03-15 17:07:00 -05007881 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007882 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007883
7884 memset(&ev, 0, sizeof(ev));
7885 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007886 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007887
Johan Hedberg333ae952015-03-17 13:48:47 +02007888 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007889 if (!cmd) {
7890 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007891
Johan Hedberg13928972013-03-15 17:07:00 -05007892 /* If this is a HCI command related to powering on the
7893 * HCI dev don't send any mgmt signals.
7894 */
Johan Hedberg333ae952015-03-17 13:48:47 +02007895 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007896 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007897 }
7898
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007899 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7900 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007901}
Szymon Jancc35938b2011-03-22 13:12:21 +01007902
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007903void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007904 u8 *rand192, u8 *hash256, u8 *rand256,
7905 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007906{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007907 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007908
Johan Hedberg744cf192011-11-08 20:40:14 +02007909 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007910
Johan Hedberg333ae952015-03-17 13:48:47 +02007911 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007912 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007913 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007914
7915 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007916 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7917 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007918 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007919 struct mgmt_rp_read_local_oob_data rp;
7920 size_t rp_size = sizeof(rp);
7921
7922 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7923 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7924
Johan Hedberg710f11c2014-05-26 11:21:22 +03007925 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007926 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007927 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007928 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007929 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007930 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007931
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007932 mgmt_cmd_complete(cmd->sk, hdev->id,
7933 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7934 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007935 }
7936
7937 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007938}
Johan Hedberge17acd42011-03-30 23:57:16 +03007939
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007940static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7941{
7942 int i;
7943
7944 for (i = 0; i < uuid_count; i++) {
7945 if (!memcmp(uuid, uuids[i], 16))
7946 return true;
7947 }
7948
7949 return false;
7950}
7951
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007952static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7953{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007954 u16 parsed = 0;
7955
7956 while (parsed < eir_len) {
7957 u8 field_len = eir[0];
7958 u8 uuid[16];
7959 int i;
7960
7961 if (field_len == 0)
7962 break;
7963
7964 if (eir_len - parsed < field_len + 1)
7965 break;
7966
7967 switch (eir[1]) {
7968 case EIR_UUID16_ALL:
7969 case EIR_UUID16_SOME:
7970 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007971 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007972 uuid[13] = eir[i + 3];
7973 uuid[12] = eir[i + 2];
7974 if (has_uuid(uuid, uuid_count, uuids))
7975 return true;
7976 }
7977 break;
7978 case EIR_UUID32_ALL:
7979 case EIR_UUID32_SOME:
7980 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007981 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007982 uuid[15] = eir[i + 5];
7983 uuid[14] = eir[i + 4];
7984 uuid[13] = eir[i + 3];
7985 uuid[12] = eir[i + 2];
7986 if (has_uuid(uuid, uuid_count, uuids))
7987 return true;
7988 }
7989 break;
7990 case EIR_UUID128_ALL:
7991 case EIR_UUID128_SOME:
7992 for (i = 0; i + 17 <= field_len; i += 16) {
7993 memcpy(uuid, eir + i + 2, 16);
7994 if (has_uuid(uuid, uuid_count, uuids))
7995 return true;
7996 }
7997 break;
7998 }
7999
8000 parsed += field_len + 1;
8001 eir += field_len + 1;
8002 }
8003
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008004 return false;
8005}
8006
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008007static void restart_le_scan(struct hci_dev *hdev)
8008{
8009 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008010 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008011 return;
8012
8013 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8014 hdev->discovery.scan_start +
8015 hdev->discovery.scan_duration))
8016 return;
8017
8018 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8019 DISCOV_LE_RESTART_DELAY);
8020}
8021
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008022static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8023 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8024{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008025 /* If a RSSI threshold has been specified, and
8026 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8027 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8028 * is set, let it through for further processing, as we might need to
8029 * restart the scan.
8030 *
8031 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8032 * the results are also dropped.
8033 */
8034 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8035 (rssi == HCI_RSSI_INVALID ||
8036 (rssi < hdev->discovery.rssi &&
8037 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8038 return false;
8039
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008040 if (hdev->discovery.uuid_count != 0) {
8041 /* If a list of UUIDs is provided in filter, results with no
8042 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008043 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008044 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8045 hdev->discovery.uuids) &&
8046 !eir_has_uuids(scan_rsp, scan_rsp_len,
8047 hdev->discovery.uuid_count,
8048 hdev->discovery.uuids))
8049 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008050 }
8051
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008052 /* If duplicate filtering does not report RSSI changes, then restart
8053 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008054 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008055 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8056 restart_le_scan(hdev);
8057
8058 /* Validate RSSI value against the RSSI threshold once more. */
8059 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8060 rssi < hdev->discovery.rssi)
8061 return false;
8062 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008063
8064 return true;
8065}
8066
Marcel Holtmann901801b2013-10-06 23:55:51 -07008067void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008068 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8069 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008070{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008071 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008072 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008073 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008074
Johan Hedberg75ce2082014-07-02 22:42:01 +03008075 /* Don't send events for a non-kernel initiated discovery. With
8076 * LE one exception is if we have pend_le_reports > 0 in which
8077 * case we're doing passive scanning and want these events.
8078 */
8079 if (!hci_discovery_active(hdev)) {
8080 if (link_type == ACL_LINK)
8081 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008082 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008083 return;
8084 }
Andre Guedes12602d02013-04-30 15:29:40 -03008085
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008086 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008087 /* We are using service discovery */
8088 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8089 scan_rsp_len))
8090 return;
8091 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008092
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008093 /* Make sure that the buffer is big enough. The 5 extra bytes
8094 * are for the potential CoD field.
8095 */
8096 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008097 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008098
Johan Hedberg1dc06092012-01-15 21:01:23 +02008099 memset(buf, 0, sizeof(buf));
8100
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008101 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8102 * RSSI value was reported as 0 when not available. This behavior
8103 * is kept when using device discovery. This is required for full
8104 * backwards compatibility with the API.
8105 *
8106 * However when using service discovery, the value 127 will be
8107 * returned when the RSSI is not available.
8108 */
Szymon Janc91200e92015-01-22 16:57:05 +01008109 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8110 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008111 rssi = 0;
8112
Johan Hedberg841c5642014-07-07 12:45:54 +03008113 bacpy(&ev->addr.bdaddr, bdaddr);
8114 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008115 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008116 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008117
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008118 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008119 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008120 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008121
Johan Hedberg1dc06092012-01-15 21:01:23 +02008122 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8123 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008124 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008125
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008126 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008127 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008128 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008129
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008130 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8131 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008132
Marcel Holtmann901801b2013-10-06 23:55:51 -07008133 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008134}
Johan Hedberga88a9652011-03-30 13:18:12 +03008135
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008136void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8137 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008138{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008139 struct mgmt_ev_device_found *ev;
8140 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8141 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008142
Johan Hedbergb644ba32012-01-17 21:48:47 +02008143 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008144
Johan Hedbergb644ba32012-01-17 21:48:47 +02008145 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008146
Johan Hedbergb644ba32012-01-17 21:48:47 +02008147 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008148 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008149 ev->rssi = rssi;
8150
8151 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008152 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008153
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008154 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008155
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008156 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008157}
Johan Hedberg314b2382011-04-27 10:29:57 -04008158
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008159void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008160{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008161 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008162
Andre Guedes343fb142011-11-22 17:14:19 -03008163 BT_DBG("%s discovering %u", hdev->name, discovering);
8164
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008165 memset(&ev, 0, sizeof(ev));
8166 ev.type = hdev->discovery.type;
8167 ev.discovering = discovering;
8168
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008169 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008170}
Antti Julku5e762442011-08-25 16:48:02 +03008171
Marcel Holtmann1904a852015-01-11 13:50:44 -08008172static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008173{
8174 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008175}
8176
8177void mgmt_reenable_advertising(struct hci_dev *hdev)
8178{
8179 struct hci_request req;
8180
Arman Uguray24b4f382015-03-23 15:57:12 -07008181 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8182 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008183 return;
8184
8185 hci_req_init(&req, hdev);
8186 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008187 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008188}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008189
8190static struct hci_mgmt_chan chan = {
8191 .channel = HCI_CHANNEL_CONTROL,
8192 .handler_count = ARRAY_SIZE(mgmt_handlers),
8193 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008194 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008195};
8196
8197int mgmt_init(void)
8198{
8199 return hci_mgmt_chan_register(&chan);
8200}
8201
8202void mgmt_exit(void)
8203{
8204 hci_mgmt_chan_unregister(&chan);
8205}