blob: 2d84fc16e108484f43fe9183661c388f71c91d40 [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 Hedbergf7b64e692010-12-13 21:07:06 +0200637
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200638 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
639 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200640 settings |= MGMT_SETTING_CONFIGURATION;
641
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200642 return settings;
643}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200644
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200645static u32 get_current_settings(struct hci_dev *hdev)
646{
647 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200648
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200649 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100650 settings |= MGMT_SETTING_POWERED;
651
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700652 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200653 settings |= MGMT_SETTING_CONNECTABLE;
654
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700655 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500656 settings |= MGMT_SETTING_FAST_CONNECTABLE;
657
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700658 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200659 settings |= MGMT_SETTING_DISCOVERABLE;
660
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700661 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300662 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200663
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700664 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200665 settings |= MGMT_SETTING_BREDR;
666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700667 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200668 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700670 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200672
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700673 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200674 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200675
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700676 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200677 settings |= MGMT_SETTING_HS;
678
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700679 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300680 settings |= MGMT_SETTING_ADVERTISING;
681
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700682 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800683 settings |= MGMT_SETTING_SECURE_CONN;
684
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700685 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800686 settings |= MGMT_SETTING_DEBUG_KEYS;
687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700688 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200689 settings |= MGMT_SETTING_PRIVACY;
690
Marcel Holtmann93690c22015-03-06 10:11:21 -0800691 /* The current setting for static address has two purposes. The
692 * first is to indicate if the static address will be used and
693 * the second is to indicate if it is actually set.
694 *
695 * This means if the static address is not configured, this flag
Marcel Holtmann08dc0e92015-03-25 18:32:13 -0700696 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800697 * address is actually used decides if the flag is set or not.
698 *
699 * For single mode LE only controllers and dual-mode controllers
700 * with BR/EDR disabled, the existence of the static address will
701 * be evaluated.
702 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700703 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700704 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
706 if (bacmp(&hdev->static_addr, BDADDR_ANY))
707 settings |= MGMT_SETTING_STATIC_ADDRESS;
708 }
709
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200710 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200711}
712
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300713#define PNP_INFO_SVCLASS_ID 0x1200
714
Johan Hedberg213202e2013-01-27 00:31:33 +0200715static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 4)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 u16 uuid16;
725
726 if (uuid->size != 16)
727 continue;
728
729 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
730 if (uuid16 < 0x1100)
731 continue;
732
733 if (uuid16 == PNP_INFO_SVCLASS_ID)
734 continue;
735
736 if (!uuids_start) {
737 uuids_start = ptr;
738 uuids_start[0] = 1;
739 uuids_start[1] = EIR_UUID16_ALL;
740 ptr += 2;
741 }
742
743 /* Stop if not enough space to put next UUID */
744 if ((ptr - data) + sizeof(u16) > len) {
745 uuids_start[1] = EIR_UUID16_SOME;
746 break;
747 }
748
749 *ptr++ = (uuid16 & 0x00ff);
750 *ptr++ = (uuid16 & 0xff00) >> 8;
751 uuids_start[0] += sizeof(uuid16);
752 }
753
754 return ptr;
755}
756
Johan Hedbergcdf19632013-01-27 00:31:34 +0200757static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
758{
759 u8 *ptr = data, *uuids_start = NULL;
760 struct bt_uuid *uuid;
761
762 if (len < 6)
763 return ptr;
764
765 list_for_each_entry(uuid, &hdev->uuids, list) {
766 if (uuid->size != 32)
767 continue;
768
769 if (!uuids_start) {
770 uuids_start = ptr;
771 uuids_start[0] = 1;
772 uuids_start[1] = EIR_UUID32_ALL;
773 ptr += 2;
774 }
775
776 /* Stop if not enough space to put next UUID */
777 if ((ptr - data) + sizeof(u32) > len) {
778 uuids_start[1] = EIR_UUID32_SOME;
779 break;
780 }
781
782 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
783 ptr += sizeof(u32);
784 uuids_start[0] += sizeof(u32);
785 }
786
787 return ptr;
788}
789
Johan Hedbergc00d5752013-01-27 00:31:35 +0200790static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
791{
792 u8 *ptr = data, *uuids_start = NULL;
793 struct bt_uuid *uuid;
794
795 if (len < 18)
796 return ptr;
797
798 list_for_each_entry(uuid, &hdev->uuids, list) {
799 if (uuid->size != 128)
800 continue;
801
802 if (!uuids_start) {
803 uuids_start = ptr;
804 uuids_start[0] = 1;
805 uuids_start[1] = EIR_UUID128_ALL;
806 ptr += 2;
807 }
808
809 /* Stop if not enough space to put next UUID */
810 if ((ptr - data) + 16 > len) {
811 uuids_start[1] = EIR_UUID128_SOME;
812 break;
813 }
814
815 memcpy(ptr, uuid->uuid, 16);
816 ptr += 16;
817 uuids_start[0] += 16;
818 }
819
820 return ptr;
821}
822
Johan Hedberg333ae952015-03-17 13:48:47 +0200823static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
824{
825 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
826}
827
Johan Hedberg333ae952015-03-17 13:48:47 +0200828static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
829 struct hci_dev *hdev,
830 const void *data)
831{
832 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
833}
834
Arman Uguray4117ed72015-03-23 15:57:14 -0700835static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700836{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700837 u8 ad_len = 0;
838 size_t name_len;
839
840 name_len = strlen(hdev->dev_name);
841 if (name_len > 0) {
842 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
843
844 if (name_len > max_len) {
845 name_len = max_len;
846 ptr[1] = EIR_NAME_SHORT;
847 } else
848 ptr[1] = EIR_NAME_COMPLETE;
849
850 ptr[0] = name_len + 1;
851
852 memcpy(ptr + 2, hdev->dev_name, name_len);
853
854 ad_len += (name_len + 2);
855 ptr += (name_len + 2);
856 }
857
858 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700859}
860
Arman Uguray4117ed72015-03-23 15:57:14 -0700861static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
862{
863 /* TODO: Set the appropriate entries based on advertising instance flags
864 * here once flags other than 0 are supported.
865 */
866 memcpy(ptr, hdev->adv_instance.scan_rsp_data,
867 hdev->adv_instance.scan_rsp_len);
868
869 return hdev->adv_instance.scan_rsp_len;
870}
871
872static void update_scan_rsp_data_for_instance(struct hci_request *req,
873 u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700874{
875 struct hci_dev *hdev = req->hdev;
876 struct hci_cp_le_set_scan_rsp_data cp;
877 u8 len;
878
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700880 return;
881
882 memset(&cp, 0, sizeof(cp));
883
Arman Uguray4117ed72015-03-23 15:57:14 -0700884 if (instance)
885 len = create_instance_scan_rsp_data(hdev, cp.data);
886 else
887 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700888
Johan Hedbergeb438b52013-10-16 15:31:07 +0300889 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700890 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700891 return;
892
Johan Hedbergeb438b52013-10-16 15:31:07 +0300893 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
894 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700895
896 cp.length = len;
897
898 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
899}
900
Arman Uguray4117ed72015-03-23 15:57:14 -0700901static void update_scan_rsp_data(struct hci_request *req)
902{
903 struct hci_dev *hdev = req->hdev;
904 u8 instance;
905
906 /* The "Set Advertising" setting supersedes the "Add Advertising"
907 * setting. Here we set the scan response data based on which
908 * setting was set. When neither apply, default to the global settings,
909 * represented by instance "0".
910 */
911 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
912 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
913 instance = 0x01;
914 else
915 instance = 0x00;
916
917 update_scan_rsp_data_for_instance(req, instance);
918}
919
Johan Hedberg9a43e252013-10-20 19:00:07 +0300920static u8 get_adv_discov_flags(struct hci_dev *hdev)
921{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200922 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300923
924 /* If there's a pending mgmt command the flags will not yet have
925 * their final values, so check for this first.
926 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200927 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300928 if (cmd) {
929 struct mgmt_mode *cp = cmd->param;
930 if (cp->val == 0x01)
931 return LE_AD_GENERAL;
932 else if (cp->val == 0x02)
933 return LE_AD_LIMITED;
934 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700935 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300936 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700937 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300938 return LE_AD_GENERAL;
939 }
940
941 return 0;
942}
943
Arman Uguraye7a685d2015-03-25 18:53:40 -0700944static u8 get_current_adv_instance(struct hci_dev *hdev)
Arman Uguray24b4f382015-03-23 15:57:12 -0700945{
Arman Uguray24b4f382015-03-23 15:57:12 -0700946 /* The "Set Advertising" setting supersedes the "Add Advertising"
947 * setting. Here we set the advertising data based on which
948 * setting was set. When neither apply, default to the global settings,
949 * represented by instance "0".
950 */
951 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
952 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700953 return 0x01;
954
955 return 0x00;
956}
957
958static bool get_connectable(struct hci_dev *hdev)
959{
960 struct mgmt_pending_cmd *cmd;
961
962 /* If there's a pending mgmt command the flag will not yet have
963 * it's final value, so check for this first.
964 */
965 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
966 if (cmd) {
967 struct mgmt_mode *cp = cmd->param;
968
969 return cp->val;
970 }
971
972 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
973}
974
975static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
976{
977 u32 flags;
978
979 if (instance > 0x01)
980 return 0;
981
Arman Ugurayfdf51782015-03-25 18:53:46 -0700982 if (instance == 0x01)
Arman Uguraye7a685d2015-03-25 18:53:40 -0700983 return hdev->adv_instance.flags;
984
Arman Ugurayfdf51782015-03-25 18:53:46 -0700985 /* Instance 0 always manages the "Tx Power" and "Flags" fields */
986 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700987
Arman Ugurayfaccb952015-03-28 12:38:58 -0700988 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting corresponds
989 * to the "connectable" instance flag.
990 */
991 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700992 flags |= MGMT_ADV_FLAG_CONNECTABLE;
993
Arman Uguraye7a685d2015-03-25 18:53:40 -0700994 return flags;
995}
996
Arman Ugurayc7d48832015-03-28 12:38:59 -0700997static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
998{
999 /* Ignore instance 0 and other unsupported instances */
1000 if (instance != 0x01)
1001 return 0;
1002
1003 /* TODO: Take into account the "appearance" and "local-name" flags here.
1004 * These are currently being ignored as they are not supported.
1005 */
1006 return hdev->adv_instance.scan_rsp_len;
1007}
1008
Arman Ugurayfdf51782015-03-25 18:53:46 -07001009static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1010{
1011 u8 ad_len = 0, flags = 0;
1012 u32 instance_flags = get_adv_instance_flags(hdev, instance);
1013
1014 /* The Add Advertising command allows userspace to set both the general
1015 * and limited discoverable flags.
1016 */
1017 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1018 flags |= LE_AD_GENERAL;
1019
1020 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1021 flags |= LE_AD_LIMITED;
1022
1023 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1024 /* If a discovery flag wasn't provided, simply use the global
1025 * settings.
1026 */
1027 if (!flags)
1028 flags |= get_adv_discov_flags(hdev);
1029
1030 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1031 flags |= LE_AD_NO_BREDR;
1032
1033 /* If flags would still be empty, then there is no need to
1034 * include the "Flags" AD field".
1035 */
1036 if (flags) {
1037 ptr[0] = 0x02;
1038 ptr[1] = EIR_FLAGS;
1039 ptr[2] = flags;
1040
1041 ad_len += 3;
1042 ptr += 3;
1043 }
1044 }
1045
1046 /* Provide Tx Power only if we can provide a valid value for it */
1047 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1048 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1049 ptr[0] = 0x02;
1050 ptr[1] = EIR_TX_POWER;
1051 ptr[2] = (u8)hdev->adv_tx_power;
1052
1053 ad_len += 3;
1054 ptr += 3;
1055 }
1056
1057 if (instance) {
1058 memcpy(ptr, hdev->adv_instance.adv_data,
1059 hdev->adv_instance.adv_data_len);
1060 ad_len += hdev->adv_instance.adv_data_len;
1061 }
1062
1063 return ad_len;
1064}
1065
1066static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
1067{
1068 struct hci_dev *hdev = req->hdev;
1069 struct hci_cp_le_set_adv_data cp;
1070 u8 len;
1071
1072 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1073 return;
1074
1075 memset(&cp, 0, sizeof(cp));
1076
1077 len = create_instance_adv_data(hdev, instance, cp.data);
1078
1079 /* There's nothing to do if the data hasn't changed */
1080 if (hdev->adv_data_len == len &&
1081 memcmp(cp.data, hdev->adv_data, len) == 0)
1082 return;
1083
1084 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1085 hdev->adv_data_len = len;
1086
1087 cp.length = len;
1088
1089 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1090}
1091
Arman Uguraye7a685d2015-03-25 18:53:40 -07001092static void update_adv_data(struct hci_request *req)
1093{
1094 struct hci_dev *hdev = req->hdev;
1095 u8 instance = get_current_adv_instance(hdev);
Arman Uguray24b4f382015-03-23 15:57:12 -07001096
1097 update_adv_data_for_instance(req, instance);
1098}
1099
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001100int mgmt_update_adv_data(struct hci_dev *hdev)
1101{
1102 struct hci_request req;
1103
1104 hci_req_init(&req, hdev);
1105 update_adv_data(&req);
1106
1107 return hci_req_run(&req, NULL);
1108}
1109
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001110static void create_eir(struct hci_dev *hdev, u8 *data)
1111{
1112 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001113 size_t name_len;
1114
1115 name_len = strlen(hdev->dev_name);
1116
1117 if (name_len > 0) {
1118 /* EIR Data type */
1119 if (name_len > 48) {
1120 name_len = 48;
1121 ptr[1] = EIR_NAME_SHORT;
1122 } else
1123 ptr[1] = EIR_NAME_COMPLETE;
1124
1125 /* EIR Data length */
1126 ptr[0] = name_len + 1;
1127
1128 memcpy(ptr + 2, hdev->dev_name, name_len);
1129
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001130 ptr += (name_len + 2);
1131 }
1132
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001133 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001134 ptr[0] = 2;
1135 ptr[1] = EIR_TX_POWER;
1136 ptr[2] = (u8) hdev->inq_tx_power;
1137
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001138 ptr += 3;
1139 }
1140
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001141 if (hdev->devid_source > 0) {
1142 ptr[0] = 9;
1143 ptr[1] = EIR_DEVICE_ID;
1144
1145 put_unaligned_le16(hdev->devid_source, ptr + 2);
1146 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1147 put_unaligned_le16(hdev->devid_product, ptr + 6);
1148 put_unaligned_le16(hdev->devid_version, ptr + 8);
1149
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001150 ptr += 10;
1151 }
1152
Johan Hedberg213202e2013-01-27 00:31:33 +02001153 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001154 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001155 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001156}
1157
Johan Hedberg890ea892013-03-15 17:06:52 -05001158static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001159{
Johan Hedberg890ea892013-03-15 17:06:52 -05001160 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001161 struct hci_cp_write_eir cp;
1162
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001163 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001164 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001165
Johan Hedberg976eb202012-10-24 21:12:01 +03001166 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001167 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001168
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001169 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001170 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001171
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001172 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001173 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001174
1175 memset(&cp, 0, sizeof(cp));
1176
1177 create_eir(hdev, cp.data);
1178
1179 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001180 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001181
1182 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1183
Johan Hedberg890ea892013-03-15 17:06:52 -05001184 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001185}
1186
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001187static u8 get_service_classes(struct hci_dev *hdev)
1188{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001189 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001190 u8 val = 0;
1191
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001192 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001193 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001194
1195 return val;
1196}
1197
Johan Hedberg890ea892013-03-15 17:06:52 -05001198static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001199{
Johan Hedberg890ea892013-03-15 17:06:52 -05001200 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001201 u8 cod[3];
1202
1203 BT_DBG("%s", hdev->name);
1204
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001205 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001206 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001207
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001208 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001209 return;
1210
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001211 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001212 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001213
1214 cod[0] = hdev->minor_class;
1215 cod[1] = hdev->major_class;
1216 cod[2] = get_service_classes(hdev);
1217
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001218 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001219 cod[1] |= 0x20;
1220
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001221 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001222 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001223
Johan Hedberg890ea892013-03-15 17:06:52 -05001224 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001225}
1226
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001227static void disable_advertising(struct hci_request *req)
1228{
1229 u8 enable = 0x00;
1230
1231 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1232}
1233
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001234static void enable_advertising(struct hci_request *req)
1235{
1236 struct hci_dev *hdev = req->hdev;
1237 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001238 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001239 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001240 u8 instance;
1241 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001242
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001243 if (hci_conn_num(hdev, LE_LINK) > 0)
1244 return;
1245
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001246 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001247 disable_advertising(req);
1248
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001249 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001250 * hci_update_random_address knows that it's safe to go ahead
1251 * and write a new random address. The flag will be set back on
1252 * as soon as the SET_ADV_ENABLE HCI command completes.
1253 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001254 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001255
Arman Uguraye7a685d2015-03-25 18:53:40 -07001256 instance = get_current_adv_instance(hdev);
1257 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001258
1259 /* If the "connectable" instance flag was not set, then choose between
1260 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1261 */
1262 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1263 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001264
Johan Hedberga4858cb2014-02-25 19:56:31 +02001265 /* Set require_privacy to true only when non-connectable
1266 * advertising is used. In that case it is fine to use a
1267 * non-resolvable private address.
1268 */
1269 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001270 return;
1271
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001272 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001273 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1274 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001275
1276 if (connectable)
1277 cp.type = LE_ADV_IND;
1278 else if (get_adv_instance_scan_rsp_len(hdev, instance))
1279 cp.type = LE_ADV_SCAN_IND;
1280 else
1281 cp.type = LE_ADV_NONCONN_IND;
1282
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001283 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001284 cp.channel_map = hdev->le_adv_channel_map;
1285
1286 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1287
1288 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1289}
1290
Johan Hedberg7d785252011-12-15 00:47:39 +02001291static void service_cache_off(struct work_struct *work)
1292{
1293 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001294 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001295 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001296
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001297 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001298 return;
1299
Johan Hedberg890ea892013-03-15 17:06:52 -05001300 hci_req_init(&req, hdev);
1301
Johan Hedberg7d785252011-12-15 00:47:39 +02001302 hci_dev_lock(hdev);
1303
Johan Hedberg890ea892013-03-15 17:06:52 -05001304 update_eir(&req);
1305 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001306
1307 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001308
1309 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001310}
1311
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001312static void rpa_expired(struct work_struct *work)
1313{
1314 struct hci_dev *hdev = container_of(work, struct hci_dev,
1315 rpa_expired.work);
1316 struct hci_request req;
1317
1318 BT_DBG("");
1319
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001320 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001321
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001322 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001323 return;
1324
1325 /* The generation of a new RPA and programming it into the
1326 * controller happens in the enable_advertising() function.
1327 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001328 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001329 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001330 hci_req_run(&req, NULL);
1331}
1332
Johan Hedberg6a919082012-02-28 06:17:26 +02001333static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001334{
Marcel Holtmann238be782015-03-13 02:11:06 -07001335 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001336 return;
1337
Johan Hedberg4f87da82012-03-02 19:55:56 +02001338 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001339 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001340
Johan Hedberg4f87da82012-03-02 19:55:56 +02001341 /* Non-mgmt controlled devices get this bit set
1342 * implicitly so that pairing works for them, however
1343 * for mgmt we require user-space to explicitly enable
1344 * it
1345 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001346 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001347}
1348
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001349static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001350 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001351{
1352 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001354 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001355
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001356 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001357
Johan Hedberg03811012010-12-08 00:21:06 +02001358 memset(&rp, 0, sizeof(rp));
1359
Johan Hedberg03811012010-12-08 00:21:06 +02001360 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001361
1362 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001363 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001364
1365 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1366 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1367
1368 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001369
1370 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001371 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001372
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001373 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001374
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001375 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1376 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001377}
1378
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001379static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001380{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001381 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001382
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001383 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1384 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001385}
1386
Marcel Holtmann1904a852015-01-11 13:50:44 -08001387static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001388{
1389 BT_DBG("%s status 0x%02x", hdev->name, status);
1390
Johan Hedberga3172b72014-02-28 09:33:44 +02001391 if (hci_conn_count(hdev) == 0) {
1392 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001393 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001394 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001395}
1396
Johan Hedberg23a48092014-07-08 16:05:06 +03001397static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001398{
1399 struct hci_dev *hdev = req->hdev;
1400 struct hci_cp_remote_name_req_cancel cp;
1401 struct inquiry_entry *e;
1402
1403 switch (hdev->discovery.state) {
1404 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001405 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001406 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001407
1408 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001409 cancel_delayed_work(&hdev->le_scan_disable);
1410 hci_req_add_le_scan_disable(req);
1411 }
1412
Johan Hedberg23a48092014-07-08 16:05:06 +03001413 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001414
1415 case DISCOVERY_RESOLVING:
1416 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1417 NAME_PENDING);
1418 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001419 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001420
1421 bacpy(&cp.bdaddr, &e->data.bdaddr);
1422 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1423 &cp);
1424
Johan Hedberg23a48092014-07-08 16:05:06 +03001425 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001426
1427 default:
1428 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001429 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001430 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001431 return true;
1432 }
1433
Johan Hedberg21a60d32014-06-10 14:05:58 +03001434 break;
1435 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001436
1437 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001438}
1439
Arman Uguray912098a2015-03-23 15:57:15 -07001440static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1441 u8 instance)
1442{
1443 struct mgmt_ev_advertising_added ev;
1444
1445 ev.instance = instance;
1446
1447 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1448}
1449
1450static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1451 u8 instance)
1452{
1453 struct mgmt_ev_advertising_removed ev;
1454
1455 ev.instance = instance;
1456
1457 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1458}
1459
1460static void clear_adv_instance(struct hci_dev *hdev)
1461{
1462 struct hci_request req;
1463
1464 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1465 return;
1466
1467 if (hdev->adv_instance.timeout)
1468 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
1469
1470 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1471 advertising_removed(NULL, hdev, 1);
1472 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1473
1474 if (!hdev_is_powered(hdev) ||
1475 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1476 return;
1477
1478 hci_req_init(&req, hdev);
1479 disable_advertising(&req);
1480 hci_req_run(&req, NULL);
1481}
1482
Johan Hedberg8b064a32014-02-24 14:52:22 +02001483static int clean_up_hci_state(struct hci_dev *hdev)
1484{
1485 struct hci_request req;
1486 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001487 bool discov_stopped;
1488 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001489
1490 hci_req_init(&req, hdev);
1491
1492 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1493 test_bit(HCI_PSCAN, &hdev->flags)) {
1494 u8 scan = 0x00;
1495 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1496 }
1497
Arman Uguray912098a2015-03-23 15:57:15 -07001498 if (hdev->adv_instance.timeout)
1499 clear_adv_instance(hdev);
1500
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001501 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001502 disable_advertising(&req);
1503
Johan Hedberg23a48092014-07-08 16:05:06 +03001504 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001505
1506 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1507 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001508 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001509
Johan Hedbergc9910d02014-02-27 14:35:12 +02001510 switch (conn->state) {
1511 case BT_CONNECTED:
1512 case BT_CONFIG:
1513 dc.handle = cpu_to_le16(conn->handle);
1514 dc.reason = 0x15; /* Terminated due to Power Off */
1515 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1516 break;
1517 case BT_CONNECT:
1518 if (conn->type == LE_LINK)
1519 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1520 0, NULL);
1521 else if (conn->type == ACL_LINK)
1522 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1523 6, &conn->dst);
1524 break;
1525 case BT_CONNECT2:
1526 bacpy(&rej.bdaddr, &conn->dst);
1527 rej.reason = 0x15; /* Terminated due to Power Off */
1528 if (conn->type == ACL_LINK)
1529 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1530 sizeof(rej), &rej);
1531 else if (conn->type == SCO_LINK)
1532 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1533 sizeof(rej), &rej);
1534 break;
1535 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001536 }
1537
Johan Hedberg23a48092014-07-08 16:05:06 +03001538 err = hci_req_run(&req, clean_up_hci_complete);
1539 if (!err && discov_stopped)
1540 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1541
1542 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001543}
1544
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001545static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001546 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001547{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001548 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001549 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001550 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001552 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001553
Johan Hedberga7e80f22013-01-09 16:05:19 +02001554 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001555 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1556 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001557
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001558 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001559
Johan Hedberg333ae952015-03-17 13:48:47 +02001560 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001561 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1562 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001563 goto failed;
1564 }
1565
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001566 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001567 cancel_delayed_work(&hdev->power_off);
1568
1569 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001570 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1571 data, len);
1572 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001573 goto failed;
1574 }
1575 }
1576
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001577 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001578 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001579 goto failed;
1580 }
1581
Johan Hedberg03811012010-12-08 00:21:06 +02001582 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1583 if (!cmd) {
1584 err = -ENOMEM;
1585 goto failed;
1586 }
1587
Johan Hedberg8b064a32014-02-24 14:52:22 +02001588 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001589 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590 err = 0;
1591 } else {
1592 /* Disconnect connections, stop scans, etc */
1593 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001594 if (!err)
1595 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1596 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001597
Johan Hedberg8b064a32014-02-24 14:52:22 +02001598 /* ENODATA means there were no HCI commands queued */
1599 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001600 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001601 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1602 err = 0;
1603 }
1604 }
Johan Hedberg03811012010-12-08 00:21:06 +02001605
1606failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001607 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001608 return err;
1609}
1610
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001611static int new_settings(struct hci_dev *hdev, struct sock *skip)
1612{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001613 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001614
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001615 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1616 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001617}
1618
Johan Hedberg91a668b2014-07-09 13:28:26 +03001619int mgmt_new_settings(struct hci_dev *hdev)
1620{
1621 return new_settings(hdev, NULL);
1622}
1623
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001624struct cmd_lookup {
1625 struct sock *sk;
1626 struct hci_dev *hdev;
1627 u8 mgmt_status;
1628};
1629
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001630static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001631{
1632 struct cmd_lookup *match = data;
1633
1634 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1635
1636 list_del(&cmd->list);
1637
1638 if (match->sk == NULL) {
1639 match->sk = cmd->sk;
1640 sock_hold(match->sk);
1641 }
1642
1643 mgmt_pending_free(cmd);
1644}
1645
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001646static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001647{
1648 u8 *status = data;
1649
Johan Hedberga69e8372015-03-06 21:08:53 +02001650 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001651 mgmt_pending_remove(cmd);
1652}
1653
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001654static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001655{
1656 if (cmd->cmd_complete) {
1657 u8 *status = data;
1658
1659 cmd->cmd_complete(cmd, *status);
1660 mgmt_pending_remove(cmd);
1661
1662 return;
1663 }
1664
1665 cmd_status_rsp(cmd, data);
1666}
1667
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001668static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001669{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001670 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1671 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001672}
1673
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001674static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001675{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001676 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1677 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001678}
1679
Johan Hedberge6fe7982013-10-02 15:45:22 +03001680static u8 mgmt_bredr_support(struct hci_dev *hdev)
1681{
1682 if (!lmp_bredr_capable(hdev))
1683 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001684 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001685 return MGMT_STATUS_REJECTED;
1686 else
1687 return MGMT_STATUS_SUCCESS;
1688}
1689
1690static u8 mgmt_le_support(struct hci_dev *hdev)
1691{
1692 if (!lmp_le_capable(hdev))
1693 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001694 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001695 return MGMT_STATUS_REJECTED;
1696 else
1697 return MGMT_STATUS_SUCCESS;
1698}
1699
Marcel Holtmann1904a852015-01-11 13:50:44 -08001700static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1701 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001702{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001703 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001704 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001705 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001706 bool changed;
1707
1708 BT_DBG("status 0x%02x", status);
1709
1710 hci_dev_lock(hdev);
1711
Johan Hedberg333ae952015-03-17 13:48:47 +02001712 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001713 if (!cmd)
1714 goto unlock;
1715
1716 if (status) {
1717 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001718 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001719 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001720 goto remove_cmd;
1721 }
1722
1723 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001724 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001725 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001726
1727 if (hdev->discov_timeout > 0) {
1728 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1729 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1730 to);
1731 }
1732 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001733 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001734 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001735
1736 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1737
1738 if (changed)
1739 new_settings(hdev, cmd->sk);
1740
Marcel Holtmann970ba522013-10-15 06:33:57 -07001741 /* When the discoverable mode gets changed, make sure
1742 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001743 * bit correctly set. Also update page scan based on whitelist
1744 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001745 */
1746 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001747 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001748 update_class(&req);
1749 hci_req_run(&req, NULL);
1750
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001751remove_cmd:
1752 mgmt_pending_remove(cmd);
1753
1754unlock:
1755 hci_dev_unlock(hdev);
1756}
1757
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001758static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001759 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001760{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001761 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001762 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001763 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001764 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001765 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001766 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001767
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001768 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001769
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001770 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1771 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001772 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1773 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001774
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001775 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001776 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1777 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001778
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001779 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001780
1781 /* Disabling discoverable requires that no timeout is set,
1782 * and enabling limited discoverable requires a timeout.
1783 */
1784 if ((cp->val == 0x00 && timeout > 0) ||
1785 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001786 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1787 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001788
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001789 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001790
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001791 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001792 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1793 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001794 goto failed;
1795 }
1796
Johan Hedberg333ae952015-03-17 13:48:47 +02001797 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1798 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001799 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1800 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001801 goto failed;
1802 }
1803
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001804 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001805 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1806 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001807 goto failed;
1808 }
1809
1810 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001811 bool changed = false;
1812
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001813 /* Setting limited discoverable when powered off is
1814 * not a valid operation since it requires a timeout
1815 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1816 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001817 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001818 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001819 changed = true;
1820 }
1821
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001822 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001823 if (err < 0)
1824 goto failed;
1825
1826 if (changed)
1827 err = new_settings(hdev, sk);
1828
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001829 goto failed;
1830 }
1831
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001832 /* If the current mode is the same, then just update the timeout
1833 * value with the new value. And if only the timeout gets updated,
1834 * then no need for any HCI transactions.
1835 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001836 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1837 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1838 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001839 cancel_delayed_work(&hdev->discov_off);
1840 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001841
Marcel Holtmann36261542013-10-15 08:28:51 -07001842 if (cp->val && hdev->discov_timeout > 0) {
1843 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001844 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001845 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001846 }
1847
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001848 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001849 goto failed;
1850 }
1851
1852 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1853 if (!cmd) {
1854 err = -ENOMEM;
1855 goto failed;
1856 }
1857
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001858 /* Cancel any potential discoverable timeout that might be
1859 * still active and store new timeout value. The arming of
1860 * the timeout happens in the complete handler.
1861 */
1862 cancel_delayed_work(&hdev->discov_off);
1863 hdev->discov_timeout = timeout;
1864
Johan Hedbergb456f872013-10-19 23:38:22 +03001865 /* Limited discoverable mode */
1866 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001867 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001868 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001869 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001870
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001871 hci_req_init(&req, hdev);
1872
Johan Hedberg9a43e252013-10-20 19:00:07 +03001873 /* The procedure for LE-only controllers is much simpler - just
1874 * update the advertising data.
1875 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001876 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001877 goto update_ad;
1878
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001879 scan = SCAN_PAGE;
1880
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001881 if (cp->val) {
1882 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001883
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001884 if (cp->val == 0x02) {
1885 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001886 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001887 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1888 hci_cp.iac_lap[1] = 0x8b;
1889 hci_cp.iac_lap[2] = 0x9e;
1890 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1891 hci_cp.iac_lap[4] = 0x8b;
1892 hci_cp.iac_lap[5] = 0x9e;
1893 } else {
1894 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001895 hci_cp.num_iac = 1;
1896 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1897 hci_cp.iac_lap[1] = 0x8b;
1898 hci_cp.iac_lap[2] = 0x9e;
1899 }
1900
1901 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1902 (hci_cp.num_iac * 3) + 1, &hci_cp);
1903
1904 scan |= SCAN_INQUIRY;
1905 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001906 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001907 }
1908
1909 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001910
Johan Hedberg9a43e252013-10-20 19:00:07 +03001911update_ad:
1912 update_adv_data(&req);
1913
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001914 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001915 if (err < 0)
1916 mgmt_pending_remove(cmd);
1917
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001918failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001919 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001920 return err;
1921}
1922
Johan Hedberg406d7802013-03-15 17:07:09 -05001923static void write_fast_connectable(struct hci_request *req, bool enable)
1924{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001925 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001926 struct hci_cp_write_page_scan_activity acp;
1927 u8 type;
1928
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001929 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001930 return;
1931
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001932 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1933 return;
1934
Johan Hedberg406d7802013-03-15 17:07:09 -05001935 if (enable) {
1936 type = PAGE_SCAN_TYPE_INTERLACED;
1937
1938 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001939 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001940 } else {
1941 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1942
1943 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001944 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001945 }
1946
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001947 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001948
Johan Hedbergbd98b992013-03-15 17:07:13 -05001949 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1950 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1951 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1952 sizeof(acp), &acp);
1953
1954 if (hdev->page_scan_type != type)
1955 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001956}
1957
Marcel Holtmann1904a852015-01-11 13:50:44 -08001958static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1959 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001960{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001961 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001962 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001963 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001964
1965 BT_DBG("status 0x%02x", status);
1966
1967 hci_dev_lock(hdev);
1968
Johan Hedberg333ae952015-03-17 13:48:47 +02001969 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001970 if (!cmd)
1971 goto unlock;
1972
Johan Hedberg37438c12013-10-14 16:20:05 +03001973 if (status) {
1974 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001975 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001976 goto remove_cmd;
1977 }
1978
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001979 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001980 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001981 conn_changed = !hci_dev_test_and_set_flag(hdev,
1982 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001983 discov_changed = false;
1984 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001985 conn_changed = hci_dev_test_and_clear_flag(hdev,
1986 HCI_CONNECTABLE);
1987 discov_changed = hci_dev_test_and_clear_flag(hdev,
1988 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001989 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001990
Johan Hedberg2b76f452013-03-15 17:07:04 -05001991 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1992
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001993 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001994 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001995 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001996 if (discov_changed)
1997 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001998 hci_update_background_scan(hdev);
1999 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002000
Johan Hedberg37438c12013-10-14 16:20:05 +03002001remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002002 mgmt_pending_remove(cmd);
2003
2004unlock:
2005 hci_dev_unlock(hdev);
2006}
2007
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002008static int set_connectable_update_settings(struct hci_dev *hdev,
2009 struct sock *sk, u8 val)
2010{
2011 bool changed = false;
2012 int err;
2013
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002014 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002015 changed = true;
2016
2017 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002018 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002019 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002020 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2021 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002022 }
2023
2024 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2025 if (err < 0)
2026 return err;
2027
Johan Hedberg562064e2014-07-08 16:35:34 +03002028 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002029 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002030 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002031 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002032 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002033
2034 return 0;
2035}
2036
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002037static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002038 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002039{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002040 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002041 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002042 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002043 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002044 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002045
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002046 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002047
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002048 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2049 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002050 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2051 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002052
Johan Hedberga7e80f22013-01-09 16:05:19 +02002053 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002054 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2055 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002056
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002057 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002058
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002059 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002060 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002061 goto failed;
2062 }
2063
Johan Hedberg333ae952015-03-17 13:48:47 +02002064 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2065 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002066 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2067 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002068 goto failed;
2069 }
2070
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002071 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2072 if (!cmd) {
2073 err = -ENOMEM;
2074 goto failed;
2075 }
2076
Johan Hedberg2b76f452013-03-15 17:07:04 -05002077 hci_req_init(&req, hdev);
2078
Johan Hedberg9a43e252013-10-20 19:00:07 +03002079 /* If BR/EDR is not enabled and we disable advertising as a
2080 * by-product of disabling connectable, we need to update the
2081 * advertising flags.
2082 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002083 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002084 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002085 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2086 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002087 }
2088 update_adv_data(&req);
2089 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002090 if (cp->val) {
2091 scan = SCAN_PAGE;
2092 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002093 /* If we don't have any whitelist entries just
2094 * disable all scanning. If there are entries
2095 * and we had both page and inquiry scanning
2096 * enabled then fall back to only page scanning.
2097 * Otherwise no changes are needed.
2098 */
2099 if (list_empty(&hdev->whitelist))
2100 scan = SCAN_DISABLED;
2101 else if (test_bit(HCI_ISCAN, &hdev->flags))
2102 scan = SCAN_PAGE;
2103 else
2104 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002105
2106 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002107 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002108 cancel_delayed_work(&hdev->discov_off);
2109 }
2110
2111 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2112 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002113
Johan Hedberg3bd27242014-07-28 20:53:58 +03002114no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002115 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002116 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002117 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002118
Johan Hedberg2b76f452013-03-15 17:07:04 -05002119 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002120 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002121 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002122 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002123 err = set_connectable_update_settings(hdev, sk,
2124 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002125 goto failed;
2126 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002127
2128failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002129 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002130 return err;
2131}
2132
Johan Hedbergb2939472014-07-30 09:22:23 +03002133static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002134 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002135{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002136 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002137 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002138 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002139
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002140 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002141
Johan Hedberga7e80f22013-01-09 16:05:19 +02002142 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002143 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2144 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002145
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002146 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002147
2148 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002149 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002150 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002151 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002152
Johan Hedbergb2939472014-07-30 09:22:23 +03002153 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002154 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002155 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002156
Marcel Holtmann55594352013-10-06 16:11:57 -07002157 if (changed)
2158 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002159
Marcel Holtmann55594352013-10-06 16:11:57 -07002160unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002161 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002162 return err;
2163}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002164
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002165static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2166 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002167{
2168 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002169 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002170 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002171 int err;
2172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002173 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002174
Johan Hedberge6fe7982013-10-02 15:45:22 +03002175 status = mgmt_bredr_support(hdev);
2176 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002177 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2178 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002179
Johan Hedberga7e80f22013-01-09 16:05:19 +02002180 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002181 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2182 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002183
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002184 hci_dev_lock(hdev);
2185
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002186 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002187 bool changed = false;
2188
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002189 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002190 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002191 changed = true;
2192 }
2193
2194 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2195 if (err < 0)
2196 goto failed;
2197
2198 if (changed)
2199 err = new_settings(hdev, sk);
2200
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002201 goto failed;
2202 }
2203
Johan Hedberg333ae952015-03-17 13:48:47 +02002204 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002205 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2206 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002207 goto failed;
2208 }
2209
2210 val = !!cp->val;
2211
2212 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2213 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2214 goto failed;
2215 }
2216
2217 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2218 if (!cmd) {
2219 err = -ENOMEM;
2220 goto failed;
2221 }
2222
2223 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2224 if (err < 0) {
2225 mgmt_pending_remove(cmd);
2226 goto failed;
2227 }
2228
2229failed:
2230 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002231 return err;
2232}
2233
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002234static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002235{
2236 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002237 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002238 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002239 int err;
2240
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002241 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002242
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002243 status = mgmt_bredr_support(hdev);
2244 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002245 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002246
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002247 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002248 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2249 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002250
Johan Hedberga7e80f22013-01-09 16:05:19 +02002251 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002252 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2253 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002254
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002255 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002256
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002257 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002258 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002259
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002260 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002261 changed = !hci_dev_test_and_set_flag(hdev,
2262 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002263 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002264 changed = hci_dev_test_and_clear_flag(hdev,
2265 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002266 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002267 changed = hci_dev_test_and_clear_flag(hdev,
2268 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002269 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002270 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002271 }
2272
2273 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2274 if (err < 0)
2275 goto failed;
2276
2277 if (changed)
2278 err = new_settings(hdev, sk);
2279
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002280 goto failed;
2281 }
2282
Johan Hedberg333ae952015-03-17 13:48:47 +02002283 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002284 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2285 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002286 goto failed;
2287 }
2288
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002289 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002290 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2291 goto failed;
2292 }
2293
2294 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2295 if (!cmd) {
2296 err = -ENOMEM;
2297 goto failed;
2298 }
2299
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002300 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002301 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2302 sizeof(cp->val), &cp->val);
2303
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002304 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002305 if (err < 0) {
2306 mgmt_pending_remove(cmd);
2307 goto failed;
2308 }
2309
2310failed:
2311 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002312 return err;
2313}
2314
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002315static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002316{
2317 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002318 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002319 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002320 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002321
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002322 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002323
Johan Hedberge6fe7982013-10-02 15:45:22 +03002324 status = mgmt_bredr_support(hdev);
2325 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002326 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002327
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002328 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002329 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2330 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002331
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002332 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002333 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2334 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002335
Johan Hedberga7e80f22013-01-09 16:05:19 +02002336 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002337 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2338 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002339
Marcel Holtmannee392692013-10-01 22:59:23 -07002340 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002341
Johan Hedberg333ae952015-03-17 13:48:47 +02002342 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002343 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2344 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002345 goto unlock;
2346 }
2347
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002348 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002349 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002350 } else {
2351 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002352 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2353 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002354 goto unlock;
2355 }
2356
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002357 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002358 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002359
2360 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2361 if (err < 0)
2362 goto unlock;
2363
2364 if (changed)
2365 err = new_settings(hdev, sk);
2366
2367unlock:
2368 hci_dev_unlock(hdev);
2369 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002370}
2371
Marcel Holtmann1904a852015-01-11 13:50:44 -08002372static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002373{
2374 struct cmd_lookup match = { NULL, hdev };
2375
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302376 hci_dev_lock(hdev);
2377
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002378 if (status) {
2379 u8 mgmt_err = mgmt_status(status);
2380
2381 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2382 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302383 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002384 }
2385
2386 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2387
2388 new_settings(hdev, match.sk);
2389
2390 if (match.sk)
2391 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002392
2393 /* Make sure the controller has a good default for
2394 * advertising data. Restrict the update to when LE
2395 * has actually been enabled. During power on, the
2396 * update in powered_update_hci will take care of it.
2397 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002398 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002399 struct hci_request req;
2400
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002401 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002402 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002403 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002404 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002405 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002406 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302407
2408unlock:
2409 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002410}
2411
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002412static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002413{
2414 struct mgmt_mode *cp = data;
2415 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002416 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002417 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002418 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002419 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002420
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002421 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002422
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002423 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002424 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2425 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002426
Johan Hedberga7e80f22013-01-09 16:05:19 +02002427 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002428 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2429 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002430
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002431 /* Bluetooth single mode LE only controllers or dual-mode
2432 * controllers configured as LE only devices, do not allow
2433 * switching LE off. These have either LE enabled explicitly
2434 * or BR/EDR has been previously switched off.
2435 *
2436 * When trying to enable an already enabled LE, then gracefully
2437 * send a positive response. Trying to disable it however will
2438 * result into rejection.
2439 */
2440 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2441 if (cp->val == 0x01)
2442 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2443
Johan Hedberga69e8372015-03-06 21:08:53 +02002444 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2445 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002446 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002447
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002448 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002449
2450 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002451 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002452
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002453 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002454 bool changed = false;
2455
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002456 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002457 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002458 changed = true;
2459 }
2460
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002461 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002462 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002463 changed = true;
2464 }
2465
Johan Hedberg06199cf2012-02-22 16:37:11 +02002466 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2467 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002468 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002469
2470 if (changed)
2471 err = new_settings(hdev, sk);
2472
Johan Hedberg1de028c2012-02-29 19:55:35 -08002473 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002474 }
2475
Johan Hedberg333ae952015-03-17 13:48:47 +02002476 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2477 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002478 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2479 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002480 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002481 }
2482
2483 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2484 if (!cmd) {
2485 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002486 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002487 }
2488
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002489 hci_req_init(&req, hdev);
2490
Johan Hedberg06199cf2012-02-22 16:37:11 +02002491 memset(&hci_cp, 0, sizeof(hci_cp));
2492
2493 if (val) {
2494 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002495 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002496 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002497 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002498 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002499 }
2500
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002501 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2502 &hci_cp);
2503
2504 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302505 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002506 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002507
Johan Hedberg1de028c2012-02-29 19:55:35 -08002508unlock:
2509 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002510 return err;
2511}
2512
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002513/* This is a helper function to test for pending mgmt commands that can
2514 * cause CoD or EIR HCI commands. We can only allow one such pending
2515 * mgmt command at a time since otherwise we cannot easily track what
2516 * the current values are, will be, and based on that calculate if a new
2517 * HCI command needs to be sent and if yes with what value.
2518 */
2519static bool pending_eir_or_class(struct hci_dev *hdev)
2520{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002521 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002522
2523 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2524 switch (cmd->opcode) {
2525 case MGMT_OP_ADD_UUID:
2526 case MGMT_OP_REMOVE_UUID:
2527 case MGMT_OP_SET_DEV_CLASS:
2528 case MGMT_OP_SET_POWERED:
2529 return true;
2530 }
2531 }
2532
2533 return false;
2534}
2535
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002536static const u8 bluetooth_base_uuid[] = {
2537 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2538 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2539};
2540
2541static u8 get_uuid_size(const u8 *uuid)
2542{
2543 u32 val;
2544
2545 if (memcmp(uuid, bluetooth_base_uuid, 12))
2546 return 128;
2547
2548 val = get_unaligned_le32(&uuid[12]);
2549 if (val > 0xffff)
2550 return 32;
2551
2552 return 16;
2553}
2554
Johan Hedberg92da6092013-03-15 17:06:55 -05002555static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2556{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002557 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002558
2559 hci_dev_lock(hdev);
2560
Johan Hedberg333ae952015-03-17 13:48:47 +02002561 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002562 if (!cmd)
2563 goto unlock;
2564
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002565 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2566 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002567
2568 mgmt_pending_remove(cmd);
2569
2570unlock:
2571 hci_dev_unlock(hdev);
2572}
2573
Marcel Holtmann1904a852015-01-11 13:50:44 -08002574static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002575{
2576 BT_DBG("status 0x%02x", status);
2577
2578 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2579}
2580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002581static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002583 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002584 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002585 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002586 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002587 int err;
2588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002589 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002590
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002591 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002592
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002593 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002594 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2595 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002596 goto failed;
2597 }
2598
Andre Guedes92c4c202012-06-07 19:05:44 -03002599 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002600 if (!uuid) {
2601 err = -ENOMEM;
2602 goto failed;
2603 }
2604
2605 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002606 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002607 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002608
Johan Hedbergde66aa62013-01-27 00:31:27 +02002609 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002610
Johan Hedberg890ea892013-03-15 17:06:52 -05002611 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002612
Johan Hedberg890ea892013-03-15 17:06:52 -05002613 update_class(&req);
2614 update_eir(&req);
2615
Johan Hedberg92da6092013-03-15 17:06:55 -05002616 err = hci_req_run(&req, add_uuid_complete);
2617 if (err < 0) {
2618 if (err != -ENODATA)
2619 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002620
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002621 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2622 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002623 goto failed;
2624 }
2625
2626 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002627 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002628 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002629 goto failed;
2630 }
2631
2632 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002633
2634failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002635 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002636 return err;
2637}
2638
Johan Hedberg24b78d02012-02-23 23:24:30 +02002639static bool enable_service_cache(struct hci_dev *hdev)
2640{
2641 if (!hdev_is_powered(hdev))
2642 return false;
2643
Marcel Holtmann238be782015-03-13 02:11:06 -07002644 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002645 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2646 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002647 return true;
2648 }
2649
2650 return false;
2651}
2652
Marcel Holtmann1904a852015-01-11 13:50:44 -08002653static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002654{
2655 BT_DBG("status 0x%02x", status);
2656
2657 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2658}
2659
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002660static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002661 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002662{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002663 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002664 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002665 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002666 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 -05002667 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002668 int err, found;
2669
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002670 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002671
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002672 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002673
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002674 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002675 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2676 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002677 goto unlock;
2678 }
2679
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002680 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002681 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002682
Johan Hedberg24b78d02012-02-23 23:24:30 +02002683 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002684 err = mgmt_cmd_complete(sk, hdev->id,
2685 MGMT_OP_REMOVE_UUID,
2686 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002687 goto unlock;
2688 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002689
Johan Hedberg9246a862012-02-23 21:33:16 +02002690 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002691 }
2692
2693 found = 0;
2694
Johan Hedberg056341c2013-01-27 00:31:30 +02002695 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002696 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2697 continue;
2698
2699 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002700 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002701 found++;
2702 }
2703
2704 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002705 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2706 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002707 goto unlock;
2708 }
2709
Johan Hedberg9246a862012-02-23 21:33:16 +02002710update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002711 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002712
Johan Hedberg890ea892013-03-15 17:06:52 -05002713 update_class(&req);
2714 update_eir(&req);
2715
Johan Hedberg92da6092013-03-15 17:06:55 -05002716 err = hci_req_run(&req, remove_uuid_complete);
2717 if (err < 0) {
2718 if (err != -ENODATA)
2719 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002720
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002721 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2722 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002723 goto unlock;
2724 }
2725
2726 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002727 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002728 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002729 goto unlock;
2730 }
2731
2732 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002733
2734unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002735 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002736 return err;
2737}
2738
Marcel Holtmann1904a852015-01-11 13:50:44 -08002739static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002740{
2741 BT_DBG("status 0x%02x", status);
2742
2743 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2744}
2745
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002746static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002747 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002748{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002749 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002750 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002751 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002752 int err;
2753
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002754 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002755
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002756 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002757 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2758 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002759
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002760 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002761
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002762 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002763 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2764 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002765 goto unlock;
2766 }
2767
2768 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002769 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2770 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002771 goto unlock;
2772 }
2773
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002774 hdev->major_class = cp->major;
2775 hdev->minor_class = cp->minor;
2776
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002777 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002778 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2779 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002780 goto unlock;
2781 }
2782
Johan Hedberg890ea892013-03-15 17:06:52 -05002783 hci_req_init(&req, hdev);
2784
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002785 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002786 hci_dev_unlock(hdev);
2787 cancel_delayed_work_sync(&hdev->service_cache);
2788 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002789 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002790 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002791
Johan Hedberg890ea892013-03-15 17:06:52 -05002792 update_class(&req);
2793
Johan Hedberg92da6092013-03-15 17:06:55 -05002794 err = hci_req_run(&req, set_class_complete);
2795 if (err < 0) {
2796 if (err != -ENODATA)
2797 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002798
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002799 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2800 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002801 goto unlock;
2802 }
2803
2804 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002805 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002806 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002807 goto unlock;
2808 }
2809
2810 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002811
Johan Hedbergb5235a62012-02-21 14:32:24 +02002812unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002813 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002814 return err;
2815}
2816
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002817static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002818 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002819{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002820 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002821 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2822 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002823 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002824 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002825 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002826
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002827 BT_DBG("request for %s", hdev->name);
2828
2829 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002830 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2831 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002832
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002833 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002834 if (key_count > max_key_count) {
2835 BT_ERR("load_link_keys: too big key_count value %u",
2836 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002837 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2838 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002839 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002840
Johan Hedberg86742e12011-11-07 23:13:38 +02002841 expected_len = sizeof(*cp) + key_count *
2842 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002843 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002844 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002845 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002846 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2847 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002848 }
2849
Johan Hedberg4ae14302013-01-20 14:27:13 +02002850 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002851 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2852 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002853
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002854 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002855 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002856
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002857 for (i = 0; i < key_count; i++) {
2858 struct mgmt_link_key_info *key = &cp->keys[i];
2859
Marcel Holtmann8e991132014-01-10 02:07:25 -08002860 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002861 return mgmt_cmd_status(sk, hdev->id,
2862 MGMT_OP_LOAD_LINK_KEYS,
2863 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002864 }
2865
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002866 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002867
2868 hci_link_keys_clear(hdev);
2869
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002870 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002871 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002872 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002873 changed = hci_dev_test_and_clear_flag(hdev,
2874 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002875
2876 if (changed)
2877 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002878
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002879 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002880 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002881
Johan Hedberg58e92932014-06-24 14:00:26 +03002882 /* Always ignore debug keys and require a new pairing if
2883 * the user wants to use them.
2884 */
2885 if (key->type == HCI_LK_DEBUG_COMBINATION)
2886 continue;
2887
Johan Hedberg7652ff62014-06-24 13:15:49 +03002888 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2889 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002890 }
2891
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002892 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002893
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002894 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002895
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002896 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002897}
2898
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002899static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002900 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002901{
2902 struct mgmt_ev_device_unpaired ev;
2903
2904 bacpy(&ev.addr.bdaddr, bdaddr);
2905 ev.addr.type = addr_type;
2906
2907 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002908 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002909}
2910
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002911static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002912 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002913{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002914 struct mgmt_cp_unpair_device *cp = data;
2915 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002916 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002917 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002918 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002919 int err;
2920
Johan Hedberga8a1d192011-11-10 15:54:38 +02002921 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002922 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2923 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002924
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002925 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002926 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2927 MGMT_STATUS_INVALID_PARAMS,
2928 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002929
Johan Hedberg118da702013-01-20 14:27:20 +02002930 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002931 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2932 MGMT_STATUS_INVALID_PARAMS,
2933 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002934
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002935 hci_dev_lock(hdev);
2936
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002937 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002938 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2939 MGMT_STATUS_NOT_POWERED, &rp,
2940 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002941 goto unlock;
2942 }
2943
Johan Hedberge0b2b272014-02-18 17:14:31 +02002944 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002945 /* If disconnection is requested, then look up the
2946 * connection. If the remote device is connected, it
2947 * will be later used to terminate the link.
2948 *
2949 * Setting it to NULL explicitly will cause no
2950 * termination of the link.
2951 */
2952 if (cp->disconnect)
2953 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2954 &cp->addr.bdaddr);
2955 else
2956 conn = NULL;
2957
Johan Hedberg124f6e32012-02-09 13:50:12 +02002958 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002959 } else {
2960 u8 addr_type;
2961
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002962 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2963 &cp->addr.bdaddr);
2964 if (conn) {
2965 /* Defer clearing up the connection parameters
2966 * until closing to give a chance of keeping
2967 * them if a repairing happens.
2968 */
2969 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2970
2971 /* If disconnection is not requested, then
2972 * clear the connection variable so that the
2973 * link is not terminated.
2974 */
2975 if (!cp->disconnect)
2976 conn = NULL;
2977 }
2978
Johan Hedberge0b2b272014-02-18 17:14:31 +02002979 if (cp->addr.type == BDADDR_LE_PUBLIC)
2980 addr_type = ADDR_LE_DEV_PUBLIC;
2981 else
2982 addr_type = ADDR_LE_DEV_RANDOM;
2983
Johan Hedberga7ec7332014-02-18 17:14:35 +02002984 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2985
Johan Hedberge0b2b272014-02-18 17:14:31 +02002986 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2987 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002988
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002989 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002990 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2991 MGMT_STATUS_NOT_PAIRED, &rp,
2992 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002993 goto unlock;
2994 }
2995
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002996 /* If the connection variable is set, then termination of the
2997 * link is requested.
2998 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002999 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003000 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3001 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003002 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003003 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003004 }
3005
Johan Hedberg124f6e32012-02-09 13:50:12 +02003006 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003007 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003008 if (!cmd) {
3009 err = -ENOMEM;
3010 goto unlock;
3011 }
3012
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003013 cmd->cmd_complete = addr_cmd_complete;
3014
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003015 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003016 dc.reason = 0x13; /* Remote User Terminated Connection */
3017 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3018 if (err < 0)
3019 mgmt_pending_remove(cmd);
3020
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003021unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003022 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003023 return err;
3024}
3025
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003026static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003027 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003028{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003029 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003030 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003031 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003032 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003033 int err;
3034
3035 BT_DBG("");
3036
Johan Hedberg06a63b12013-01-20 14:27:21 +02003037 memset(&rp, 0, sizeof(rp));
3038 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3039 rp.addr.type = cp->addr.type;
3040
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003041 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003042 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3043 MGMT_STATUS_INVALID_PARAMS,
3044 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003045
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003046 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003047
3048 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003049 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3050 MGMT_STATUS_NOT_POWERED, &rp,
3051 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003052 goto failed;
3053 }
3054
Johan Hedberg333ae952015-03-17 13:48:47 +02003055 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003056 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3057 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003058 goto failed;
3059 }
3060
Andre Guedes591f47f2012-04-24 21:02:49 -03003061 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003062 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3063 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003064 else
3065 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003066
Vishal Agarwalf9607272012-06-13 05:32:43 +05303067 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003068 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3069 MGMT_STATUS_NOT_CONNECTED, &rp,
3070 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003071 goto failed;
3072 }
3073
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003074 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003075 if (!cmd) {
3076 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003077 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003078 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003079
Johan Hedbergf5818c22014-12-05 13:36:02 +02003080 cmd->cmd_complete = generic_cmd_complete;
3081
Johan Hedberge3f2f922014-08-18 20:33:33 +03003082 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003083 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003084 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003085
3086failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003087 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003088 return err;
3089}
3090
Andre Guedes57c14772012-04-24 21:02:50 -03003091static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003092{
3093 switch (link_type) {
3094 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003095 switch (addr_type) {
3096 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003097 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003098
Johan Hedberg48264f02011-11-09 13:58:58 +02003099 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003100 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003101 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003102 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003103
Johan Hedberg4c659c32011-11-07 23:13:39 +02003104 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003105 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003106 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003107 }
3108}
3109
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003110static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3111 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003112{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003113 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003114 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003115 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003116 int err;
3117 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003118
3119 BT_DBG("");
3120
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003121 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003122
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003123 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003124 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3125 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003126 goto unlock;
3127 }
3128
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003129 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003130 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3131 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003132 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003133 }
3134
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003135 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003136 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003137 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003138 err = -ENOMEM;
3139 goto unlock;
3140 }
3141
Johan Hedberg2784eb42011-01-21 13:56:35 +02003142 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003143 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003144 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3145 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003146 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003147 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003148 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003149 continue;
3150 i++;
3151 }
3152
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003153 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003154
Johan Hedberg4c659c32011-11-07 23:13:39 +02003155 /* Recalculate length in case of filtered SCO connections, etc */
3156 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003157
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003158 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3159 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003160
Johan Hedberga38528f2011-01-22 06:46:43 +02003161 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003162
3163unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003164 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003165 return err;
3166}
3167
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003168static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003169 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003170{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003171 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003172 int err;
3173
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003174 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003175 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003176 if (!cmd)
3177 return -ENOMEM;
3178
Johan Hedbergd8457692012-02-17 14:24:57 +02003179 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003180 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003181 if (err < 0)
3182 mgmt_pending_remove(cmd);
3183
3184 return err;
3185}
3186
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003187static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003188 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003189{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003190 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003191 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003192 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003193 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003194 int err;
3195
3196 BT_DBG("");
3197
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003198 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003199
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003200 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003201 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3202 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003203 goto failed;
3204 }
3205
Johan Hedbergd8457692012-02-17 14:24:57 +02003206 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003207 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003208 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3209 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003210 goto failed;
3211 }
3212
3213 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003214 struct mgmt_cp_pin_code_neg_reply ncp;
3215
3216 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003217
3218 BT_ERR("PIN code is not 16 bytes long");
3219
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003220 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003221 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003222 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3223 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003224
3225 goto failed;
3226 }
3227
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003228 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003229 if (!cmd) {
3230 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003231 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003232 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003233
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003234 cmd->cmd_complete = addr_cmd_complete;
3235
Johan Hedbergd8457692012-02-17 14:24:57 +02003236 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003237 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003238 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003239
3240 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3241 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003242 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003243
3244failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003245 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003246 return err;
3247}
3248
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003249static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3250 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003251{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003252 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003253
3254 BT_DBG("");
3255
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003256 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003257 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3258 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003259
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003260 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003261
3262 hdev->io_capability = cp->io_capability;
3263
3264 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003265 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003266
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003267 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003268
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003269 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3270 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003271}
3272
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003273static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003274{
3275 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003276 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003277
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003278 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003279 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3280 continue;
3281
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282 if (cmd->user_data != conn)
3283 continue;
3284
3285 return cmd;
3286 }
3287
3288 return NULL;
3289}
3290
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003291static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003292{
3293 struct mgmt_rp_pair_device rp;
3294 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003295 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003296
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003297 bacpy(&rp.addr.bdaddr, &conn->dst);
3298 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003299
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003300 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3301 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003302
3303 /* So we don't get further callbacks for this connection */
3304 conn->connect_cfm_cb = NULL;
3305 conn->security_cfm_cb = NULL;
3306 conn->disconn_cfm_cb = NULL;
3307
David Herrmann76a68ba2013-04-06 20:28:37 +02003308 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003309
3310 /* The device is paired so there is no need to remove
3311 * its connection parameters anymore.
3312 */
3313 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003314
3315 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003316
3317 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003318}
3319
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003320void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3321{
3322 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003323 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003324
3325 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003326 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003327 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003328 mgmt_pending_remove(cmd);
3329 }
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003330}
3331
Johan Hedberge9a416b2011-02-19 12:05:56 -03003332static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3333{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003334 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003335
3336 BT_DBG("status %u", status);
3337
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003338 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003339 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003340 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003341 return;
3342 }
3343
3344 cmd->cmd_complete(cmd, mgmt_status(status));
3345 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003346}
3347
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003348static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303349{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003350 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303351
3352 BT_DBG("status %u", status);
3353
3354 if (!status)
3355 return;
3356
3357 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003358 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303359 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003360 return;
3361 }
3362
3363 cmd->cmd_complete(cmd, mgmt_status(status));
3364 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303365}
3366
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003367static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003368 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003369{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003370 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003371 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003372 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003373 u8 sec_level, auth_type;
3374 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003375 int err;
3376
3377 BT_DBG("");
3378
Szymon Jancf950a30e2013-01-18 12:48:07 +01003379 memset(&rp, 0, sizeof(rp));
3380 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3381 rp.addr.type = cp->addr.type;
3382
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003383 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003384 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3385 MGMT_STATUS_INVALID_PARAMS,
3386 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003387
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003388 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003389 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3390 MGMT_STATUS_INVALID_PARAMS,
3391 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003392
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003393 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003394
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003395 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003396 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3397 MGMT_STATUS_NOT_POWERED, &rp,
3398 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003399 goto unlock;
3400 }
3401
Johan Hedberg55e76b32015-03-10 22:34:40 +02003402 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3403 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3404 MGMT_STATUS_ALREADY_PAIRED, &rp,
3405 sizeof(rp));
3406 goto unlock;
3407 }
3408
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003409 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003410 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003411
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003412 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003413 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3414 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003415 } else {
3416 u8 addr_type;
3417
3418 /* Convert from L2CAP channel address type to HCI address type
3419 */
3420 if (cp->addr.type == BDADDR_LE_PUBLIC)
3421 addr_type = ADDR_LE_DEV_PUBLIC;
3422 else
3423 addr_type = ADDR_LE_DEV_RANDOM;
3424
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003425 /* When pairing a new device, it is expected to remember
3426 * this device for future connections. Adding the connection
3427 * parameter information ahead of time allows tracking
3428 * of the slave preferred values and will speed up any
3429 * further connection establishment.
3430 *
3431 * If connection parameters already exist, then they
3432 * will be kept and this function does nothing.
3433 */
3434 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3435
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003436 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003437 sec_level, HCI_LE_CONN_TIMEOUT,
3438 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003439 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003440
Ville Tervo30e76272011-02-22 16:10:53 -03003441 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003442 int status;
3443
3444 if (PTR_ERR(conn) == -EBUSY)
3445 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003446 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3447 status = MGMT_STATUS_NOT_SUPPORTED;
3448 else if (PTR_ERR(conn) == -ECONNREFUSED)
3449 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003450 else
3451 status = MGMT_STATUS_CONNECT_FAILED;
3452
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003453 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3454 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003455 goto unlock;
3456 }
3457
3458 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003459 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003460 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3461 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003462 goto unlock;
3463 }
3464
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003465 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003466 if (!cmd) {
3467 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003468 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003469 goto unlock;
3470 }
3471
Johan Hedberg04ab2742014-12-05 13:36:04 +02003472 cmd->cmd_complete = pairing_complete;
3473
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003474 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003475 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003476 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003477 conn->security_cfm_cb = pairing_complete_cb;
3478 conn->disconn_cfm_cb = pairing_complete_cb;
3479 } else {
3480 conn->connect_cfm_cb = le_pairing_complete_cb;
3481 conn->security_cfm_cb = le_pairing_complete_cb;
3482 conn->disconn_cfm_cb = le_pairing_complete_cb;
3483 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003484
Johan Hedberge9a416b2011-02-19 12:05:56 -03003485 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003486 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003487
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003488 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003489 hci_conn_security(conn, sec_level, auth_type, true)) {
3490 cmd->cmd_complete(cmd, 0);
3491 mgmt_pending_remove(cmd);
3492 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003493
3494 err = 0;
3495
3496unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003497 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003498 return err;
3499}
3500
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003501static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3502 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003503{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003504 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003505 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003506 struct hci_conn *conn;
3507 int err;
3508
3509 BT_DBG("");
3510
Johan Hedberg28424702012-02-02 04:02:29 +02003511 hci_dev_lock(hdev);
3512
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003513 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003514 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3515 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003516 goto unlock;
3517 }
3518
Johan Hedberg333ae952015-03-17 13:48:47 +02003519 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003520 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003521 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3522 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003523 goto unlock;
3524 }
3525
3526 conn = cmd->user_data;
3527
3528 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003529 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3530 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003531 goto unlock;
3532 }
3533
Johan Hedberga511b352014-12-11 21:45:45 +02003534 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3535 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003536
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003537 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3538 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003539unlock:
3540 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003541 return err;
3542}
3543
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003544static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003545 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003546 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003547{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003548 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003549 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003550 int err;
3551
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003552 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003553
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003554 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003555 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3556 MGMT_STATUS_NOT_POWERED, addr,
3557 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003558 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003559 }
3560
Johan Hedberg1707c602013-03-15 17:07:15 -05003561 if (addr->type == BDADDR_BREDR)
3562 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003563 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003564 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003565
Johan Hedberg272d90d2012-02-09 15:26:12 +02003566 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003567 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3568 MGMT_STATUS_NOT_CONNECTED, addr,
3569 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003570 goto done;
3571 }
3572
Johan Hedberg1707c602013-03-15 17:07:15 -05003573 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003574 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003575 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003576 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3577 MGMT_STATUS_SUCCESS, addr,
3578 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003579 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003580 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3581 MGMT_STATUS_FAILED, addr,
3582 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003583
Brian Gix47c15e22011-11-16 13:53:14 -08003584 goto done;
3585 }
3586
Johan Hedberg1707c602013-03-15 17:07:15 -05003587 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003588 if (!cmd) {
3589 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003590 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003591 }
3592
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003593 cmd->cmd_complete = addr_cmd_complete;
3594
Brian Gix0df4c182011-11-16 13:53:13 -08003595 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003596 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3597 struct hci_cp_user_passkey_reply cp;
3598
Johan Hedberg1707c602013-03-15 17:07:15 -05003599 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003600 cp.passkey = passkey;
3601 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3602 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003603 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3604 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003605
Johan Hedberga664b5b2011-02-19 12:06:02 -03003606 if (err < 0)
3607 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003608
Brian Gix0df4c182011-11-16 13:53:13 -08003609done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003610 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003611 return err;
3612}
3613
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303614static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3615 void *data, u16 len)
3616{
3617 struct mgmt_cp_pin_code_neg_reply *cp = data;
3618
3619 BT_DBG("");
3620
Johan Hedberg1707c602013-03-15 17:07:15 -05003621 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303622 MGMT_OP_PIN_CODE_NEG_REPLY,
3623 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3624}
3625
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003626static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3627 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003628{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003629 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003630
3631 BT_DBG("");
3632
3633 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003634 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3635 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003636
Johan Hedberg1707c602013-03-15 17:07:15 -05003637 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003638 MGMT_OP_USER_CONFIRM_REPLY,
3639 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003640}
3641
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003642static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003643 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003644{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003645 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003646
3647 BT_DBG("");
3648
Johan Hedberg1707c602013-03-15 17:07:15 -05003649 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003650 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3651 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003652}
3653
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003654static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3655 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003656{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003657 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003658
3659 BT_DBG("");
3660
Johan Hedberg1707c602013-03-15 17:07:15 -05003661 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003662 MGMT_OP_USER_PASSKEY_REPLY,
3663 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003664}
3665
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003666static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003667 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003668{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003669 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003670
3671 BT_DBG("");
3672
Johan Hedberg1707c602013-03-15 17:07:15 -05003673 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003674 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3675 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003676}
3677
Johan Hedberg13928972013-03-15 17:07:00 -05003678static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003679{
Johan Hedberg13928972013-03-15 17:07:00 -05003680 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003681 struct hci_cp_write_local_name cp;
3682
Johan Hedberg13928972013-03-15 17:07:00 -05003683 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003684
Johan Hedberg890ea892013-03-15 17:06:52 -05003685 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003686}
3687
Marcel Holtmann1904a852015-01-11 13:50:44 -08003688static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003689{
3690 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003691 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003692
3693 BT_DBG("status 0x%02x", status);
3694
3695 hci_dev_lock(hdev);
3696
Johan Hedberg333ae952015-03-17 13:48:47 +02003697 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003698 if (!cmd)
3699 goto unlock;
3700
3701 cp = cmd->param;
3702
3703 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003704 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3705 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003706 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003707 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3708 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003709
3710 mgmt_pending_remove(cmd);
3711
3712unlock:
3713 hci_dev_unlock(hdev);
3714}
3715
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003716static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003717 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003718{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003719 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003720 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003721 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003722 int err;
3723
3724 BT_DBG("");
3725
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003726 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003727
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003728 /* If the old values are the same as the new ones just return a
3729 * direct command complete event.
3730 */
3731 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3732 !memcmp(hdev->short_name, cp->short_name,
3733 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003734 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3735 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003736 goto failed;
3737 }
3738
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003739 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003740
Johan Hedbergb5235a62012-02-21 14:32:24 +02003741 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003742 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003743
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003744 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3745 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003746 if (err < 0)
3747 goto failed;
3748
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003749 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3750 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003751
Johan Hedbergb5235a62012-02-21 14:32:24 +02003752 goto failed;
3753 }
3754
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003755 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003756 if (!cmd) {
3757 err = -ENOMEM;
3758 goto failed;
3759 }
3760
Johan Hedberg13928972013-03-15 17:07:00 -05003761 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3762
Johan Hedberg890ea892013-03-15 17:06:52 -05003763 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003764
3765 if (lmp_bredr_capable(hdev)) {
3766 update_name(&req);
3767 update_eir(&req);
3768 }
3769
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003770 /* The name is stored in the scan response data and so
3771 * no need to udpate the advertising data here.
3772 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003773 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003774 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003775
Johan Hedberg13928972013-03-15 17:07:00 -05003776 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003777 if (err < 0)
3778 mgmt_pending_remove(cmd);
3779
3780failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003781 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003782 return err;
3783}
3784
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003785static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003786 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003787{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003788 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003789 int err;
3790
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003791 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003792
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003793 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003794
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003795 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003796 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3797 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003798 goto unlock;
3799 }
3800
Andre Guedes9a1a1992012-07-24 15:03:48 -03003801 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003802 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3803 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003804 goto unlock;
3805 }
3806
Johan Hedberg333ae952015-03-17 13:48:47 +02003807 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003808 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3809 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003810 goto unlock;
3811 }
3812
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003813 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003814 if (!cmd) {
3815 err = -ENOMEM;
3816 goto unlock;
3817 }
3818
Johan Hedberg710f11c2014-05-26 11:21:22 +03003819 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003820 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3821 0, NULL);
3822 else
3823 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3824
Szymon Jancc35938b2011-03-22 13:12:21 +01003825 if (err < 0)
3826 mgmt_pending_remove(cmd);
3827
3828unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003829 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003830 return err;
3831}
3832
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003833static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003834 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003835{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003836 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003837 int err;
3838
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003839 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003840
Johan Hedberg5d57e792015-01-23 10:10:38 +02003841 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003842 return mgmt_cmd_complete(sk, hdev->id,
3843 MGMT_OP_ADD_REMOTE_OOB_DATA,
3844 MGMT_STATUS_INVALID_PARAMS,
3845 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003846
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003847 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003848
Marcel Holtmannec109112014-01-10 02:07:30 -08003849 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3850 struct mgmt_cp_add_remote_oob_data *cp = data;
3851 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003852
Johan Hedbergc19a4952014-11-17 20:52:19 +02003853 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003854 err = mgmt_cmd_complete(sk, hdev->id,
3855 MGMT_OP_ADD_REMOTE_OOB_DATA,
3856 MGMT_STATUS_INVALID_PARAMS,
3857 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003858 goto unlock;
3859 }
3860
Marcel Holtmannec109112014-01-10 02:07:30 -08003861 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003862 cp->addr.type, cp->hash,
3863 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003864 if (err < 0)
3865 status = MGMT_STATUS_FAILED;
3866 else
3867 status = MGMT_STATUS_SUCCESS;
3868
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003869 err = mgmt_cmd_complete(sk, hdev->id,
3870 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3871 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003872 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3873 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003874 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003875 u8 status;
3876
Johan Hedberg86df9202014-10-26 20:52:27 +01003877 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003878 /* Enforce zero-valued 192-bit parameters as
3879 * long as legacy SMP OOB isn't implemented.
3880 */
3881 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3882 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003883 err = mgmt_cmd_complete(sk, hdev->id,
3884 MGMT_OP_ADD_REMOTE_OOB_DATA,
3885 MGMT_STATUS_INVALID_PARAMS,
3886 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003887 goto unlock;
3888 }
3889
Johan Hedberg86df9202014-10-26 20:52:27 +01003890 rand192 = NULL;
3891 hash192 = NULL;
3892 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003893 /* In case one of the P-192 values is set to zero,
3894 * then just disable OOB data for P-192.
3895 */
3896 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3897 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3898 rand192 = NULL;
3899 hash192 = NULL;
3900 } else {
3901 rand192 = cp->rand192;
3902 hash192 = cp->hash192;
3903 }
3904 }
3905
3906 /* In case one of the P-256 values is set to zero, then just
3907 * disable OOB data for P-256.
3908 */
3909 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3910 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3911 rand256 = NULL;
3912 hash256 = NULL;
3913 } else {
3914 rand256 = cp->rand256;
3915 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003916 }
3917
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003918 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003919 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003920 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003921 if (err < 0)
3922 status = MGMT_STATUS_FAILED;
3923 else
3924 status = MGMT_STATUS_SUCCESS;
3925
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003926 err = mgmt_cmd_complete(sk, hdev->id,
3927 MGMT_OP_ADD_REMOTE_OOB_DATA,
3928 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003929 } else {
3930 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003931 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3932 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003933 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003934
Johan Hedbergc19a4952014-11-17 20:52:19 +02003935unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003936 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003937 return err;
3938}
3939
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003940static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003941 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003942{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003943 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003944 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003945 int err;
3946
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003947 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003948
Johan Hedbergc19a4952014-11-17 20:52:19 +02003949 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003950 return mgmt_cmd_complete(sk, hdev->id,
3951 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3952 MGMT_STATUS_INVALID_PARAMS,
3953 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003954
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003955 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003956
Johan Hedbergeedbd582014-11-15 09:34:23 +02003957 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3958 hci_remote_oob_data_clear(hdev);
3959 status = MGMT_STATUS_SUCCESS;
3960 goto done;
3961 }
3962
Johan Hedberg6928a922014-10-26 20:46:09 +01003963 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003964 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003965 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003966 else
Szymon Janca6785be2012-12-13 15:11:21 +01003967 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003968
Johan Hedbergeedbd582014-11-15 09:34:23 +02003969done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003970 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3971 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003972
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003973 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003974 return err;
3975}
3976
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003977static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
3978{
3979 struct hci_dev *hdev = req->hdev;
3980 struct hci_cp_inquiry cp;
3981 /* General inquiry access code (GIAC) */
3982 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3983
3984 *status = mgmt_bredr_support(hdev);
3985 if (*status)
3986 return false;
3987
3988 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
3989 *status = MGMT_STATUS_BUSY;
3990 return false;
3991 }
3992
3993 hci_inquiry_cache_flush(hdev);
3994
3995 memset(&cp, 0, sizeof(cp));
3996 memcpy(&cp.lap, lap, sizeof(cp.lap));
3997 cp.length = DISCOV_BREDR_INQUIRY_LEN;
3998
3999 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4000
4001 return true;
4002}
4003
4004static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004005{
Marcel Holtmann80190442014-12-04 11:36:36 +01004006 struct hci_dev *hdev = req->hdev;
4007 struct hci_cp_le_set_scan_param param_cp;
4008 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004009 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004010 int err;
4011
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004012 *status = mgmt_le_support(hdev);
4013 if (*status)
4014 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004015
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004016 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4017 /* Don't let discovery abort an outgoing connection attempt
4018 * that's using directed advertising.
4019 */
4020 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4021 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004022 return false;
4023 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004024
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004025 disable_advertising(req);
4026 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004027
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004028 /* If controller is scanning, it means the background scanning is
4029 * running. Thus, we should temporarily stop it in order to set the
4030 * discovery scanning parameters.
4031 */
4032 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4033 hci_req_add_le_scan_disable(req);
4034
4035 /* All active scans will be done with either a resolvable private
4036 * address (when privacy feature has been enabled) or non-resolvable
4037 * private address.
4038 */
4039 err = hci_update_random_address(req, true, &own_addr_type);
4040 if (err < 0) {
4041 *status = MGMT_STATUS_FAILED;
4042 return false;
4043 }
4044
4045 memset(&param_cp, 0, sizeof(param_cp));
4046 param_cp.type = LE_SCAN_ACTIVE;
4047 param_cp.interval = cpu_to_le16(interval);
4048 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4049 param_cp.own_address_type = own_addr_type;
4050
4051 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4052 &param_cp);
4053
4054 memset(&enable_cp, 0, sizeof(enable_cp));
4055 enable_cp.enable = LE_SCAN_ENABLE;
4056 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4057
4058 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4059 &enable_cp);
4060
4061 return true;
4062}
4063
4064static bool trigger_discovery(struct hci_request *req, u8 *status)
4065{
4066 struct hci_dev *hdev = req->hdev;
4067
4068 switch (hdev->discovery.type) {
4069 case DISCOV_TYPE_BREDR:
4070 if (!trigger_bredr_inquiry(req, status))
4071 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004072 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004073
Marcel Holtmann80190442014-12-04 11:36:36 +01004074 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004075 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4076 &hdev->quirks)) {
4077 /* During simultaneous discovery, we double LE scan
4078 * interval. We must leave some time for the controller
4079 * to do BR/EDR inquiry.
4080 */
4081 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4082 status))
4083 return false;
4084
4085 if (!trigger_bredr_inquiry(req, status))
4086 return false;
4087
4088 return true;
4089 }
4090
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004091 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004092 *status = MGMT_STATUS_NOT_SUPPORTED;
4093 return false;
4094 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004095 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004096
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004097 case DISCOV_TYPE_LE:
4098 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004099 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004100 break;
4101
4102 default:
4103 *status = MGMT_STATUS_INVALID_PARAMS;
4104 return false;
4105 }
4106
4107 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004108}
4109
Marcel Holtmann1904a852015-01-11 13:50:44 -08004110static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4111 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004112{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004113 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004114 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004115
Andre Guedes7c307722013-04-30 15:29:28 -03004116 BT_DBG("status %d", status);
4117
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004118 hci_dev_lock(hdev);
4119
Johan Hedberg333ae952015-03-17 13:48:47 +02004120 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004121 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004122 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004123
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004124 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004125 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004126 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004127 }
4128
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004129 if (status) {
4130 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4131 goto unlock;
4132 }
4133
Andre Guedes7c307722013-04-30 15:29:28 -03004134 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004135
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004136 /* If the scan involves LE scan, pick proper timeout to schedule
4137 * hdev->le_scan_disable that will stop it.
4138 */
Andre Guedes7c307722013-04-30 15:29:28 -03004139 switch (hdev->discovery.type) {
4140 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004141 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004142 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004143 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004144 /* When running simultaneous discovery, the LE scanning time
4145 * should occupy the whole discovery time sine BR/EDR inquiry
4146 * and LE scanning are scheduled by the controller.
4147 *
4148 * For interleaving discovery in comparison, BR/EDR inquiry
4149 * and LE scanning are done sequentially with separate
4150 * timeouts.
4151 */
4152 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4153 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4154 else
4155 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004156 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004157 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004158 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004159 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004160 default:
4161 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004162 timeout = 0;
4163 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004164 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004165
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004166 if (timeout) {
4167 /* When service discovery is used and the controller has
4168 * a strict duplicate filter, it is important to remember
4169 * the start and duration of the scan. This is required
4170 * for restarting scanning during the discovery phase.
4171 */
4172 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4173 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004174 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004175 hdev->discovery.scan_start = jiffies;
4176 hdev->discovery.scan_duration = timeout;
4177 }
4178
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004179 queue_delayed_work(hdev->workqueue,
4180 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004181 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004182
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004183unlock:
4184 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004185}
4186
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004187static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004188 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004189{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004190 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004191 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004192 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004193 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004194 int err;
4195
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004196 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004197
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004198 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004199
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004200 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004201 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4202 MGMT_STATUS_NOT_POWERED,
4203 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004204 goto failed;
4205 }
4206
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004207 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004208 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004209 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4210 MGMT_STATUS_BUSY, &cp->type,
4211 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004212 goto failed;
4213 }
4214
Johan Hedberg2922a942014-12-05 13:36:06 +02004215 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004216 if (!cmd) {
4217 err = -ENOMEM;
4218 goto failed;
4219 }
4220
Johan Hedberg2922a942014-12-05 13:36:06 +02004221 cmd->cmd_complete = generic_cmd_complete;
4222
Marcel Holtmann22078802014-12-05 11:45:22 +01004223 /* Clear the discovery filter first to free any previously
4224 * allocated memory for the UUID list.
4225 */
4226 hci_discovery_filter_clear(hdev);
4227
Andre Guedes4aab14e2012-02-17 20:39:36 -03004228 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004229 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004230
Andre Guedes7c307722013-04-30 15:29:28 -03004231 hci_req_init(&req, hdev);
4232
Marcel Holtmann80190442014-12-04 11:36:36 +01004233 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004234 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4235 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004236 mgmt_pending_remove(cmd);
4237 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004238 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004239
Andre Guedes7c307722013-04-30 15:29:28 -03004240 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004241 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004242 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004243 goto failed;
4244 }
4245
4246 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004247
4248failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004249 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004250 return err;
4251}
4252
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004253static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4254 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004255{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004256 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4257 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004258}
4259
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004260static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4261 void *data, u16 len)
4262{
4263 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004264 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004265 struct hci_request req;
4266 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4267 u16 uuid_count, expected_len;
4268 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004269 int err;
4270
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004271 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004272
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004273 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004274
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004275 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004276 err = mgmt_cmd_complete(sk, hdev->id,
4277 MGMT_OP_START_SERVICE_DISCOVERY,
4278 MGMT_STATUS_NOT_POWERED,
4279 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004280 goto failed;
4281 }
4282
4283 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004284 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004285 err = mgmt_cmd_complete(sk, hdev->id,
4286 MGMT_OP_START_SERVICE_DISCOVERY,
4287 MGMT_STATUS_BUSY, &cp->type,
4288 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004289 goto failed;
4290 }
4291
4292 uuid_count = __le16_to_cpu(cp->uuid_count);
4293 if (uuid_count > max_uuid_count) {
4294 BT_ERR("service_discovery: too big uuid_count value %u",
4295 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004296 err = mgmt_cmd_complete(sk, hdev->id,
4297 MGMT_OP_START_SERVICE_DISCOVERY,
4298 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4299 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004300 goto failed;
4301 }
4302
4303 expected_len = sizeof(*cp) + uuid_count * 16;
4304 if (expected_len != len) {
4305 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4306 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004307 err = mgmt_cmd_complete(sk, hdev->id,
4308 MGMT_OP_START_SERVICE_DISCOVERY,
4309 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4310 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004311 goto failed;
4312 }
4313
4314 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004315 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004316 if (!cmd) {
4317 err = -ENOMEM;
4318 goto failed;
4319 }
4320
Johan Hedberg2922a942014-12-05 13:36:06 +02004321 cmd->cmd_complete = service_discovery_cmd_complete;
4322
Marcel Holtmann22078802014-12-05 11:45:22 +01004323 /* Clear the discovery filter first to free any previously
4324 * allocated memory for the UUID list.
4325 */
4326 hci_discovery_filter_clear(hdev);
4327
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004328 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004329 hdev->discovery.type = cp->type;
4330 hdev->discovery.rssi = cp->rssi;
4331 hdev->discovery.uuid_count = uuid_count;
4332
4333 if (uuid_count > 0) {
4334 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4335 GFP_KERNEL);
4336 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004337 err = mgmt_cmd_complete(sk, hdev->id,
4338 MGMT_OP_START_SERVICE_DISCOVERY,
4339 MGMT_STATUS_FAILED,
4340 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004341 mgmt_pending_remove(cmd);
4342 goto failed;
4343 }
4344 }
4345
4346 hci_req_init(&req, hdev);
4347
4348 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004349 err = mgmt_cmd_complete(sk, hdev->id,
4350 MGMT_OP_START_SERVICE_DISCOVERY,
4351 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004352 mgmt_pending_remove(cmd);
4353 goto failed;
4354 }
4355
4356 err = hci_req_run(&req, start_discovery_complete);
4357 if (err < 0) {
4358 mgmt_pending_remove(cmd);
4359 goto failed;
4360 }
4361
4362 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4363
4364failed:
4365 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004366 return err;
4367}
4368
Marcel Holtmann1904a852015-01-11 13:50:44 -08004369static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004370{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004371 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004372
Andre Guedes0e05bba2013-04-30 15:29:33 -03004373 BT_DBG("status %d", status);
4374
4375 hci_dev_lock(hdev);
4376
Johan Hedberg333ae952015-03-17 13:48:47 +02004377 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004378 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004379 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004380 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004381 }
4382
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004383 if (!status)
4384 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004385
Andre Guedes0e05bba2013-04-30 15:29:33 -03004386 hci_dev_unlock(hdev);
4387}
4388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004389static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004390 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004391{
Johan Hedbergd9306502012-02-20 23:25:18 +02004392 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004393 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004394 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004395 int err;
4396
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004397 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004398
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004399 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004400
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004401 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004402 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4403 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4404 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004405 goto unlock;
4406 }
4407
4408 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004409 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4410 MGMT_STATUS_INVALID_PARAMS,
4411 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004412 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004413 }
4414
Johan Hedberg2922a942014-12-05 13:36:06 +02004415 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004416 if (!cmd) {
4417 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004418 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004419 }
4420
Johan Hedberg2922a942014-12-05 13:36:06 +02004421 cmd->cmd_complete = generic_cmd_complete;
4422
Andre Guedes0e05bba2013-04-30 15:29:33 -03004423 hci_req_init(&req, hdev);
4424
Johan Hedberg21a60d32014-06-10 14:05:58 +03004425 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004426
Johan Hedberg21a60d32014-06-10 14:05:58 +03004427 err = hci_req_run(&req, stop_discovery_complete);
4428 if (!err) {
4429 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004430 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004431 }
4432
Johan Hedberg21a60d32014-06-10 14:05:58 +03004433 mgmt_pending_remove(cmd);
4434
4435 /* If no HCI commands were sent we're done */
4436 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004437 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4438 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004439 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4440 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004441
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004442unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004443 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004444 return err;
4445}
4446
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004447static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004448 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004449{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004450 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004451 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004452 int err;
4453
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004454 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004455
Johan Hedberg561aafb2012-01-04 13:31:59 +02004456 hci_dev_lock(hdev);
4457
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004458 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004459 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4460 MGMT_STATUS_FAILED, &cp->addr,
4461 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004462 goto failed;
4463 }
4464
Johan Hedberga198e7b2012-02-17 14:27:06 +02004465 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004466 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004467 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4468 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4469 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004470 goto failed;
4471 }
4472
4473 if (cp->name_known) {
4474 e->name_state = NAME_KNOWN;
4475 list_del(&e->list);
4476 } else {
4477 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004478 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004479 }
4480
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004481 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4482 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004483
4484failed:
4485 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004486 return err;
4487}
4488
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004489static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004490 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004491{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004492 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004493 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004494 int err;
4495
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004496 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004497
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004498 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004499 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4500 MGMT_STATUS_INVALID_PARAMS,
4501 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004502
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004503 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004504
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004505 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4506 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004507 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004508 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004509 goto done;
4510 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004511
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004512 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4513 sk);
4514 status = MGMT_STATUS_SUCCESS;
4515
4516done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004517 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4518 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004519
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004520 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004521
4522 return err;
4523}
4524
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004525static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004526 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004527{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004528 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004529 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004530 int err;
4531
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004532 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004533
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004534 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004535 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4536 MGMT_STATUS_INVALID_PARAMS,
4537 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004538
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004539 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004540
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004541 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4542 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004543 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004544 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004545 goto done;
4546 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004547
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004548 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4549 sk);
4550 status = MGMT_STATUS_SUCCESS;
4551
4552done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004553 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4554 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004555
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004556 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004557
4558 return err;
4559}
4560
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004561static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4562 u16 len)
4563{
4564 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004565 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004566 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004567 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004568
4569 BT_DBG("%s", hdev->name);
4570
Szymon Jancc72d4b82012-03-16 16:02:57 +01004571 source = __le16_to_cpu(cp->source);
4572
4573 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004574 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4575 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004576
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004577 hci_dev_lock(hdev);
4578
Szymon Jancc72d4b82012-03-16 16:02:57 +01004579 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004580 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4581 hdev->devid_product = __le16_to_cpu(cp->product);
4582 hdev->devid_version = __le16_to_cpu(cp->version);
4583
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004584 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4585 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004586
Johan Hedberg890ea892013-03-15 17:06:52 -05004587 hci_req_init(&req, hdev);
4588 update_eir(&req);
4589 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004590
4591 hci_dev_unlock(hdev);
4592
4593 return err;
4594}
4595
Arman Uguray24b4f382015-03-23 15:57:12 -07004596static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4597 u16 opcode)
4598{
4599 BT_DBG("status %d", status);
4600}
4601
Marcel Holtmann1904a852015-01-11 13:50:44 -08004602static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4603 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004604{
4605 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004606 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004607
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304608 hci_dev_lock(hdev);
4609
Johan Hedberg4375f102013-09-25 13:26:10 +03004610 if (status) {
4611 u8 mgmt_err = mgmt_status(status);
4612
4613 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4614 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304615 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004616 }
4617
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004618 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004619 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004620 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004621 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004622
Johan Hedberg4375f102013-09-25 13:26:10 +03004623 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4624 &match);
4625
4626 new_settings(hdev, match.sk);
4627
4628 if (match.sk)
4629 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304630
Arman Uguray24b4f382015-03-23 15:57:12 -07004631 /* If "Set Advertising" was just disabled and instance advertising was
4632 * set up earlier, then enable the advertising instance.
4633 */
4634 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4635 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4636 goto unlock;
4637
4638 hci_req_init(&req, hdev);
4639
4640 update_adv_data(&req);
4641 enable_advertising(&req);
4642
4643 if (hci_req_run(&req, enable_advertising_instance) < 0)
4644 BT_ERR("Failed to re-configure advertising");
4645
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304646unlock:
4647 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004648}
4649
Marcel Holtmann21b51872013-10-10 09:47:53 -07004650static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4651 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004652{
4653 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004654 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004655 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004656 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004657 int err;
4658
4659 BT_DBG("request for %s", hdev->name);
4660
Johan Hedberge6fe7982013-10-02 15:45:22 +03004661 status = mgmt_le_support(hdev);
4662 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004663 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4664 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004665
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004666 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004667 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4668 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004669
4670 hci_dev_lock(hdev);
4671
4672 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004673
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004674 /* The following conditions are ones which mean that we should
4675 * not do any HCI communication but directly send a mgmt
4676 * response to user space (after toggling the flag if
4677 * necessary).
4678 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004679 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004680 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4681 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004682 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004683 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004684 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004685 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004686
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004687 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004688 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004689 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004690 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004691 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004692 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004693 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004694 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004695 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004696 }
4697
4698 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4699 if (err < 0)
4700 goto unlock;
4701
4702 if (changed)
4703 err = new_settings(hdev, sk);
4704
4705 goto unlock;
4706 }
4707
Johan Hedberg333ae952015-03-17 13:48:47 +02004708 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4709 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004710 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4711 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004712 goto unlock;
4713 }
4714
4715 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4716 if (!cmd) {
4717 err = -ENOMEM;
4718 goto unlock;
4719 }
4720
4721 hci_req_init(&req, hdev);
4722
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004723 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004724 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004725 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004726 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004727
Arman Uguray24b4f382015-03-23 15:57:12 -07004728 if (val) {
4729 /* Switch to instance "0" for the Set Advertising setting. */
4730 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004731 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004732 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004733 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004734 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004735 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004736
4737 err = hci_req_run(&req, set_advertising_complete);
4738 if (err < 0)
4739 mgmt_pending_remove(cmd);
4740
4741unlock:
4742 hci_dev_unlock(hdev);
4743 return err;
4744}
4745
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004746static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4747 void *data, u16 len)
4748{
4749 struct mgmt_cp_set_static_address *cp = data;
4750 int err;
4751
4752 BT_DBG("%s", hdev->name);
4753
Marcel Holtmann62af4442013-10-02 22:10:32 -07004754 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004755 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4756 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004757
4758 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004759 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4760 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004761
4762 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4763 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004764 return mgmt_cmd_status(sk, hdev->id,
4765 MGMT_OP_SET_STATIC_ADDRESS,
4766 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004767
4768 /* Two most significant bits shall be set */
4769 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004770 return mgmt_cmd_status(sk, hdev->id,
4771 MGMT_OP_SET_STATIC_ADDRESS,
4772 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004773 }
4774
4775 hci_dev_lock(hdev);
4776
4777 bacpy(&hdev->static_addr, &cp->bdaddr);
4778
Marcel Holtmann93690c22015-03-06 10:11:21 -08004779 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4780 if (err < 0)
4781 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004782
Marcel Holtmann93690c22015-03-06 10:11:21 -08004783 err = new_settings(hdev, sk);
4784
4785unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004786 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004787 return err;
4788}
4789
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004790static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4791 void *data, u16 len)
4792{
4793 struct mgmt_cp_set_scan_params *cp = data;
4794 __u16 interval, window;
4795 int err;
4796
4797 BT_DBG("%s", hdev->name);
4798
4799 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004800 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4801 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004802
4803 interval = __le16_to_cpu(cp->interval);
4804
4805 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004806 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4807 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004808
4809 window = __le16_to_cpu(cp->window);
4810
4811 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004812 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4813 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004814
Marcel Holtmann899e1072013-10-14 09:55:32 -07004815 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004816 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4817 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004818
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004819 hci_dev_lock(hdev);
4820
4821 hdev->le_scan_interval = interval;
4822 hdev->le_scan_window = window;
4823
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004824 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4825 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004826
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004827 /* If background scan is running, restart it so new parameters are
4828 * loaded.
4829 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004830 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004831 hdev->discovery.state == DISCOVERY_STOPPED) {
4832 struct hci_request req;
4833
4834 hci_req_init(&req, hdev);
4835
4836 hci_req_add_le_scan_disable(&req);
4837 hci_req_add_le_passive_scan(&req);
4838
4839 hci_req_run(&req, NULL);
4840 }
4841
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004842 hci_dev_unlock(hdev);
4843
4844 return err;
4845}
4846
Marcel Holtmann1904a852015-01-11 13:50:44 -08004847static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4848 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004849{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004850 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004851
4852 BT_DBG("status 0x%02x", status);
4853
4854 hci_dev_lock(hdev);
4855
Johan Hedberg333ae952015-03-17 13:48:47 +02004856 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004857 if (!cmd)
4858 goto unlock;
4859
4860 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004861 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4862 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004863 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004864 struct mgmt_mode *cp = cmd->param;
4865
4866 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004867 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004868 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004869 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004870
Johan Hedberg33e38b32013-03-15 17:07:05 -05004871 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4872 new_settings(hdev, cmd->sk);
4873 }
4874
4875 mgmt_pending_remove(cmd);
4876
4877unlock:
4878 hci_dev_unlock(hdev);
4879}
4880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004881static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004882 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004883{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004884 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004885 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004886 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004887 int err;
4888
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004889 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004890
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004891 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004892 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004893 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4894 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004895
Johan Hedberga7e80f22013-01-09 16:05:19 +02004896 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004897 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4898 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004899
Antti Julkuf6422ec2011-06-22 13:11:56 +03004900 hci_dev_lock(hdev);
4901
Johan Hedberg333ae952015-03-17 13:48:47 +02004902 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004903 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4904 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004905 goto unlock;
4906 }
4907
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004908 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004909 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4910 hdev);
4911 goto unlock;
4912 }
4913
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004914 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004915 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004916 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4917 hdev);
4918 new_settings(hdev, sk);
4919 goto unlock;
4920 }
4921
Johan Hedberg33e38b32013-03-15 17:07:05 -05004922 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4923 data, len);
4924 if (!cmd) {
4925 err = -ENOMEM;
4926 goto unlock;
4927 }
4928
4929 hci_req_init(&req, hdev);
4930
Johan Hedberg406d7802013-03-15 17:07:09 -05004931 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004932
4933 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004934 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004935 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4936 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004937 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004938 }
4939
Johan Hedberg33e38b32013-03-15 17:07:05 -05004940unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004941 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004942
Antti Julkuf6422ec2011-06-22 13:11:56 +03004943 return err;
4944}
4945
Marcel Holtmann1904a852015-01-11 13:50:44 -08004946static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004947{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004948 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004949
4950 BT_DBG("status 0x%02x", status);
4951
4952 hci_dev_lock(hdev);
4953
Johan Hedberg333ae952015-03-17 13:48:47 +02004954 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004955 if (!cmd)
4956 goto unlock;
4957
4958 if (status) {
4959 u8 mgmt_err = mgmt_status(status);
4960
4961 /* We need to restore the flag if related HCI commands
4962 * failed.
4963 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004964 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004965
Johan Hedberga69e8372015-03-06 21:08:53 +02004966 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004967 } else {
4968 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4969 new_settings(hdev, cmd->sk);
4970 }
4971
4972 mgmt_pending_remove(cmd);
4973
4974unlock:
4975 hci_dev_unlock(hdev);
4976}
4977
4978static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4979{
4980 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004981 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004982 struct hci_request req;
4983 int err;
4984
4985 BT_DBG("request for %s", hdev->name);
4986
4987 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004988 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4989 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004990
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004991 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004992 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4993 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004994
4995 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004996 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4997 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004998
4999 hci_dev_lock(hdev);
5000
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005001 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005002 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5003 goto unlock;
5004 }
5005
5006 if (!hdev_is_powered(hdev)) {
5007 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005008 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5009 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5010 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5011 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5012 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005013 }
5014
Marcel Holtmannce05d602015-03-13 02:11:03 -07005015 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005016
5017 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5018 if (err < 0)
5019 goto unlock;
5020
5021 err = new_settings(hdev, sk);
5022 goto unlock;
5023 }
5024
5025 /* Reject disabling when powered on */
5026 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005027 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5028 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005029 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005030 } else {
5031 /* When configuring a dual-mode controller to operate
5032 * with LE only and using a static address, then switching
5033 * BR/EDR back on is not allowed.
5034 *
5035 * Dual-mode controllers shall operate with the public
5036 * address as its identity address for BR/EDR and LE. So
5037 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005038 *
5039 * The same restrictions applies when secure connections
5040 * has been enabled. For BR/EDR this is a controller feature
5041 * while for LE it is a host stack feature. This means that
5042 * switching BR/EDR back on when secure connections has been
5043 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005044 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005045 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005046 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005047 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005048 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5049 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005050 goto unlock;
5051 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005052 }
5053
Johan Hedberg333ae952015-03-17 13:48:47 +02005054 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005055 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5056 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005057 goto unlock;
5058 }
5059
5060 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5061 if (!cmd) {
5062 err = -ENOMEM;
5063 goto unlock;
5064 }
5065
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005066 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005067 * generates the correct flags.
5068 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005069 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005070
5071 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005072
Johan Hedberg432df052014-08-01 11:13:31 +03005073 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005074 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005075
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005076 /* Since only the advertising data flags will change, there
5077 * is no need to update the scan response data.
5078 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005079 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005080
Johan Hedberg0663ca22013-10-02 13:43:14 +03005081 err = hci_req_run(&req, set_bredr_complete);
5082 if (err < 0)
5083 mgmt_pending_remove(cmd);
5084
5085unlock:
5086 hci_dev_unlock(hdev);
5087 return err;
5088}
5089
Johan Hedberga1443f52015-01-23 15:42:46 +02005090static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5091{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005092 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005093 struct mgmt_mode *cp;
5094
5095 BT_DBG("%s status %u", hdev->name, status);
5096
5097 hci_dev_lock(hdev);
5098
Johan Hedberg333ae952015-03-17 13:48:47 +02005099 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005100 if (!cmd)
5101 goto unlock;
5102
5103 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005104 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5105 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005106 goto remove;
5107 }
5108
5109 cp = cmd->param;
5110
5111 switch (cp->val) {
5112 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005113 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5114 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005115 break;
5116 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005117 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005118 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005119 break;
5120 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005121 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5122 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005123 break;
5124 }
5125
5126 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5127 new_settings(hdev, cmd->sk);
5128
5129remove:
5130 mgmt_pending_remove(cmd);
5131unlock:
5132 hci_dev_unlock(hdev);
5133}
5134
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005135static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5136 void *data, u16 len)
5137{
5138 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005139 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005140 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005141 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005142 int err;
5143
5144 BT_DBG("request for %s", hdev->name);
5145
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005146 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005147 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005148 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5149 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005150
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005151 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005152 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005153 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005154 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5155 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005156
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005157 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005158 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005159 MGMT_STATUS_INVALID_PARAMS);
5160
5161 hci_dev_lock(hdev);
5162
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005163 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005164 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005165 bool changed;
5166
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005167 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005168 changed = !hci_dev_test_and_set_flag(hdev,
5169 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005170 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005171 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005172 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005173 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005174 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005175 changed = hci_dev_test_and_clear_flag(hdev,
5176 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005177 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005178 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005179
5180 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5181 if (err < 0)
5182 goto failed;
5183
5184 if (changed)
5185 err = new_settings(hdev, sk);
5186
5187 goto failed;
5188 }
5189
Johan Hedberg333ae952015-03-17 13:48:47 +02005190 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005191 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5192 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005193 goto failed;
5194 }
5195
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005196 val = !!cp->val;
5197
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005198 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5199 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005200 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5201 goto failed;
5202 }
5203
5204 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5205 if (!cmd) {
5206 err = -ENOMEM;
5207 goto failed;
5208 }
5209
Johan Hedberga1443f52015-01-23 15:42:46 +02005210 hci_req_init(&req, hdev);
5211 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5212 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005213 if (err < 0) {
5214 mgmt_pending_remove(cmd);
5215 goto failed;
5216 }
5217
5218failed:
5219 hci_dev_unlock(hdev);
5220 return err;
5221}
5222
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005223static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5224 void *data, u16 len)
5225{
5226 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005227 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005228 int err;
5229
5230 BT_DBG("request for %s", hdev->name);
5231
Johan Hedbergb97109792014-06-24 14:00:28 +03005232 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005233 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5234 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005235
5236 hci_dev_lock(hdev);
5237
5238 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005239 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005240 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005241 changed = hci_dev_test_and_clear_flag(hdev,
5242 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005243
Johan Hedbergb97109792014-06-24 14:00:28 +03005244 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005245 use_changed = !hci_dev_test_and_set_flag(hdev,
5246 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005247 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005248 use_changed = hci_dev_test_and_clear_flag(hdev,
5249 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005250
5251 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005252 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005253 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5254 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5255 sizeof(mode), &mode);
5256 }
5257
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005258 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5259 if (err < 0)
5260 goto unlock;
5261
5262 if (changed)
5263 err = new_settings(hdev, sk);
5264
5265unlock:
5266 hci_dev_unlock(hdev);
5267 return err;
5268}
5269
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005270static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5271 u16 len)
5272{
5273 struct mgmt_cp_set_privacy *cp = cp_data;
5274 bool changed;
5275 int err;
5276
5277 BT_DBG("request for %s", hdev->name);
5278
5279 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005280 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5281 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005282
5283 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005284 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5285 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005286
5287 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005288 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5289 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005290
5291 hci_dev_lock(hdev);
5292
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005293 /* If user space supports this command it is also expected to
5294 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5295 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005296 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005297
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005298 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005299 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005300 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005301 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005302 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005303 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005304 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005305 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005306 }
5307
5308 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5309 if (err < 0)
5310 goto unlock;
5311
5312 if (changed)
5313 err = new_settings(hdev, sk);
5314
5315unlock:
5316 hci_dev_unlock(hdev);
5317 return err;
5318}
5319
Johan Hedberg41edf162014-02-18 10:19:35 +02005320static bool irk_is_valid(struct mgmt_irk_info *irk)
5321{
5322 switch (irk->addr.type) {
5323 case BDADDR_LE_PUBLIC:
5324 return true;
5325
5326 case BDADDR_LE_RANDOM:
5327 /* Two most significant bits shall be set */
5328 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5329 return false;
5330 return true;
5331 }
5332
5333 return false;
5334}
5335
5336static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5337 u16 len)
5338{
5339 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005340 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5341 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005342 u16 irk_count, expected_len;
5343 int i, err;
5344
5345 BT_DBG("request for %s", hdev->name);
5346
5347 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005348 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5349 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005350
5351 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005352 if (irk_count > max_irk_count) {
5353 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005354 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5355 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005356 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005357
5358 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5359 if (expected_len != len) {
5360 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005361 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005362 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5363 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005364 }
5365
5366 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5367
5368 for (i = 0; i < irk_count; i++) {
5369 struct mgmt_irk_info *key = &cp->irks[i];
5370
5371 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005372 return mgmt_cmd_status(sk, hdev->id,
5373 MGMT_OP_LOAD_IRKS,
5374 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005375 }
5376
5377 hci_dev_lock(hdev);
5378
5379 hci_smp_irks_clear(hdev);
5380
5381 for (i = 0; i < irk_count; i++) {
5382 struct mgmt_irk_info *irk = &cp->irks[i];
5383 u8 addr_type;
5384
5385 if (irk->addr.type == BDADDR_LE_PUBLIC)
5386 addr_type = ADDR_LE_DEV_PUBLIC;
5387 else
5388 addr_type = ADDR_LE_DEV_RANDOM;
5389
5390 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5391 BDADDR_ANY);
5392 }
5393
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005394 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005395
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005396 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005397
5398 hci_dev_unlock(hdev);
5399
5400 return err;
5401}
5402
Johan Hedberg3f706b72013-01-20 14:27:16 +02005403static bool ltk_is_valid(struct mgmt_ltk_info *key)
5404{
5405 if (key->master != 0x00 && key->master != 0x01)
5406 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005407
5408 switch (key->addr.type) {
5409 case BDADDR_LE_PUBLIC:
5410 return true;
5411
5412 case BDADDR_LE_RANDOM:
5413 /* Two most significant bits shall be set */
5414 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5415 return false;
5416 return true;
5417 }
5418
5419 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005420}
5421
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005422static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005423 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005424{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005425 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005426 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5427 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005428 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005429 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005430
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005431 BT_DBG("request for %s", hdev->name);
5432
5433 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005434 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5435 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005436
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005437 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005438 if (key_count > max_key_count) {
5439 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005440 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5441 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005442 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005443
5444 expected_len = sizeof(*cp) + key_count *
5445 sizeof(struct mgmt_ltk_info);
5446 if (expected_len != len) {
5447 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005448 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005449 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5450 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005451 }
5452
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005453 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005454
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005455 for (i = 0; i < key_count; i++) {
5456 struct mgmt_ltk_info *key = &cp->keys[i];
5457
Johan Hedberg3f706b72013-01-20 14:27:16 +02005458 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005459 return mgmt_cmd_status(sk, hdev->id,
5460 MGMT_OP_LOAD_LONG_TERM_KEYS,
5461 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005462 }
5463
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005464 hci_dev_lock(hdev);
5465
5466 hci_smp_ltks_clear(hdev);
5467
5468 for (i = 0; i < key_count; i++) {
5469 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005470 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005471
5472 if (key->addr.type == BDADDR_LE_PUBLIC)
5473 addr_type = ADDR_LE_DEV_PUBLIC;
5474 else
5475 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005476
Johan Hedberg61b43352014-05-29 19:36:53 +03005477 switch (key->type) {
5478 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005479 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005480 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005481 break;
5482 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005483 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005484 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005485 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005486 case MGMT_LTK_P256_UNAUTH:
5487 authenticated = 0x00;
5488 type = SMP_LTK_P256;
5489 break;
5490 case MGMT_LTK_P256_AUTH:
5491 authenticated = 0x01;
5492 type = SMP_LTK_P256;
5493 break;
5494 case MGMT_LTK_P256_DEBUG:
5495 authenticated = 0x00;
5496 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005497 default:
5498 continue;
5499 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005500
Johan Hedberg35d70272014-02-19 14:57:47 +02005501 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005502 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005503 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005504 }
5505
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005506 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005507 NULL, 0);
5508
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005509 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005510
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005511 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005512}
5513
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005514static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005515{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005516 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005517 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005518 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005519
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005520 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005521
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005522 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005523 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005524 rp.tx_power = conn->tx_power;
5525 rp.max_tx_power = conn->max_tx_power;
5526 } else {
5527 rp.rssi = HCI_RSSI_INVALID;
5528 rp.tx_power = HCI_TX_POWER_INVALID;
5529 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005530 }
5531
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005532 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5533 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005534
5535 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005536 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005537
5538 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005539}
5540
Marcel Holtmann1904a852015-01-11 13:50:44 -08005541static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5542 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005543{
5544 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005545 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005546 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005547 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005548 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005549
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005550 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005551
5552 hci_dev_lock(hdev);
5553
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005554 /* Commands sent in request are either Read RSSI or Read Transmit Power
5555 * Level so we check which one was last sent to retrieve connection
5556 * handle. Both commands have handle as first parameter so it's safe to
5557 * cast data on the same command struct.
5558 *
5559 * First command sent is always Read RSSI and we fail only if it fails.
5560 * In other case we simply override error to indicate success as we
5561 * already remembered if TX power value is actually valid.
5562 */
5563 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5564 if (!cp) {
5565 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005566 status = MGMT_STATUS_SUCCESS;
5567 } else {
5568 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005569 }
5570
5571 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005572 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005573 goto unlock;
5574 }
5575
5576 handle = __le16_to_cpu(cp->handle);
5577 conn = hci_conn_hash_lookup_handle(hdev, handle);
5578 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005579 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005580 goto unlock;
5581 }
5582
Johan Hedberg333ae952015-03-17 13:48:47 +02005583 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005584 if (!cmd)
5585 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005586
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005587 cmd->cmd_complete(cmd, status);
5588 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005589
5590unlock:
5591 hci_dev_unlock(hdev);
5592}
5593
5594static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5595 u16 len)
5596{
5597 struct mgmt_cp_get_conn_info *cp = data;
5598 struct mgmt_rp_get_conn_info rp;
5599 struct hci_conn *conn;
5600 unsigned long conn_info_age;
5601 int err = 0;
5602
5603 BT_DBG("%s", hdev->name);
5604
5605 memset(&rp, 0, sizeof(rp));
5606 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5607 rp.addr.type = cp->addr.type;
5608
5609 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005610 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5611 MGMT_STATUS_INVALID_PARAMS,
5612 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005613
5614 hci_dev_lock(hdev);
5615
5616 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005617 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5618 MGMT_STATUS_NOT_POWERED, &rp,
5619 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005620 goto unlock;
5621 }
5622
5623 if (cp->addr.type == BDADDR_BREDR)
5624 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5625 &cp->addr.bdaddr);
5626 else
5627 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5628
5629 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005630 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5631 MGMT_STATUS_NOT_CONNECTED, &rp,
5632 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005633 goto unlock;
5634 }
5635
Johan Hedberg333ae952015-03-17 13:48:47 +02005636 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005637 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5638 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005639 goto unlock;
5640 }
5641
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005642 /* To avoid client trying to guess when to poll again for information we
5643 * calculate conn info age as random value between min/max set in hdev.
5644 */
5645 conn_info_age = hdev->conn_info_min_age +
5646 prandom_u32_max(hdev->conn_info_max_age -
5647 hdev->conn_info_min_age);
5648
5649 /* Query controller to refresh cached values if they are too old or were
5650 * never read.
5651 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005652 if (time_after(jiffies, conn->conn_info_timestamp +
5653 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005654 !conn->conn_info_timestamp) {
5655 struct hci_request req;
5656 struct hci_cp_read_tx_power req_txp_cp;
5657 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005658 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005659
5660 hci_req_init(&req, hdev);
5661 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5662 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5663 &req_rssi_cp);
5664
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005665 /* For LE links TX power does not change thus we don't need to
5666 * query for it once value is known.
5667 */
5668 if (!bdaddr_type_is_le(cp->addr.type) ||
5669 conn->tx_power == HCI_TX_POWER_INVALID) {
5670 req_txp_cp.handle = cpu_to_le16(conn->handle);
5671 req_txp_cp.type = 0x00;
5672 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5673 sizeof(req_txp_cp), &req_txp_cp);
5674 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005675
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005676 /* Max TX power needs to be read only once per connection */
5677 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5678 req_txp_cp.handle = cpu_to_le16(conn->handle);
5679 req_txp_cp.type = 0x01;
5680 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5681 sizeof(req_txp_cp), &req_txp_cp);
5682 }
5683
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005684 err = hci_req_run(&req, conn_info_refresh_complete);
5685 if (err < 0)
5686 goto unlock;
5687
5688 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5689 data, len);
5690 if (!cmd) {
5691 err = -ENOMEM;
5692 goto unlock;
5693 }
5694
5695 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005696 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005697 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005698
5699 conn->conn_info_timestamp = jiffies;
5700 } else {
5701 /* Cache is valid, just reply with values cached in hci_conn */
5702 rp.rssi = conn->rssi;
5703 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005704 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005705
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005706 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5707 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005708 }
5709
5710unlock:
5711 hci_dev_unlock(hdev);
5712 return err;
5713}
5714
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005715static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005716{
5717 struct hci_conn *conn = cmd->user_data;
5718 struct mgmt_rp_get_clock_info rp;
5719 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005720 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005721
5722 memset(&rp, 0, sizeof(rp));
5723 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5724
5725 if (status)
5726 goto complete;
5727
5728 hdev = hci_dev_get(cmd->index);
5729 if (hdev) {
5730 rp.local_clock = cpu_to_le32(hdev->clock);
5731 hci_dev_put(hdev);
5732 }
5733
5734 if (conn) {
5735 rp.piconet_clock = cpu_to_le32(conn->clock);
5736 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5737 }
5738
5739complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005740 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5741 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005742
5743 if (conn) {
5744 hci_conn_drop(conn);
5745 hci_conn_put(conn);
5746 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005747
5748 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005749}
5750
Marcel Holtmann1904a852015-01-11 13:50:44 -08005751static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005752{
Johan Hedberg95868422014-06-28 17:54:07 +03005753 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005754 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005755 struct hci_conn *conn;
5756
5757 BT_DBG("%s status %u", hdev->name, status);
5758
5759 hci_dev_lock(hdev);
5760
5761 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5762 if (!hci_cp)
5763 goto unlock;
5764
5765 if (hci_cp->which) {
5766 u16 handle = __le16_to_cpu(hci_cp->handle);
5767 conn = hci_conn_hash_lookup_handle(hdev, handle);
5768 } else {
5769 conn = NULL;
5770 }
5771
Johan Hedberg333ae952015-03-17 13:48:47 +02005772 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005773 if (!cmd)
5774 goto unlock;
5775
Johan Hedberg69487372014-12-05 13:36:07 +02005776 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005777 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005778
5779unlock:
5780 hci_dev_unlock(hdev);
5781}
5782
5783static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5784 u16 len)
5785{
5786 struct mgmt_cp_get_clock_info *cp = data;
5787 struct mgmt_rp_get_clock_info rp;
5788 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005789 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005790 struct hci_request req;
5791 struct hci_conn *conn;
5792 int err;
5793
5794 BT_DBG("%s", hdev->name);
5795
5796 memset(&rp, 0, sizeof(rp));
5797 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5798 rp.addr.type = cp->addr.type;
5799
5800 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005801 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5802 MGMT_STATUS_INVALID_PARAMS,
5803 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005804
5805 hci_dev_lock(hdev);
5806
5807 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005808 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5809 MGMT_STATUS_NOT_POWERED, &rp,
5810 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005811 goto unlock;
5812 }
5813
5814 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5815 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5816 &cp->addr.bdaddr);
5817 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005818 err = mgmt_cmd_complete(sk, hdev->id,
5819 MGMT_OP_GET_CLOCK_INFO,
5820 MGMT_STATUS_NOT_CONNECTED,
5821 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005822 goto unlock;
5823 }
5824 } else {
5825 conn = NULL;
5826 }
5827
5828 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5829 if (!cmd) {
5830 err = -ENOMEM;
5831 goto unlock;
5832 }
5833
Johan Hedberg69487372014-12-05 13:36:07 +02005834 cmd->cmd_complete = clock_info_cmd_complete;
5835
Johan Hedberg95868422014-06-28 17:54:07 +03005836 hci_req_init(&req, hdev);
5837
5838 memset(&hci_cp, 0, sizeof(hci_cp));
5839 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5840
5841 if (conn) {
5842 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005843 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005844
5845 hci_cp.handle = cpu_to_le16(conn->handle);
5846 hci_cp.which = 0x01; /* Piconet clock */
5847 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5848 }
5849
5850 err = hci_req_run(&req, get_clock_info_complete);
5851 if (err < 0)
5852 mgmt_pending_remove(cmd);
5853
5854unlock:
5855 hci_dev_unlock(hdev);
5856 return err;
5857}
5858
Johan Hedberg5a154e62014-12-19 22:26:02 +02005859static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5860{
5861 struct hci_conn *conn;
5862
5863 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5864 if (!conn)
5865 return false;
5866
5867 if (conn->dst_type != type)
5868 return false;
5869
5870 if (conn->state != BT_CONNECTED)
5871 return false;
5872
5873 return true;
5874}
5875
5876/* This function requires the caller holds hdev->lock */
5877static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5878 u8 addr_type, u8 auto_connect)
5879{
5880 struct hci_dev *hdev = req->hdev;
5881 struct hci_conn_params *params;
5882
5883 params = hci_conn_params_add(hdev, addr, addr_type);
5884 if (!params)
5885 return -EIO;
5886
5887 if (params->auto_connect == auto_connect)
5888 return 0;
5889
5890 list_del_init(&params->action);
5891
5892 switch (auto_connect) {
5893 case HCI_AUTO_CONN_DISABLED:
5894 case HCI_AUTO_CONN_LINK_LOSS:
5895 __hci_update_background_scan(req);
5896 break;
5897 case HCI_AUTO_CONN_REPORT:
5898 list_add(&params->action, &hdev->pend_le_reports);
5899 __hci_update_background_scan(req);
5900 break;
5901 case HCI_AUTO_CONN_DIRECT:
5902 case HCI_AUTO_CONN_ALWAYS:
5903 if (!is_connected(hdev, addr, addr_type)) {
5904 list_add(&params->action, &hdev->pend_le_conns);
5905 __hci_update_background_scan(req);
5906 }
5907 break;
5908 }
5909
5910 params->auto_connect = auto_connect;
5911
5912 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5913 auto_connect);
5914
5915 return 0;
5916}
5917
Marcel Holtmann8afef092014-06-29 22:28:34 +02005918static void device_added(struct sock *sk, struct hci_dev *hdev,
5919 bdaddr_t *bdaddr, u8 type, u8 action)
5920{
5921 struct mgmt_ev_device_added ev;
5922
5923 bacpy(&ev.addr.bdaddr, bdaddr);
5924 ev.addr.type = type;
5925 ev.action = action;
5926
5927 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5928}
5929
Marcel Holtmann1904a852015-01-11 13:50:44 -08005930static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005931{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005932 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005933
5934 BT_DBG("status 0x%02x", status);
5935
5936 hci_dev_lock(hdev);
5937
Johan Hedberg333ae952015-03-17 13:48:47 +02005938 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005939 if (!cmd)
5940 goto unlock;
5941
5942 cmd->cmd_complete(cmd, mgmt_status(status));
5943 mgmt_pending_remove(cmd);
5944
5945unlock:
5946 hci_dev_unlock(hdev);
5947}
5948
Marcel Holtmann2faade52014-06-29 19:44:03 +02005949static int add_device(struct sock *sk, struct hci_dev *hdev,
5950 void *data, u16 len)
5951{
5952 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005953 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005954 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005955 u8 auto_conn, addr_type;
5956 int err;
5957
5958 BT_DBG("%s", hdev->name);
5959
Johan Hedberg66593582014-07-09 12:59:14 +03005960 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005961 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005962 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5963 MGMT_STATUS_INVALID_PARAMS,
5964 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005965
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005966 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005967 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5968 MGMT_STATUS_INVALID_PARAMS,
5969 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005970
Johan Hedberg5a154e62014-12-19 22:26:02 +02005971 hci_req_init(&req, hdev);
5972
Marcel Holtmann2faade52014-06-29 19:44:03 +02005973 hci_dev_lock(hdev);
5974
Johan Hedberg5a154e62014-12-19 22:26:02 +02005975 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5976 if (!cmd) {
5977 err = -ENOMEM;
5978 goto unlock;
5979 }
5980
5981 cmd->cmd_complete = addr_cmd_complete;
5982
Johan Hedberg66593582014-07-09 12:59:14 +03005983 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005984 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005985 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005986 err = cmd->cmd_complete(cmd,
5987 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005988 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005989 goto unlock;
5990 }
5991
5992 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5993 cp->addr.type);
5994 if (err)
5995 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005996
Johan Hedberg5a154e62014-12-19 22:26:02 +02005997 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005998
Johan Hedberg66593582014-07-09 12:59:14 +03005999 goto added;
6000 }
6001
Marcel Holtmann2faade52014-06-29 19:44:03 +02006002 if (cp->addr.type == BDADDR_LE_PUBLIC)
6003 addr_type = ADDR_LE_DEV_PUBLIC;
6004 else
6005 addr_type = ADDR_LE_DEV_RANDOM;
6006
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006007 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006008 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006009 else if (cp->action == 0x01)
6010 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006011 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006012 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006013
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006014 /* If the connection parameters don't exist for this device,
6015 * they will be created and configured with defaults.
6016 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006017 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006018 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006019 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006020 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006021 goto unlock;
6022 }
6023
Johan Hedberg66593582014-07-09 12:59:14 +03006024added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006025 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6026
Johan Hedberg5a154e62014-12-19 22:26:02 +02006027 err = hci_req_run(&req, add_device_complete);
6028 if (err < 0) {
6029 /* ENODATA means no HCI commands were needed (e.g. if
6030 * the adapter is powered off).
6031 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006032 if (err == -ENODATA)
6033 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006034 mgmt_pending_remove(cmd);
6035 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006036
6037unlock:
6038 hci_dev_unlock(hdev);
6039 return err;
6040}
6041
Marcel Holtmann8afef092014-06-29 22:28:34 +02006042static void device_removed(struct sock *sk, struct hci_dev *hdev,
6043 bdaddr_t *bdaddr, u8 type)
6044{
6045 struct mgmt_ev_device_removed ev;
6046
6047 bacpy(&ev.addr.bdaddr, bdaddr);
6048 ev.addr.type = type;
6049
6050 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6051}
6052
Marcel Holtmann1904a852015-01-11 13:50:44 -08006053static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006054{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006055 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006056
6057 BT_DBG("status 0x%02x", status);
6058
6059 hci_dev_lock(hdev);
6060
Johan Hedberg333ae952015-03-17 13:48:47 +02006061 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006062 if (!cmd)
6063 goto unlock;
6064
6065 cmd->cmd_complete(cmd, mgmt_status(status));
6066 mgmt_pending_remove(cmd);
6067
6068unlock:
6069 hci_dev_unlock(hdev);
6070}
6071
Marcel Holtmann2faade52014-06-29 19:44:03 +02006072static int remove_device(struct sock *sk, struct hci_dev *hdev,
6073 void *data, u16 len)
6074{
6075 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006076 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006077 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006078 int err;
6079
6080 BT_DBG("%s", hdev->name);
6081
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006082 hci_req_init(&req, hdev);
6083
Marcel Holtmann2faade52014-06-29 19:44:03 +02006084 hci_dev_lock(hdev);
6085
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006086 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6087 if (!cmd) {
6088 err = -ENOMEM;
6089 goto unlock;
6090 }
6091
6092 cmd->cmd_complete = addr_cmd_complete;
6093
Marcel Holtmann2faade52014-06-29 19:44:03 +02006094 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006095 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006096 u8 addr_type;
6097
Johan Hedberg66593582014-07-09 12:59:14 +03006098 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006099 err = cmd->cmd_complete(cmd,
6100 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006101 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006102 goto unlock;
6103 }
6104
Johan Hedberg66593582014-07-09 12:59:14 +03006105 if (cp->addr.type == BDADDR_BREDR) {
6106 err = hci_bdaddr_list_del(&hdev->whitelist,
6107 &cp->addr.bdaddr,
6108 cp->addr.type);
6109 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006110 err = cmd->cmd_complete(cmd,
6111 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006112 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006113 goto unlock;
6114 }
6115
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006116 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006117
Johan Hedberg66593582014-07-09 12:59:14 +03006118 device_removed(sk, hdev, &cp->addr.bdaddr,
6119 cp->addr.type);
6120 goto complete;
6121 }
6122
Marcel Holtmann2faade52014-06-29 19:44:03 +02006123 if (cp->addr.type == BDADDR_LE_PUBLIC)
6124 addr_type = ADDR_LE_DEV_PUBLIC;
6125 else
6126 addr_type = ADDR_LE_DEV_RANDOM;
6127
Johan Hedbergc71593d2014-07-02 17:37:28 +03006128 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6129 addr_type);
6130 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006131 err = cmd->cmd_complete(cmd,
6132 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006133 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006134 goto unlock;
6135 }
6136
6137 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006138 err = cmd->cmd_complete(cmd,
6139 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006140 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006141 goto unlock;
6142 }
6143
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006144 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006145 list_del(&params->list);
6146 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006147 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006148
6149 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006150 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006151 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006152 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006153
Marcel Holtmann2faade52014-06-29 19:44:03 +02006154 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006155 err = cmd->cmd_complete(cmd,
6156 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006157 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006158 goto unlock;
6159 }
6160
Johan Hedberg66593582014-07-09 12:59:14 +03006161 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6162 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6163 list_del(&b->list);
6164 kfree(b);
6165 }
6166
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006167 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006168
Johan Hedberg19de0822014-07-06 13:06:51 +03006169 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6170 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6171 continue;
6172 device_removed(sk, hdev, &p->addr, p->addr_type);
6173 list_del(&p->action);
6174 list_del(&p->list);
6175 kfree(p);
6176 }
6177
6178 BT_DBG("All LE connection parameters were removed");
6179
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006180 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006181 }
6182
Johan Hedberg66593582014-07-09 12:59:14 +03006183complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006184 err = hci_req_run(&req, remove_device_complete);
6185 if (err < 0) {
6186 /* ENODATA means no HCI commands were needed (e.g. if
6187 * the adapter is powered off).
6188 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006189 if (err == -ENODATA)
6190 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006191 mgmt_pending_remove(cmd);
6192 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006193
6194unlock:
6195 hci_dev_unlock(hdev);
6196 return err;
6197}
6198
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006199static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6200 u16 len)
6201{
6202 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006203 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6204 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006205 u16 param_count, expected_len;
6206 int i;
6207
6208 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006209 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6210 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006211
6212 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006213 if (param_count > max_param_count) {
6214 BT_ERR("load_conn_param: too big param_count value %u",
6215 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006216 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6217 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006218 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006219
6220 expected_len = sizeof(*cp) + param_count *
6221 sizeof(struct mgmt_conn_param);
6222 if (expected_len != len) {
6223 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6224 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006225 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6226 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006227 }
6228
6229 BT_DBG("%s param_count %u", hdev->name, param_count);
6230
6231 hci_dev_lock(hdev);
6232
6233 hci_conn_params_clear_disabled(hdev);
6234
6235 for (i = 0; i < param_count; i++) {
6236 struct mgmt_conn_param *param = &cp->params[i];
6237 struct hci_conn_params *hci_param;
6238 u16 min, max, latency, timeout;
6239 u8 addr_type;
6240
6241 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6242 param->addr.type);
6243
6244 if (param->addr.type == BDADDR_LE_PUBLIC) {
6245 addr_type = ADDR_LE_DEV_PUBLIC;
6246 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6247 addr_type = ADDR_LE_DEV_RANDOM;
6248 } else {
6249 BT_ERR("Ignoring invalid connection parameters");
6250 continue;
6251 }
6252
6253 min = le16_to_cpu(param->min_interval);
6254 max = le16_to_cpu(param->max_interval);
6255 latency = le16_to_cpu(param->latency);
6256 timeout = le16_to_cpu(param->timeout);
6257
6258 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6259 min, max, latency, timeout);
6260
6261 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6262 BT_ERR("Ignoring invalid connection parameters");
6263 continue;
6264 }
6265
6266 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6267 addr_type);
6268 if (!hci_param) {
6269 BT_ERR("Failed to add connection parameters");
6270 continue;
6271 }
6272
6273 hci_param->conn_min_interval = min;
6274 hci_param->conn_max_interval = max;
6275 hci_param->conn_latency = latency;
6276 hci_param->supervision_timeout = timeout;
6277 }
6278
6279 hci_dev_unlock(hdev);
6280
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006281 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6282 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006283}
6284
Marcel Holtmanndbece372014-07-04 18:11:55 +02006285static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6286 void *data, u16 len)
6287{
6288 struct mgmt_cp_set_external_config *cp = data;
6289 bool changed;
6290 int err;
6291
6292 BT_DBG("%s", hdev->name);
6293
6294 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006295 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6296 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006297
6298 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006299 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6300 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006301
6302 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006303 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6304 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006305
6306 hci_dev_lock(hdev);
6307
6308 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006309 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006310 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006311 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006312
6313 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6314 if (err < 0)
6315 goto unlock;
6316
6317 if (!changed)
6318 goto unlock;
6319
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006320 err = new_options(hdev, sk);
6321
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006322 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006323 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006324
Marcel Holtmann516018a2015-03-13 02:11:04 -07006325 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006326 hci_dev_set_flag(hdev, HCI_CONFIG);
6327 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006328
6329 queue_work(hdev->req_workqueue, &hdev->power_on);
6330 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006331 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006332 mgmt_index_added(hdev);
6333 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006334 }
6335
6336unlock:
6337 hci_dev_unlock(hdev);
6338 return err;
6339}
6340
Marcel Holtmann9713c172014-07-06 12:11:15 +02006341static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6342 void *data, u16 len)
6343{
6344 struct mgmt_cp_set_public_address *cp = data;
6345 bool changed;
6346 int err;
6347
6348 BT_DBG("%s", hdev->name);
6349
6350 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006351 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6352 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006353
6354 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006355 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6356 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006357
6358 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006359 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6360 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006361
6362 hci_dev_lock(hdev);
6363
6364 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6365 bacpy(&hdev->public_addr, &cp->bdaddr);
6366
6367 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6368 if (err < 0)
6369 goto unlock;
6370
6371 if (!changed)
6372 goto unlock;
6373
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006374 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006375 err = new_options(hdev, sk);
6376
6377 if (is_configured(hdev)) {
6378 mgmt_index_removed(hdev);
6379
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006380 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006381
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006382 hci_dev_set_flag(hdev, HCI_CONFIG);
6383 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006384
6385 queue_work(hdev->req_workqueue, &hdev->power_on);
6386 }
6387
6388unlock:
6389 hci_dev_unlock(hdev);
6390 return err;
6391}
6392
Marcel Holtmannbea41602015-03-14 22:43:17 -07006393static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6394 u8 data_len)
6395{
6396 eir[eir_len++] = sizeof(type) + data_len;
6397 eir[eir_len++] = type;
6398 memcpy(&eir[eir_len], data, data_len);
6399 eir_len += data_len;
6400
6401 return eir_len;
6402}
6403
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006404static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6405 void *data, u16 data_len)
6406{
6407 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6408 struct mgmt_rp_read_local_oob_ext_data *rp;
6409 size_t rp_len;
6410 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006411 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006412 int err;
6413
6414 BT_DBG("%s", hdev->name);
6415
6416 if (!hdev_is_powered(hdev))
6417 return mgmt_cmd_complete(sk, hdev->id,
6418 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6419 MGMT_STATUS_NOT_POWERED,
6420 &cp->type, sizeof(cp->type));
6421
6422 switch (cp->type) {
6423 case BIT(BDADDR_BREDR):
6424 status = mgmt_bredr_support(hdev);
6425 if (status)
6426 return mgmt_cmd_complete(sk, hdev->id,
6427 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6428 status, &cp->type,
6429 sizeof(cp->type));
6430 eir_len = 5;
6431 break;
6432 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6433 status = mgmt_le_support(hdev);
6434 if (status)
6435 return mgmt_cmd_complete(sk, hdev->id,
6436 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6437 status, &cp->type,
6438 sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006439 eir_len = 9 + 3 + 18 + 18 + 3;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006440 break;
6441 default:
6442 return mgmt_cmd_complete(sk, hdev->id,
6443 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6444 MGMT_STATUS_INVALID_PARAMS,
6445 &cp->type, sizeof(cp->type));
6446 }
6447
6448 hci_dev_lock(hdev);
6449
6450 rp_len = sizeof(*rp) + eir_len;
6451 rp = kmalloc(rp_len, GFP_ATOMIC);
6452 if (!rp) {
6453 hci_dev_unlock(hdev);
6454 return -ENOMEM;
6455 }
6456
6457 eir_len = 0;
6458 switch (cp->type) {
6459 case BIT(BDADDR_BREDR):
6460 eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
6461 hdev->dev_class, 3);
6462 break;
6463 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006464 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6465 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006466 hci_dev_unlock(hdev);
6467 err = mgmt_cmd_complete(sk, hdev->id,
Marcel Holtmann5082a592015-03-16 12:39:00 -07006468 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6469 MGMT_STATUS_FAILED,
6470 &cp->type, sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006471 goto done;
6472 }
6473
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006474 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
6475 memcpy(addr, &hdev->rpa, 6);
6476 addr[6] = 0x01;
6477 } else if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6478 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6479 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6480 bacmp(&hdev->static_addr, BDADDR_ANY))) {
6481 memcpy(addr, &hdev->static_addr, 6);
6482 addr[6] = 0x01;
6483 } else {
6484 memcpy(addr, &hdev->bdaddr, 6);
6485 addr[6] = 0x00;
6486 }
6487
6488 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6489 addr, sizeof(addr));
6490
6491 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6492 role = 0x02;
6493 else
6494 role = 0x01;
6495
6496 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6497 &role, sizeof(role));
6498
Marcel Holtmann5082a592015-03-16 12:39:00 -07006499 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6500 eir_len = eir_append_data(rp->eir, eir_len,
6501 EIR_LE_SC_CONFIRM,
6502 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006503
Marcel Holtmann5082a592015-03-16 12:39:00 -07006504 eir_len = eir_append_data(rp->eir, eir_len,
6505 EIR_LE_SC_RANDOM,
6506 rand, sizeof(rand));
6507 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006508
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006509 flags = get_adv_discov_flags(hdev);
6510
6511 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6512 flags |= LE_AD_NO_BREDR;
6513
6514 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6515 &flags, sizeof(flags));
6516 break;
6517 }
6518
6519 rp->type = cp->type;
6520 rp->eir_len = cpu_to_le16(eir_len);
6521
6522 hci_dev_unlock(hdev);
6523
Marcel Holtmann72000df2015-03-16 16:11:21 -07006524 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6525
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006526 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann5425f982015-03-16 16:05:44 -07006527 MGMT_STATUS_SUCCESS, rp, sizeof(*rp) + eir_len);
Marcel Holtmann72000df2015-03-16 16:11:21 -07006528 if (err < 0)
6529 goto done;
6530
6531 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6532 rp, sizeof(*rp) + eir_len,
6533 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006534
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006535done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006536 kfree(rp);
6537
6538 return err;
6539}
6540
Arman Uguray089fa8c2015-03-25 18:53:45 -07006541static u32 get_supported_adv_flags(struct hci_dev *hdev)
6542{
6543 u32 flags = 0;
6544
6545 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6546 flags |= MGMT_ADV_FLAG_DISCOV;
6547 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6548 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6549
6550 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6551 flags |= MGMT_ADV_FLAG_TX_POWER;
6552
6553 return flags;
6554}
6555
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006556static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6557 void *data, u16 data_len)
6558{
6559 struct mgmt_rp_read_adv_features *rp;
6560 size_t rp_len;
6561 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006562 bool instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006563 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006564
6565 BT_DBG("%s", hdev->name);
6566
Arman Uguray089fa8c2015-03-25 18:53:45 -07006567 if (!lmp_le_capable(hdev))
6568 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6569 MGMT_STATUS_REJECTED);
6570
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006571 hci_dev_lock(hdev);
6572
6573 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006574
6575 /* Currently only one instance is supported, so just add 1 to the
6576 * response length.
6577 */
6578 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6579 if (instance)
6580 rp_len++;
6581
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006582 rp = kmalloc(rp_len, GFP_ATOMIC);
6583 if (!rp) {
6584 hci_dev_unlock(hdev);
6585 return -ENOMEM;
6586 }
6587
Arman Uguray089fa8c2015-03-25 18:53:45 -07006588 supported_flags = get_supported_adv_flags(hdev);
6589
6590 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006591 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6592 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006593 rp->max_instances = 1;
6594
6595 /* Currently only one instance is supported, so simply return the
6596 * current instance number.
6597 */
6598 if (instance) {
6599 rp->num_instances = 1;
6600 rp->instance[0] = 1;
6601 } else {
6602 rp->num_instances = 0;
6603 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006604
6605 hci_dev_unlock(hdev);
6606
6607 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6608 MGMT_STATUS_SUCCESS, rp, rp_len);
6609
6610 kfree(rp);
6611
6612 return err;
6613}
6614
Arman Uguray4117ed72015-03-23 15:57:14 -07006615static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006616 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006617{
Arman Uguray4117ed72015-03-23 15:57:14 -07006618 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006619 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006620 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006621 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006622 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6623 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006624
Arman Uguray807ec772015-03-25 18:53:42 -07006625 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006626 flags_managed = true;
6627 max_len -= 3;
6628 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006629
Arman Uguray5507e352015-03-25 18:53:44 -07006630 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6631 tx_power_managed = true;
6632 max_len -= 3;
6633 }
6634
Arman Uguray4117ed72015-03-23 15:57:14 -07006635 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006636 return false;
6637
Arman Uguray4117ed72015-03-23 15:57:14 -07006638 /* Make sure that the data is correctly formatted. */
6639 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6640 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006641
Arman Ugurayb44133f2015-03-25 18:53:41 -07006642 if (flags_managed && data[i + 1] == EIR_FLAGS)
6643 return false;
6644
Arman Uguray5507e352015-03-25 18:53:44 -07006645 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6646 return false;
6647
Arman Uguray24b4f382015-03-23 15:57:12 -07006648 /* If the current field length would exceed the total data
6649 * length, then it's invalid.
6650 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006651 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006652 return false;
6653 }
6654
6655 return true;
6656}
6657
Arman Uguray24b4f382015-03-23 15:57:12 -07006658static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6659 u16 opcode)
6660{
6661 struct mgmt_pending_cmd *cmd;
6662 struct mgmt_rp_add_advertising rp;
6663
6664 BT_DBG("status %d", status);
6665
6666 hci_dev_lock(hdev);
6667
6668 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6669
6670 if (status) {
6671 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6672 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6673 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6674 }
6675
6676 if (!cmd)
6677 goto unlock;
6678
6679 rp.instance = 0x01;
6680
6681 if (status)
6682 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6683 mgmt_status(status));
6684 else
6685 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6686 mgmt_status(status), &rp, sizeof(rp));
6687
6688 mgmt_pending_remove(cmd);
6689
6690unlock:
6691 hci_dev_unlock(hdev);
6692}
6693
Arman Uguray912098a2015-03-23 15:57:15 -07006694static void adv_timeout_expired(struct work_struct *work)
6695{
6696 struct hci_dev *hdev = container_of(work, struct hci_dev,
6697 adv_instance.timeout_exp.work);
6698
6699 hdev->adv_instance.timeout = 0;
6700
6701 hci_dev_lock(hdev);
6702 clear_adv_instance(hdev);
6703 hci_dev_unlock(hdev);
6704}
6705
Arman Uguray24b4f382015-03-23 15:57:12 -07006706static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6707 void *data, u16 data_len)
6708{
6709 struct mgmt_cp_add_advertising *cp = data;
6710 struct mgmt_rp_add_advertising rp;
6711 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006712 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006713 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006714 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006715 int err;
6716 struct mgmt_pending_cmd *cmd;
6717 struct hci_request req;
6718
6719 BT_DBG("%s", hdev->name);
6720
6721 status = mgmt_le_support(hdev);
6722 if (status)
6723 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6724 status);
6725
6726 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006727 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006728
Arman Uguray089fa8c2015-03-25 18:53:45 -07006729 /* The current implementation only supports adding one instance and only
6730 * a subset of the specified flags.
6731 */
6732 supported_flags = get_supported_adv_flags(hdev);
6733 if (cp->instance != 0x01 || (flags & ~supported_flags))
Arman Uguray24b4f382015-03-23 15:57:12 -07006734 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6735 MGMT_STATUS_INVALID_PARAMS);
6736
6737 hci_dev_lock(hdev);
6738
Arman Uguray912098a2015-03-23 15:57:15 -07006739 if (timeout && !hdev_is_powered(hdev)) {
6740 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6741 MGMT_STATUS_REJECTED);
6742 goto unlock;
6743 }
6744
Arman Uguray24b4f382015-03-23 15:57:12 -07006745 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006746 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006747 pending_find(MGMT_OP_SET_LE, hdev)) {
6748 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6749 MGMT_STATUS_BUSY);
6750 goto unlock;
6751 }
6752
Arman Ugurayb44133f2015-03-25 18:53:41 -07006753 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006754 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006755 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006756 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6757 MGMT_STATUS_INVALID_PARAMS);
6758 goto unlock;
6759 }
6760
Arman Uguray912098a2015-03-23 15:57:15 -07006761 INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
6762
Arman Uguray24b4f382015-03-23 15:57:12 -07006763 hdev->adv_instance.flags = flags;
6764 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6765 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6766
6767 if (cp->adv_data_len)
6768 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6769
6770 if (cp->scan_rsp_len)
6771 memcpy(hdev->adv_instance.scan_rsp_data,
6772 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6773
Arman Uguray912098a2015-03-23 15:57:15 -07006774 if (hdev->adv_instance.timeout)
6775 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6776
6777 hdev->adv_instance.timeout = timeout;
6778
6779 if (timeout)
6780 queue_delayed_work(hdev->workqueue,
6781 &hdev->adv_instance.timeout_exp,
6782 msecs_to_jiffies(timeout * 1000));
6783
Arman Uguray24b4f382015-03-23 15:57:12 -07006784 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6785 advertising_added(sk, hdev, 1);
6786
6787 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6788 * we have no HCI communication to make. Simply return.
6789 */
6790 if (!hdev_is_powered(hdev) ||
6791 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6792 rp.instance = 0x01;
6793 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6794 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6795 goto unlock;
6796 }
6797
6798 /* We're good to go, update advertising data, parameters, and start
6799 * advertising.
6800 */
6801 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
6802 data_len);
6803 if (!cmd) {
6804 err = -ENOMEM;
6805 goto unlock;
6806 }
6807
6808 hci_req_init(&req, hdev);
6809
6810 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07006811 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07006812 enable_advertising(&req);
6813
6814 err = hci_req_run(&req, add_advertising_complete);
6815 if (err < 0)
6816 mgmt_pending_remove(cmd);
6817
6818unlock:
6819 hci_dev_unlock(hdev);
6820
6821 return err;
6822}
6823
Arman Ugurayda9293352015-03-23 15:57:13 -07006824static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
6825 u16 opcode)
6826{
6827 struct mgmt_pending_cmd *cmd;
6828 struct mgmt_rp_remove_advertising rp;
6829
6830 BT_DBG("status %d", status);
6831
6832 hci_dev_lock(hdev);
6833
6834 /* A failure status here only means that we failed to disable
6835 * advertising. Otherwise, the advertising instance has been removed,
6836 * so report success.
6837 */
6838 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
6839 if (!cmd)
6840 goto unlock;
6841
6842 rp.instance = 1;
6843
6844 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
6845 &rp, sizeof(rp));
6846 mgmt_pending_remove(cmd);
6847
6848unlock:
6849 hci_dev_unlock(hdev);
6850}
6851
6852static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
6853 void *data, u16 data_len)
6854{
6855 struct mgmt_cp_remove_advertising *cp = data;
6856 struct mgmt_rp_remove_advertising rp;
6857 int err;
6858 struct mgmt_pending_cmd *cmd;
6859 struct hci_request req;
6860
6861 BT_DBG("%s", hdev->name);
6862
6863 /* The current implementation only allows modifying instance no 1. A
6864 * value of 0 indicates that all instances should be cleared.
6865 */
6866 if (cp->instance > 1)
6867 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6868 MGMT_STATUS_INVALID_PARAMS);
6869
6870 hci_dev_lock(hdev);
6871
6872 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
6873 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
6874 pending_find(MGMT_OP_SET_LE, hdev)) {
6875 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6876 MGMT_STATUS_BUSY);
6877 goto unlock;
6878 }
6879
6880 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
6881 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
6882 MGMT_STATUS_INVALID_PARAMS);
6883 goto unlock;
6884 }
6885
Arman Uguray912098a2015-03-23 15:57:15 -07006886 if (hdev->adv_instance.timeout)
6887 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
6888
Arman Ugurayda9293352015-03-23 15:57:13 -07006889 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6890
6891 advertising_removed(sk, hdev, 1);
6892
6893 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6894
6895 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6896 * we have no HCI communication to make. Simply return.
6897 */
6898 if (!hdev_is_powered(hdev) ||
6899 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6900 rp.instance = 1;
6901 err = mgmt_cmd_complete(sk, hdev->id,
6902 MGMT_OP_REMOVE_ADVERTISING,
6903 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6904 goto unlock;
6905 }
6906
6907 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
6908 data_len);
6909 if (!cmd) {
6910 err = -ENOMEM;
6911 goto unlock;
6912 }
6913
6914 hci_req_init(&req, hdev);
6915 disable_advertising(&req);
6916
6917 err = hci_req_run(&req, remove_advertising_complete);
6918 if (err < 0)
6919 mgmt_pending_remove(cmd);
6920
6921unlock:
6922 hci_dev_unlock(hdev);
6923
6924 return err;
6925}
6926
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006927static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006928 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006929 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006930 HCI_MGMT_NO_HDEV |
6931 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006932 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006933 HCI_MGMT_NO_HDEV |
6934 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006935 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006936 HCI_MGMT_NO_HDEV |
6937 HCI_MGMT_UNTRUSTED },
6938 { read_controller_info, MGMT_READ_INFO_SIZE,
6939 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006940 { set_powered, MGMT_SETTING_SIZE },
6941 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
6942 { set_connectable, MGMT_SETTING_SIZE },
6943 { set_fast_connectable, MGMT_SETTING_SIZE },
6944 { set_bondable, MGMT_SETTING_SIZE },
6945 { set_link_security, MGMT_SETTING_SIZE },
6946 { set_ssp, MGMT_SETTING_SIZE },
6947 { set_hs, MGMT_SETTING_SIZE },
6948 { set_le, MGMT_SETTING_SIZE },
6949 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
6950 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
6951 { add_uuid, MGMT_ADD_UUID_SIZE },
6952 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006953 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6954 HCI_MGMT_VAR_LEN },
6955 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6956 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006957 { disconnect, MGMT_DISCONNECT_SIZE },
6958 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
6959 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
6960 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6961 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
6962 { pair_device, MGMT_PAIR_DEVICE_SIZE },
6963 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6964 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
6965 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
6966 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6967 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
6968 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006969 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6970 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6971 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006972 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6973 { start_discovery, MGMT_START_DISCOVERY_SIZE },
6974 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
6975 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
6976 { block_device, MGMT_BLOCK_DEVICE_SIZE },
6977 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
6978 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
6979 { set_advertising, MGMT_SETTING_SIZE },
6980 { set_bredr, MGMT_SETTING_SIZE },
6981 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
6982 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
6983 { set_secure_conn, MGMT_SETTING_SIZE },
6984 { set_debug_keys, MGMT_SETTING_SIZE },
6985 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006986 { load_irks, MGMT_LOAD_IRKS_SIZE,
6987 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006988 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
6989 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
6990 { add_device, MGMT_ADD_DEVICE_SIZE },
6991 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006992 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6993 HCI_MGMT_VAR_LEN },
6994 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006995 HCI_MGMT_NO_HDEV |
6996 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006997 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006998 HCI_MGMT_UNCONFIGURED |
6999 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007000 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7001 HCI_MGMT_UNCONFIGURED },
7002 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7003 HCI_MGMT_UNCONFIGURED },
7004 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7005 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007006 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007007 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007008 HCI_MGMT_NO_HDEV |
7009 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007010 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007011 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7012 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007013 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007014};
7015
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007016void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007017{
Marcel Holtmannced85542015-03-14 19:27:56 -07007018 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007019
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007020 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7021 return;
7022
Marcel Holtmannf9207332015-03-14 19:27:55 -07007023 switch (hdev->dev_type) {
7024 case HCI_BREDR:
7025 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7026 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7027 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007028 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007029 } else {
7030 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7031 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007032 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007033 }
7034 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007035 case HCI_AMP:
7036 ev.type = 0x02;
7037 break;
7038 default:
7039 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007040 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007041
7042 ev.bus = hdev->bus;
7043
7044 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7045 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007046}
7047
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007048void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007049{
Marcel Holtmannced85542015-03-14 19:27:56 -07007050 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007051 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007052
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007053 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7054 return;
7055
Marcel Holtmannf9207332015-03-14 19:27:55 -07007056 switch (hdev->dev_type) {
7057 case HCI_BREDR:
7058 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007059
Marcel Holtmannf9207332015-03-14 19:27:55 -07007060 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7061 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7062 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007063 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007064 } else {
7065 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7066 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007067 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007068 }
7069 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007070 case HCI_AMP:
7071 ev.type = 0x02;
7072 break;
7073 default:
7074 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007075 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007076
7077 ev.bus = hdev->bus;
7078
7079 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7080 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007081}
7082
Andre Guedes6046dc32014-02-26 20:21:51 -03007083/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007084static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007085{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007086 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007087 struct hci_conn_params *p;
7088
7089 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007090 /* Needed for AUTO_OFF case where might not "really"
7091 * have been powered off.
7092 */
7093 list_del_init(&p->action);
7094
7095 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007096 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007097 case HCI_AUTO_CONN_ALWAYS:
7098 list_add(&p->action, &hdev->pend_le_conns);
7099 break;
7100 case HCI_AUTO_CONN_REPORT:
7101 list_add(&p->action, &hdev->pend_le_reports);
7102 break;
7103 default:
7104 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007105 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007106 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007107
Johan Hedberg2cf22212014-12-19 22:26:00 +02007108 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007109}
7110
Marcel Holtmann1904a852015-01-11 13:50:44 -08007111static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007112{
7113 struct cmd_lookup match = { NULL, hdev };
7114
7115 BT_DBG("status 0x%02x", status);
7116
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007117 if (!status) {
7118 /* Register the available SMP channels (BR/EDR and LE) only
7119 * when successfully powering on the controller. This late
7120 * registration is required so that LE SMP can clearly
7121 * decide if the public address or static address is used.
7122 */
7123 smp_register(hdev);
7124 }
7125
Johan Hedberg229ab392013-03-15 17:06:53 -05007126 hci_dev_lock(hdev);
7127
7128 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7129
7130 new_settings(hdev, match.sk);
7131
7132 hci_dev_unlock(hdev);
7133
7134 if (match.sk)
7135 sock_put(match.sk);
7136}
7137
Johan Hedberg70da6242013-03-15 17:06:51 -05007138static int powered_update_hci(struct hci_dev *hdev)
7139{
Johan Hedberg890ea892013-03-15 17:06:52 -05007140 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007141 u8 link_sec;
7142
Johan Hedberg890ea892013-03-15 17:06:52 -05007143 hci_req_init(&req, hdev);
7144
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007145 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007146 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007147 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007148
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007149 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007150
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007151 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7152 u8 support = 0x01;
7153
7154 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7155 sizeof(support), &support);
7156 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007157 }
7158
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007159 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007160 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007161 struct hci_cp_write_le_host_supported cp;
7162
Marcel Holtmann32226e42014-07-24 20:04:16 +02007163 cp.le = 0x01;
7164 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007165
7166 /* Check first if we already have the right
7167 * host state (host features set)
7168 */
7169 if (cp.le != lmp_host_le_capable(hdev) ||
7170 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007171 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7172 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007173 }
7174
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007175 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007176 /* Make sure the controller has a good default for
7177 * advertising data. This also applies to the case
7178 * where BR/EDR was toggled during the AUTO_OFF phase.
7179 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007180 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007181 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007182 update_scan_rsp_data(&req);
7183 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007184
Arman Uguray24b4f382015-03-23 15:57:12 -07007185 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7186 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007187 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007188
7189 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007190 }
7191
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007192 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007193 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007194 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7195 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007196
7197 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007198 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007199 write_fast_connectable(&req, true);
7200 else
7201 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007202 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007203 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007204 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007205 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007206 }
7207
Johan Hedberg229ab392013-03-15 17:06:53 -05007208 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007209}
7210
Johan Hedberg744cf192011-11-08 20:40:14 +02007211int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007212{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007213 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007214 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007215 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007216
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007217 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007218 return 0;
7219
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007220 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007221 if (powered_update_hci(hdev) == 0)
7222 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007223
Johan Hedberg229ab392013-03-15 17:06:53 -05007224 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7225 &match);
7226 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007227 }
7228
Johan Hedberg229ab392013-03-15 17:06:53 -05007229 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007230
7231 /* If the power off is because of hdev unregistration let
7232 * use the appropriate INVALID_INDEX status. Otherwise use
7233 * NOT_POWERED. We cover both scenarios here since later in
7234 * mgmt_index_removed() any hci_conn callbacks will have already
7235 * been triggered, potentially causing misleading DISCONNECTED
7236 * status responses.
7237 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007238 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007239 status = MGMT_STATUS_INVALID_INDEX;
7240 else
7241 status = MGMT_STATUS_NOT_POWERED;
7242
7243 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007244
7245 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007246 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7247 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007248
7249new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007250 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007251
7252 if (match.sk)
7253 sock_put(match.sk);
7254
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007255 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007256}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007257
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007258void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007259{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007260 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007261 u8 status;
7262
Johan Hedberg333ae952015-03-17 13:48:47 +02007263 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007264 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007265 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007266
7267 if (err == -ERFKILL)
7268 status = MGMT_STATUS_RFKILLED;
7269 else
7270 status = MGMT_STATUS_FAILED;
7271
Johan Hedberga69e8372015-03-06 21:08:53 +02007272 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007273
7274 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007275}
7276
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007277void mgmt_discoverable_timeout(struct hci_dev *hdev)
7278{
7279 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007280
7281 hci_dev_lock(hdev);
7282
7283 /* When discoverable timeout triggers, then just make sure
7284 * the limited discoverable flag is cleared. Even in the case
7285 * of a timeout triggered from general discoverable, it is
7286 * safe to unconditionally clear the flag.
7287 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007288 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7289 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007290
7291 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007292 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007293 u8 scan = SCAN_PAGE;
7294 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7295 sizeof(scan), &scan);
7296 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007297 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007298
7299 /* Advertising instances don't use the global discoverable setting, so
7300 * only update AD if advertising was enabled using Set Advertising.
7301 */
7302 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7303 update_adv_data(&req);
7304
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007305 hci_req_run(&req, NULL);
7306
7307 hdev->discov_timeout = 0;
7308
Johan Hedberg9a43e252013-10-20 19:00:07 +03007309 new_settings(hdev, NULL);
7310
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007311 hci_dev_unlock(hdev);
7312}
7313
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007314void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7315 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007316{
Johan Hedberg86742e12011-11-07 23:13:38 +02007317 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007318
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007319 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007320
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007321 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007322 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007323 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007324 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007325 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007326 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007327
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007328 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007329}
Johan Hedbergf7520542011-01-20 12:34:39 +02007330
Johan Hedbergd7b25452014-05-23 13:19:53 +03007331static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7332{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007333 switch (ltk->type) {
7334 case SMP_LTK:
7335 case SMP_LTK_SLAVE:
7336 if (ltk->authenticated)
7337 return MGMT_LTK_AUTHENTICATED;
7338 return MGMT_LTK_UNAUTHENTICATED;
7339 case SMP_LTK_P256:
7340 if (ltk->authenticated)
7341 return MGMT_LTK_P256_AUTH;
7342 return MGMT_LTK_P256_UNAUTH;
7343 case SMP_LTK_P256_DEBUG:
7344 return MGMT_LTK_P256_DEBUG;
7345 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007346
7347 return MGMT_LTK_UNAUTHENTICATED;
7348}
7349
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007350void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007351{
7352 struct mgmt_ev_new_long_term_key ev;
7353
7354 memset(&ev, 0, sizeof(ev));
7355
Marcel Holtmann5192d302014-02-19 17:11:58 -08007356 /* Devices using resolvable or non-resolvable random addresses
7357 * without providing an indentity resolving key don't require
7358 * to store long term keys. Their addresses will change the
7359 * next time around.
7360 *
7361 * Only when a remote device provides an identity address
7362 * make sure the long term key is stored. If the remote
7363 * identity is known, the long term keys are internally
7364 * mapped to the identity address. So allow static random
7365 * and public addresses here.
7366 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007367 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7368 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7369 ev.store_hint = 0x00;
7370 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007371 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007372
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007373 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007374 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007375 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007376 ev.key.enc_size = key->enc_size;
7377 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007378 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007379
Johan Hedberg2ceba532014-06-16 19:25:16 +03007380 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007381 ev.key.master = 1;
7382
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007383 memcpy(ev.key.val, key->val, sizeof(key->val));
7384
Marcel Holtmann083368f2013-10-15 14:26:29 -07007385 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007386}
7387
Johan Hedberg95fbac82014-02-19 15:18:31 +02007388void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7389{
7390 struct mgmt_ev_new_irk ev;
7391
7392 memset(&ev, 0, sizeof(ev));
7393
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007394 /* For identity resolving keys from devices that are already
7395 * using a public address or static random address, do not
7396 * ask for storing this key. The identity resolving key really
7397 * is only mandatory for devices using resovlable random
7398 * addresses.
7399 *
7400 * Storing all identity resolving keys has the downside that
7401 * they will be also loaded on next boot of they system. More
7402 * identity resolving keys, means more time during scanning is
7403 * needed to actually resolve these addresses.
7404 */
7405 if (bacmp(&irk->rpa, BDADDR_ANY))
7406 ev.store_hint = 0x01;
7407 else
7408 ev.store_hint = 0x00;
7409
Johan Hedberg95fbac82014-02-19 15:18:31 +02007410 bacpy(&ev.rpa, &irk->rpa);
7411 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7412 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7413 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7414
7415 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7416}
7417
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007418void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7419 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007420{
7421 struct mgmt_ev_new_csrk ev;
7422
7423 memset(&ev, 0, sizeof(ev));
7424
7425 /* Devices using resolvable or non-resolvable random addresses
7426 * without providing an indentity resolving key don't require
7427 * to store signature resolving keys. Their addresses will change
7428 * the next time around.
7429 *
7430 * Only when a remote device provides an identity address
7431 * make sure the signature resolving key is stored. So allow
7432 * static random and public addresses here.
7433 */
7434 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7435 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7436 ev.store_hint = 0x00;
7437 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007438 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007439
7440 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7441 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007442 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007443 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7444
7445 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7446}
7447
Andre Guedesffb5a8272014-07-01 18:10:11 -03007448void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007449 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7450 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007451{
7452 struct mgmt_ev_new_conn_param ev;
7453
Johan Hedbergc103aea2014-07-02 17:37:34 +03007454 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7455 return;
7456
Andre Guedesffb5a8272014-07-01 18:10:11 -03007457 memset(&ev, 0, sizeof(ev));
7458 bacpy(&ev.addr.bdaddr, bdaddr);
7459 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007460 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007461 ev.min_interval = cpu_to_le16(min_interval);
7462 ev.max_interval = cpu_to_le16(max_interval);
7463 ev.latency = cpu_to_le16(latency);
7464 ev.timeout = cpu_to_le16(timeout);
7465
7466 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7467}
7468
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007469void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7470 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007471{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007472 char buf[512];
7473 struct mgmt_ev_device_connected *ev = (void *) buf;
7474 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007475
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007476 bacpy(&ev->addr.bdaddr, &conn->dst);
7477 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007478
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007479 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007480
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007481 /* We must ensure that the EIR Data fields are ordered and
7482 * unique. Keep it simple for now and avoid the problem by not
7483 * adding any BR/EDR data to the LE adv.
7484 */
7485 if (conn->le_adv_data_len > 0) {
7486 memcpy(&ev->eir[eir_len],
7487 conn->le_adv_data, conn->le_adv_data_len);
7488 eir_len = conn->le_adv_data_len;
7489 } else {
7490 if (name_len > 0)
7491 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7492 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007493
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007494 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007495 eir_len = eir_append_data(ev->eir, eir_len,
7496 EIR_CLASS_OF_DEV,
7497 conn->dev_class, 3);
7498 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007499
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007500 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007501
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007502 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7503 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007504}
7505
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007506static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007507{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007508 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007509
Johan Hedbergf5818c22014-12-05 13:36:02 +02007510 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007511
7512 *sk = cmd->sk;
7513 sock_hold(*sk);
7514
Johan Hedberga664b5b2011-02-19 12:06:02 -03007515 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007516}
7517
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007518static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007519{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007520 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007521 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007522
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007523 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7524
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007525 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007526 mgmt_pending_remove(cmd);
7527}
7528
Johan Hedberg84c61d92014-08-01 11:13:30 +03007529bool mgmt_powering_down(struct hci_dev *hdev)
7530{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007531 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007532 struct mgmt_mode *cp;
7533
Johan Hedberg333ae952015-03-17 13:48:47 +02007534 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007535 if (!cmd)
7536 return false;
7537
7538 cp = cmd->param;
7539 if (!cp->val)
7540 return true;
7541
7542 return false;
7543}
7544
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007545void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007546 u8 link_type, u8 addr_type, u8 reason,
7547 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007548{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007549 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007550 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007551
Johan Hedberg84c61d92014-08-01 11:13:30 +03007552 /* The connection is still in hci_conn_hash so test for 1
7553 * instead of 0 to know if this is the last one.
7554 */
7555 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7556 cancel_delayed_work(&hdev->power_off);
7557 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007558 }
7559
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007560 if (!mgmt_connected)
7561 return;
7562
Andre Guedes57eb7762013-10-30 19:01:41 -03007563 if (link_type != ACL_LINK && link_type != LE_LINK)
7564 return;
7565
Johan Hedberg744cf192011-11-08 20:40:14 +02007566 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007567
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007568 bacpy(&ev.addr.bdaddr, bdaddr);
7569 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7570 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007571
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007572 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007573
7574 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007575 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007576
Johan Hedberg124f6e32012-02-09 13:50:12 +02007577 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007578 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007579}
7580
Marcel Holtmann78929242013-10-06 23:55:47 -07007581void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7582 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007583{
Andre Guedes3655bba2013-10-30 19:01:40 -03007584 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7585 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007586 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007587
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007588 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7589 hdev);
7590
Johan Hedberg333ae952015-03-17 13:48:47 +02007591 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007592 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007593 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007594
Andre Guedes3655bba2013-10-30 19:01:40 -03007595 cp = cmd->param;
7596
7597 if (bacmp(bdaddr, &cp->addr.bdaddr))
7598 return;
7599
7600 if (cp->addr.type != bdaddr_type)
7601 return;
7602
Johan Hedbergf5818c22014-12-05 13:36:02 +02007603 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007604 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007605}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007606
Marcel Holtmann445608d2013-10-06 23:55:48 -07007607void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7608 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007609{
7610 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007611
Johan Hedberg84c61d92014-08-01 11:13:30 +03007612 /* The connection is still in hci_conn_hash so test for 1
7613 * instead of 0 to know if this is the last one.
7614 */
7615 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7616 cancel_delayed_work(&hdev->power_off);
7617 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007618 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007619
Johan Hedberg4c659c32011-11-07 23:13:39 +02007620 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007621 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007622 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007623
Marcel Holtmann445608d2013-10-06 23:55:48 -07007624 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007625}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007626
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007627void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007628{
7629 struct mgmt_ev_pin_code_request ev;
7630
Johan Hedbergd8457692012-02-17 14:24:57 +02007631 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007632 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007633 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007634
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007635 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007636}
7637
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007638void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7639 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007640{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007641 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007642
Johan Hedberg333ae952015-03-17 13:48:47 +02007643 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007644 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007645 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007646
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007647 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007648 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007649}
7650
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007651void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7652 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007653{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007654 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007655
Johan Hedberg333ae952015-03-17 13:48:47 +02007656 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007657 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007658 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007659
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007660 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007661 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007662}
Johan Hedberga5c29682011-02-19 12:05:57 -03007663
Johan Hedberg744cf192011-11-08 20:40:14 +02007664int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007665 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007666 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007667{
7668 struct mgmt_ev_user_confirm_request ev;
7669
Johan Hedberg744cf192011-11-08 20:40:14 +02007670 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007671
Johan Hedberg272d90d2012-02-09 15:26:12 +02007672 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007673 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007674 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007675 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007676
Johan Hedberg744cf192011-11-08 20:40:14 +02007677 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007678 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007679}
7680
Johan Hedberg272d90d2012-02-09 15:26:12 +02007681int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007682 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007683{
7684 struct mgmt_ev_user_passkey_request ev;
7685
7686 BT_DBG("%s", hdev->name);
7687
Johan Hedberg272d90d2012-02-09 15:26:12 +02007688 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007689 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007690
7691 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007692 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007693}
7694
Brian Gix0df4c182011-11-16 13:53:13 -08007695static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007696 u8 link_type, u8 addr_type, u8 status,
7697 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007698{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007699 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007700
Johan Hedberg333ae952015-03-17 13:48:47 +02007701 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007702 if (!cmd)
7703 return -ENOENT;
7704
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007705 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007706 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007707
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007708 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007709}
7710
Johan Hedberg744cf192011-11-08 20:40:14 +02007711int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007712 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007713{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007714 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007715 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007716}
7717
Johan Hedberg272d90d2012-02-09 15:26:12 +02007718int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007719 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007720{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007721 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007722 status,
7723 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007724}
Johan Hedberg2a611692011-02-19 12:06:00 -03007725
Brian Gix604086b2011-11-23 08:28:33 -08007726int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007727 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007728{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007729 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007730 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007731}
7732
Johan Hedberg272d90d2012-02-09 15:26:12 +02007733int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007734 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007735{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007736 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007737 status,
7738 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007739}
7740
Johan Hedberg92a25252012-09-06 18:39:26 +03007741int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7742 u8 link_type, u8 addr_type, u32 passkey,
7743 u8 entered)
7744{
7745 struct mgmt_ev_passkey_notify ev;
7746
7747 BT_DBG("%s", hdev->name);
7748
7749 bacpy(&ev.addr.bdaddr, bdaddr);
7750 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7751 ev.passkey = __cpu_to_le32(passkey);
7752 ev.entered = entered;
7753
7754 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7755}
7756
Johan Hedberge1e930f2014-09-08 17:09:49 -07007757void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007758{
7759 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007760 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007761 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007762
Johan Hedberge1e930f2014-09-08 17:09:49 -07007763 bacpy(&ev.addr.bdaddr, &conn->dst);
7764 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7765 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007766
Johan Hedberge1e930f2014-09-08 17:09:49 -07007767 cmd = find_pairing(conn);
7768
7769 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7770 cmd ? cmd->sk : NULL);
7771
Johan Hedberga511b352014-12-11 21:45:45 +02007772 if (cmd) {
7773 cmd->cmd_complete(cmd, status);
7774 mgmt_pending_remove(cmd);
7775 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007776}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007777
Marcel Holtmann464996a2013-10-15 14:26:24 -07007778void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007779{
7780 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007781 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007782
7783 if (status) {
7784 u8 mgmt_err = mgmt_status(status);
7785 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007786 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007787 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007788 }
7789
Marcel Holtmann464996a2013-10-15 14:26:24 -07007790 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007791 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007792 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007793 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007794
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007795 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007796 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007797
Johan Hedberg47990ea2012-02-22 11:58:37 +02007798 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007799 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007800
7801 if (match.sk)
7802 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007803}
7804
Johan Hedberg890ea892013-03-15 17:06:52 -05007805static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007806{
Johan Hedberg890ea892013-03-15 17:06:52 -05007807 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007808 struct hci_cp_write_eir cp;
7809
Johan Hedberg976eb202012-10-24 21:12:01 +03007810 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007811 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007812
Johan Hedbergc80da272012-02-22 15:38:48 +02007813 memset(hdev->eir, 0, sizeof(hdev->eir));
7814
Johan Hedbergcacaf522012-02-21 00:52:42 +02007815 memset(&cp, 0, sizeof(cp));
7816
Johan Hedberg890ea892013-03-15 17:06:52 -05007817 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007818}
7819
Marcel Holtmann3e248562013-10-15 14:26:25 -07007820void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007821{
7822 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007823 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007824 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007825
7826 if (status) {
7827 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007828
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007829 if (enable && hci_dev_test_and_clear_flag(hdev,
7830 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007831 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007832 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007833 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007834
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007835 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7836 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007837 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007838 }
7839
7840 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007841 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007842 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007843 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007844 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007845 changed = hci_dev_test_and_clear_flag(hdev,
7846 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007847 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007848 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007849 }
7850
7851 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7852
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007853 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007854 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007855
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007856 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007857 sock_put(match.sk);
7858
Johan Hedberg890ea892013-03-15 17:06:52 -05007859 hci_req_init(&req, hdev);
7860
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007861 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7862 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007863 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7864 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007865 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007866 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007867 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007868 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007869
7870 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007871}
7872
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007873static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007874{
7875 struct cmd_lookup *match = data;
7876
Johan Hedberg90e70452012-02-23 23:09:40 +02007877 if (match->sk == NULL) {
7878 match->sk = cmd->sk;
7879 sock_hold(match->sk);
7880 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007881}
7882
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007883void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7884 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007885{
Johan Hedberg90e70452012-02-23 23:09:40 +02007886 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007887
Johan Hedberg92da6092013-03-15 17:06:55 -05007888 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7889 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7890 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007891
7892 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007893 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7894 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007895
7896 if (match.sk)
7897 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007898}
7899
Marcel Holtmann7667da32013-10-15 14:26:27 -07007900void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007901{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007902 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007903 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007904
Johan Hedberg13928972013-03-15 17:07:00 -05007905 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007906 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007907
7908 memset(&ev, 0, sizeof(ev));
7909 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007910 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007911
Johan Hedberg333ae952015-03-17 13:48:47 +02007912 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007913 if (!cmd) {
7914 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007915
Johan Hedberg13928972013-03-15 17:07:00 -05007916 /* If this is a HCI command related to powering on the
7917 * HCI dev don't send any mgmt signals.
7918 */
Johan Hedberg333ae952015-03-17 13:48:47 +02007919 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007920 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007921 }
7922
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007923 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7924 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007925}
Szymon Jancc35938b2011-03-22 13:12:21 +01007926
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007927void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007928 u8 *rand192, u8 *hash256, u8 *rand256,
7929 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007930{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007931 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007932
Johan Hedberg744cf192011-11-08 20:40:14 +02007933 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007934
Johan Hedberg333ae952015-03-17 13:48:47 +02007935 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007936 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007937 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007938
7939 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007940 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7941 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007942 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007943 struct mgmt_rp_read_local_oob_data rp;
7944 size_t rp_size = sizeof(rp);
7945
7946 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7947 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7948
Johan Hedberg710f11c2014-05-26 11:21:22 +03007949 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007950 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007951 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007952 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007953 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007954 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007955
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007956 mgmt_cmd_complete(cmd->sk, hdev->id,
7957 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7958 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007959 }
7960
7961 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007962}
Johan Hedberge17acd42011-03-30 23:57:16 +03007963
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007964static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7965{
7966 int i;
7967
7968 for (i = 0; i < uuid_count; i++) {
7969 if (!memcmp(uuid, uuids[i], 16))
7970 return true;
7971 }
7972
7973 return false;
7974}
7975
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007976static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7977{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007978 u16 parsed = 0;
7979
7980 while (parsed < eir_len) {
7981 u8 field_len = eir[0];
7982 u8 uuid[16];
7983 int i;
7984
7985 if (field_len == 0)
7986 break;
7987
7988 if (eir_len - parsed < field_len + 1)
7989 break;
7990
7991 switch (eir[1]) {
7992 case EIR_UUID16_ALL:
7993 case EIR_UUID16_SOME:
7994 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007995 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007996 uuid[13] = eir[i + 3];
7997 uuid[12] = eir[i + 2];
7998 if (has_uuid(uuid, uuid_count, uuids))
7999 return true;
8000 }
8001 break;
8002 case EIR_UUID32_ALL:
8003 case EIR_UUID32_SOME:
8004 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008005 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008006 uuid[15] = eir[i + 5];
8007 uuid[14] = eir[i + 4];
8008 uuid[13] = eir[i + 3];
8009 uuid[12] = eir[i + 2];
8010 if (has_uuid(uuid, uuid_count, uuids))
8011 return true;
8012 }
8013 break;
8014 case EIR_UUID128_ALL:
8015 case EIR_UUID128_SOME:
8016 for (i = 0; i + 17 <= field_len; i += 16) {
8017 memcpy(uuid, eir + i + 2, 16);
8018 if (has_uuid(uuid, uuid_count, uuids))
8019 return true;
8020 }
8021 break;
8022 }
8023
8024 parsed += field_len + 1;
8025 eir += field_len + 1;
8026 }
8027
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008028 return false;
8029}
8030
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008031static void restart_le_scan(struct hci_dev *hdev)
8032{
8033 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008034 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008035 return;
8036
8037 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8038 hdev->discovery.scan_start +
8039 hdev->discovery.scan_duration))
8040 return;
8041
8042 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8043 DISCOV_LE_RESTART_DELAY);
8044}
8045
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008046static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8047 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8048{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008049 /* If a RSSI threshold has been specified, and
8050 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8051 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8052 * is set, let it through for further processing, as we might need to
8053 * restart the scan.
8054 *
8055 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8056 * the results are also dropped.
8057 */
8058 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8059 (rssi == HCI_RSSI_INVALID ||
8060 (rssi < hdev->discovery.rssi &&
8061 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8062 return false;
8063
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008064 if (hdev->discovery.uuid_count != 0) {
8065 /* If a list of UUIDs is provided in filter, results with no
8066 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008067 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008068 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8069 hdev->discovery.uuids) &&
8070 !eir_has_uuids(scan_rsp, scan_rsp_len,
8071 hdev->discovery.uuid_count,
8072 hdev->discovery.uuids))
8073 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008074 }
8075
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008076 /* If duplicate filtering does not report RSSI changes, then restart
8077 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008078 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008079 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8080 restart_le_scan(hdev);
8081
8082 /* Validate RSSI value against the RSSI threshold once more. */
8083 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8084 rssi < hdev->discovery.rssi)
8085 return false;
8086 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008087
8088 return true;
8089}
8090
Marcel Holtmann901801b2013-10-06 23:55:51 -07008091void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008092 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8093 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008094{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008095 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008096 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008097 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008098
Johan Hedberg75ce2082014-07-02 22:42:01 +03008099 /* Don't send events for a non-kernel initiated discovery. With
8100 * LE one exception is if we have pend_le_reports > 0 in which
8101 * case we're doing passive scanning and want these events.
8102 */
8103 if (!hci_discovery_active(hdev)) {
8104 if (link_type == ACL_LINK)
8105 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008106 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008107 return;
8108 }
Andre Guedes12602d02013-04-30 15:29:40 -03008109
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008110 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008111 /* We are using service discovery */
8112 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8113 scan_rsp_len))
8114 return;
8115 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008116
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008117 /* Make sure that the buffer is big enough. The 5 extra bytes
8118 * are for the potential CoD field.
8119 */
8120 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008121 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008122
Johan Hedberg1dc06092012-01-15 21:01:23 +02008123 memset(buf, 0, sizeof(buf));
8124
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008125 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8126 * RSSI value was reported as 0 when not available. This behavior
8127 * is kept when using device discovery. This is required for full
8128 * backwards compatibility with the API.
8129 *
8130 * However when using service discovery, the value 127 will be
8131 * returned when the RSSI is not available.
8132 */
Szymon Janc91200e92015-01-22 16:57:05 +01008133 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8134 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008135 rssi = 0;
8136
Johan Hedberg841c5642014-07-07 12:45:54 +03008137 bacpy(&ev->addr.bdaddr, bdaddr);
8138 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008139 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008140 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008141
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008142 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008143 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008144 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008145
Johan Hedberg1dc06092012-01-15 21:01:23 +02008146 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8147 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008148 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008149
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008150 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008151 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008152 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008153
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008154 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8155 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008156
Marcel Holtmann901801b2013-10-06 23:55:51 -07008157 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008158}
Johan Hedberga88a9652011-03-30 13:18:12 +03008159
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008160void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8161 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008162{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008163 struct mgmt_ev_device_found *ev;
8164 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8165 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008166
Johan Hedbergb644ba32012-01-17 21:48:47 +02008167 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008168
Johan Hedbergb644ba32012-01-17 21:48:47 +02008169 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008170
Johan Hedbergb644ba32012-01-17 21:48:47 +02008171 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008172 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008173 ev->rssi = rssi;
8174
8175 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008176 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008177
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008178 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008179
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008180 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008181}
Johan Hedberg314b2382011-04-27 10:29:57 -04008182
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008183void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008184{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008185 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008186
Andre Guedes343fb142011-11-22 17:14:19 -03008187 BT_DBG("%s discovering %u", hdev->name, discovering);
8188
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008189 memset(&ev, 0, sizeof(ev));
8190 ev.type = hdev->discovery.type;
8191 ev.discovering = discovering;
8192
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008193 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008194}
Antti Julku5e762442011-08-25 16:48:02 +03008195
Marcel Holtmann1904a852015-01-11 13:50:44 -08008196static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008197{
8198 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008199}
8200
8201void mgmt_reenable_advertising(struct hci_dev *hdev)
8202{
8203 struct hci_request req;
8204
Arman Uguray24b4f382015-03-23 15:57:12 -07008205 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8206 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008207 return;
8208
8209 hci_req_init(&req, hdev);
8210 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008211 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008212}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008213
8214static struct hci_mgmt_chan chan = {
8215 .channel = HCI_CHANNEL_CONTROL,
8216 .handler_count = ARRAY_SIZE(mgmt_handlers),
8217 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008218 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008219};
8220
8221int mgmt_init(void)
8222{
8223 return hci_mgmt_chan_register(&chan);
8224}
8225
8226void mgmt_exit(void)
8227{
8228 hci_mgmt_chan_unregister(&chan);
8229}