blob: a8319f6cfa65d5520430a5ba2e05aaaa6b4531ed [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
Marcel Holtmann38c8af62015-04-03 13:23:12 -07001046 if (instance) {
1047 memcpy(ptr, hdev->adv_instance.adv_data,
1048 hdev->adv_instance.adv_data_len);
1049
1050 ad_len += hdev->adv_instance.adv_data_len;
1051 ptr += hdev->adv_instance.adv_data_len;
1052 }
1053
Arman Ugurayfdf51782015-03-25 18:53:46 -07001054 /* Provide Tx Power only if we can provide a valid value for it */
1055 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1056 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1057 ptr[0] = 0x02;
1058 ptr[1] = EIR_TX_POWER;
1059 ptr[2] = (u8)hdev->adv_tx_power;
1060
1061 ad_len += 3;
1062 ptr += 3;
1063 }
1064
Arman Ugurayfdf51782015-03-25 18:53:46 -07001065 return ad_len;
1066}
1067
1068static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
1069{
1070 struct hci_dev *hdev = req->hdev;
1071 struct hci_cp_le_set_adv_data cp;
1072 u8 len;
1073
1074 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1075 return;
1076
1077 memset(&cp, 0, sizeof(cp));
1078
1079 len = create_instance_adv_data(hdev, instance, cp.data);
1080
1081 /* There's nothing to do if the data hasn't changed */
1082 if (hdev->adv_data_len == len &&
1083 memcmp(cp.data, hdev->adv_data, len) == 0)
1084 return;
1085
1086 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1087 hdev->adv_data_len = len;
1088
1089 cp.length = len;
1090
1091 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1092}
1093
Arman Uguraye7a685d2015-03-25 18:53:40 -07001094static void update_adv_data(struct hci_request *req)
1095{
1096 struct hci_dev *hdev = req->hdev;
1097 u8 instance = get_current_adv_instance(hdev);
Arman Uguray24b4f382015-03-23 15:57:12 -07001098
1099 update_adv_data_for_instance(req, instance);
1100}
1101
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001102int mgmt_update_adv_data(struct hci_dev *hdev)
1103{
1104 struct hci_request req;
1105
1106 hci_req_init(&req, hdev);
1107 update_adv_data(&req);
1108
1109 return hci_req_run(&req, NULL);
1110}
1111
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001112static void create_eir(struct hci_dev *hdev, u8 *data)
1113{
1114 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001115 size_t name_len;
1116
1117 name_len = strlen(hdev->dev_name);
1118
1119 if (name_len > 0) {
1120 /* EIR Data type */
1121 if (name_len > 48) {
1122 name_len = 48;
1123 ptr[1] = EIR_NAME_SHORT;
1124 } else
1125 ptr[1] = EIR_NAME_COMPLETE;
1126
1127 /* EIR Data length */
1128 ptr[0] = name_len + 1;
1129
1130 memcpy(ptr + 2, hdev->dev_name, name_len);
1131
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001132 ptr += (name_len + 2);
1133 }
1134
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001135 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001136 ptr[0] = 2;
1137 ptr[1] = EIR_TX_POWER;
1138 ptr[2] = (u8) hdev->inq_tx_power;
1139
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001140 ptr += 3;
1141 }
1142
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001143 if (hdev->devid_source > 0) {
1144 ptr[0] = 9;
1145 ptr[1] = EIR_DEVICE_ID;
1146
1147 put_unaligned_le16(hdev->devid_source, ptr + 2);
1148 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1149 put_unaligned_le16(hdev->devid_product, ptr + 6);
1150 put_unaligned_le16(hdev->devid_version, ptr + 8);
1151
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001152 ptr += 10;
1153 }
1154
Johan Hedberg213202e2013-01-27 00:31:33 +02001155 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001156 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001157 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001158}
1159
Johan Hedberg890ea892013-03-15 17:06:52 -05001160static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001161{
Johan Hedberg890ea892013-03-15 17:06:52 -05001162 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001163 struct hci_cp_write_eir cp;
1164
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001165 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001166 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001167
Johan Hedberg976eb202012-10-24 21:12:01 +03001168 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001169 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001170
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001171 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001172 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001173
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001174 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001175 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001176
1177 memset(&cp, 0, sizeof(cp));
1178
1179 create_eir(hdev, cp.data);
1180
1181 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001182 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001183
1184 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1185
Johan Hedberg890ea892013-03-15 17:06:52 -05001186 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001187}
1188
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001189static u8 get_service_classes(struct hci_dev *hdev)
1190{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001191 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001192 u8 val = 0;
1193
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001194 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001195 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001196
1197 return val;
1198}
1199
Johan Hedberg890ea892013-03-15 17:06:52 -05001200static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001201{
Johan Hedberg890ea892013-03-15 17:06:52 -05001202 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001203 u8 cod[3];
1204
1205 BT_DBG("%s", hdev->name);
1206
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001207 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001208 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001209
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001210 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001211 return;
1212
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001213 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001214 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001215
1216 cod[0] = hdev->minor_class;
1217 cod[1] = hdev->major_class;
1218 cod[2] = get_service_classes(hdev);
1219
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001220 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001221 cod[1] |= 0x20;
1222
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001223 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001224 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001225
Johan Hedberg890ea892013-03-15 17:06:52 -05001226 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001227}
1228
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001229static void disable_advertising(struct hci_request *req)
1230{
1231 u8 enable = 0x00;
1232
1233 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1234}
1235
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001236static void enable_advertising(struct hci_request *req)
1237{
1238 struct hci_dev *hdev = req->hdev;
1239 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001240 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001241 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001242 u8 instance;
1243 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001244
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001245 if (hci_conn_num(hdev, LE_LINK) > 0)
1246 return;
1247
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001248 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001249 disable_advertising(req);
1250
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001251 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001252 * hci_update_random_address knows that it's safe to go ahead
1253 * and write a new random address. The flag will be set back on
1254 * as soon as the SET_ADV_ENABLE HCI command completes.
1255 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001256 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001257
Arman Uguraye7a685d2015-03-25 18:53:40 -07001258 instance = get_current_adv_instance(hdev);
1259 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001260
1261 /* If the "connectable" instance flag was not set, then choose between
1262 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1263 */
1264 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1265 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001266
Johan Hedberga4858cb2014-02-25 19:56:31 +02001267 /* Set require_privacy to true only when non-connectable
1268 * advertising is used. In that case it is fine to use a
1269 * non-resolvable private address.
1270 */
1271 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001272 return;
1273
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001274 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001275 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1276 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001277
1278 if (connectable)
1279 cp.type = LE_ADV_IND;
1280 else if (get_adv_instance_scan_rsp_len(hdev, instance))
1281 cp.type = LE_ADV_SCAN_IND;
1282 else
1283 cp.type = LE_ADV_NONCONN_IND;
1284
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001285 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001286 cp.channel_map = hdev->le_adv_channel_map;
1287
1288 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1289
1290 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1291}
1292
Johan Hedberg7d785252011-12-15 00:47:39 +02001293static void service_cache_off(struct work_struct *work)
1294{
1295 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001296 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001297 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001298
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001299 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001300 return;
1301
Johan Hedberg890ea892013-03-15 17:06:52 -05001302 hci_req_init(&req, hdev);
1303
Johan Hedberg7d785252011-12-15 00:47:39 +02001304 hci_dev_lock(hdev);
1305
Johan Hedberg890ea892013-03-15 17:06:52 -05001306 update_eir(&req);
1307 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001308
1309 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001310
1311 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001312}
1313
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001314static void rpa_expired(struct work_struct *work)
1315{
1316 struct hci_dev *hdev = container_of(work, struct hci_dev,
1317 rpa_expired.work);
1318 struct hci_request req;
1319
1320 BT_DBG("");
1321
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001322 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001323
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001324 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001325 return;
1326
1327 /* The generation of a new RPA and programming it into the
1328 * controller happens in the enable_advertising() function.
1329 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001330 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001331 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001332 hci_req_run(&req, NULL);
1333}
1334
Johan Hedberg6a919082012-02-28 06:17:26 +02001335static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001336{
Marcel Holtmann238be782015-03-13 02:11:06 -07001337 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001338 return;
1339
Johan Hedberg4f87da82012-03-02 19:55:56 +02001340 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001341 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001342
Johan Hedberg4f87da82012-03-02 19:55:56 +02001343 /* Non-mgmt controlled devices get this bit set
1344 * implicitly so that pairing works for them, however
1345 * for mgmt we require user-space to explicitly enable
1346 * it
1347 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001348 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001349}
1350
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001351static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001352 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001353{
1354 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001355
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001356 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001357
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001358 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001359
Johan Hedberg03811012010-12-08 00:21:06 +02001360 memset(&rp, 0, sizeof(rp));
1361
Johan Hedberg03811012010-12-08 00:21:06 +02001362 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001363
1364 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001365 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001366
1367 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1368 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1369
1370 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001371
1372 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001373 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001374
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001375 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001376
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001377 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1378 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001379}
1380
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001381static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001382{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001383 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001385 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1386 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001387}
1388
Marcel Holtmann1904a852015-01-11 13:50:44 -08001389static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001390{
1391 BT_DBG("%s status 0x%02x", hdev->name, status);
1392
Johan Hedberga3172b72014-02-28 09:33:44 +02001393 if (hci_conn_count(hdev) == 0) {
1394 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001395 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001396 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001397}
1398
Johan Hedberg23a48092014-07-08 16:05:06 +03001399static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001400{
1401 struct hci_dev *hdev = req->hdev;
1402 struct hci_cp_remote_name_req_cancel cp;
1403 struct inquiry_entry *e;
1404
1405 switch (hdev->discovery.state) {
1406 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001407 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001408 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001409
1410 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001411 cancel_delayed_work(&hdev->le_scan_disable);
1412 hci_req_add_le_scan_disable(req);
1413 }
1414
Johan Hedberg23a48092014-07-08 16:05:06 +03001415 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001416
1417 case DISCOVERY_RESOLVING:
1418 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1419 NAME_PENDING);
1420 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001421 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001422
1423 bacpy(&cp.bdaddr, &e->data.bdaddr);
1424 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1425 &cp);
1426
Johan Hedberg23a48092014-07-08 16:05:06 +03001427 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001428
1429 default:
1430 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001431 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001432 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001433 return true;
1434 }
1435
Johan Hedberg21a60d32014-06-10 14:05:58 +03001436 break;
1437 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001438
1439 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001440}
1441
Arman Uguray912098a2015-03-23 15:57:15 -07001442static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1443 u8 instance)
1444{
1445 struct mgmt_ev_advertising_added ev;
1446
1447 ev.instance = instance;
1448
1449 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1450}
1451
1452static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1453 u8 instance)
1454{
1455 struct mgmt_ev_advertising_removed ev;
1456
1457 ev.instance = instance;
1458
1459 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1460}
1461
1462static void clear_adv_instance(struct hci_dev *hdev)
1463{
1464 struct hci_request req;
1465
1466 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1467 return;
1468
Florian Grandel5d900e42015-06-18 03:16:35 +02001469 if (hdev->adv_instance_timeout)
1470 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07001471
1472 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1473 advertising_removed(NULL, hdev, 1);
1474 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1475
1476 if (!hdev_is_powered(hdev) ||
1477 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1478 return;
1479
1480 hci_req_init(&req, hdev);
1481 disable_advertising(&req);
1482 hci_req_run(&req, NULL);
1483}
1484
Johan Hedberg8b064a32014-02-24 14:52:22 +02001485static int clean_up_hci_state(struct hci_dev *hdev)
1486{
1487 struct hci_request req;
1488 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001489 bool discov_stopped;
1490 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001491
1492 hci_req_init(&req, hdev);
1493
1494 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1495 test_bit(HCI_PSCAN, &hdev->flags)) {
1496 u8 scan = 0x00;
1497 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1498 }
1499
Florian Grandel5d900e42015-06-18 03:16:35 +02001500 if (hdev->adv_instance_timeout)
Arman Uguray912098a2015-03-23 15:57:15 -07001501 clear_adv_instance(hdev);
1502
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001503 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001504 disable_advertising(&req);
1505
Johan Hedberg23a48092014-07-08 16:05:06 +03001506 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001507
1508 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1509 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001510 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001511
Johan Hedbergc9910d02014-02-27 14:35:12 +02001512 switch (conn->state) {
1513 case BT_CONNECTED:
1514 case BT_CONFIG:
1515 dc.handle = cpu_to_le16(conn->handle);
1516 dc.reason = 0x15; /* Terminated due to Power Off */
1517 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1518 break;
1519 case BT_CONNECT:
1520 if (conn->type == LE_LINK)
1521 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1522 0, NULL);
1523 else if (conn->type == ACL_LINK)
1524 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1525 6, &conn->dst);
1526 break;
1527 case BT_CONNECT2:
1528 bacpy(&rej.bdaddr, &conn->dst);
1529 rej.reason = 0x15; /* Terminated due to Power Off */
1530 if (conn->type == ACL_LINK)
1531 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1532 sizeof(rej), &rej);
1533 else if (conn->type == SCO_LINK)
1534 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1535 sizeof(rej), &rej);
1536 break;
1537 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001538 }
1539
Johan Hedberg23a48092014-07-08 16:05:06 +03001540 err = hci_req_run(&req, clean_up_hci_complete);
1541 if (!err && discov_stopped)
1542 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1543
1544 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001545}
1546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001547static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001548 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001549{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001550 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001551 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001552 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001554 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001555
Johan Hedberga7e80f22013-01-09 16:05:19 +02001556 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001557 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1558 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001559
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001560 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001561
Johan Hedberg333ae952015-03-17 13:48:47 +02001562 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001563 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1564 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001565 goto failed;
1566 }
1567
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001568 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001569 cancel_delayed_work(&hdev->power_off);
1570
1571 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001572 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1573 data, len);
1574 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001575 goto failed;
1576 }
1577 }
1578
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001579 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001580 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001581 goto failed;
1582 }
1583
Johan Hedberg03811012010-12-08 00:21:06 +02001584 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1585 if (!cmd) {
1586 err = -ENOMEM;
1587 goto failed;
1588 }
1589
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001591 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001592 err = 0;
1593 } else {
1594 /* Disconnect connections, stop scans, etc */
1595 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001596 if (!err)
1597 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1598 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001599
Johan Hedberg8b064a32014-02-24 14:52:22 +02001600 /* ENODATA means there were no HCI commands queued */
1601 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001602 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001603 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1604 err = 0;
1605 }
1606 }
Johan Hedberg03811012010-12-08 00:21:06 +02001607
1608failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001609 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001610 return err;
1611}
1612
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001613static int new_settings(struct hci_dev *hdev, struct sock *skip)
1614{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001615 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001616
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001617 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1618 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001619}
1620
Johan Hedberg91a668b2014-07-09 13:28:26 +03001621int mgmt_new_settings(struct hci_dev *hdev)
1622{
1623 return new_settings(hdev, NULL);
1624}
1625
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001626struct cmd_lookup {
1627 struct sock *sk;
1628 struct hci_dev *hdev;
1629 u8 mgmt_status;
1630};
1631
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001632static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001633{
1634 struct cmd_lookup *match = data;
1635
1636 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1637
1638 list_del(&cmd->list);
1639
1640 if (match->sk == NULL) {
1641 match->sk = cmd->sk;
1642 sock_hold(match->sk);
1643 }
1644
1645 mgmt_pending_free(cmd);
1646}
1647
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001648static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001649{
1650 u8 *status = data;
1651
Johan Hedberga69e8372015-03-06 21:08:53 +02001652 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001653 mgmt_pending_remove(cmd);
1654}
1655
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001656static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001657{
1658 if (cmd->cmd_complete) {
1659 u8 *status = data;
1660
1661 cmd->cmd_complete(cmd, *status);
1662 mgmt_pending_remove(cmd);
1663
1664 return;
1665 }
1666
1667 cmd_status_rsp(cmd, data);
1668}
1669
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001670static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001671{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001672 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1673 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001674}
1675
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001676static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001677{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001678 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1679 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001680}
1681
Johan Hedberge6fe7982013-10-02 15:45:22 +03001682static u8 mgmt_bredr_support(struct hci_dev *hdev)
1683{
1684 if (!lmp_bredr_capable(hdev))
1685 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001686 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001687 return MGMT_STATUS_REJECTED;
1688 else
1689 return MGMT_STATUS_SUCCESS;
1690}
1691
1692static u8 mgmt_le_support(struct hci_dev *hdev)
1693{
1694 if (!lmp_le_capable(hdev))
1695 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001696 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001697 return MGMT_STATUS_REJECTED;
1698 else
1699 return MGMT_STATUS_SUCCESS;
1700}
1701
Marcel Holtmann1904a852015-01-11 13:50:44 -08001702static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1703 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001704{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001705 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001706 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001707 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001708 bool changed;
1709
1710 BT_DBG("status 0x%02x", status);
1711
1712 hci_dev_lock(hdev);
1713
Johan Hedberg333ae952015-03-17 13:48:47 +02001714 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001715 if (!cmd)
1716 goto unlock;
1717
1718 if (status) {
1719 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001720 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001721 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001722 goto remove_cmd;
1723 }
1724
1725 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001726 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001727 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001728
1729 if (hdev->discov_timeout > 0) {
1730 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1731 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1732 to);
1733 }
1734 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001735 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001736 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737
1738 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1739
1740 if (changed)
1741 new_settings(hdev, cmd->sk);
1742
Marcel Holtmann970ba522013-10-15 06:33:57 -07001743 /* When the discoverable mode gets changed, make sure
1744 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001745 * bit correctly set. Also update page scan based on whitelist
1746 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001747 */
1748 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001749 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001750 update_class(&req);
1751 hci_req_run(&req, NULL);
1752
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001753remove_cmd:
1754 mgmt_pending_remove(cmd);
1755
1756unlock:
1757 hci_dev_unlock(hdev);
1758}
1759
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001760static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001761 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001762{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001763 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001764 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001765 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001766 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001767 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001768 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001769
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001770 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001771
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001772 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1773 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001774 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1775 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001776
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001777 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001778 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1779 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001780
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001781 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001782
1783 /* Disabling discoverable requires that no timeout is set,
1784 * and enabling limited discoverable requires a timeout.
1785 */
1786 if ((cp->val == 0x00 && timeout > 0) ||
1787 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001788 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1789 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001790
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001791 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001792
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001793 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001794 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1795 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001796 goto failed;
1797 }
1798
Johan Hedberg333ae952015-03-17 13:48:47 +02001799 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1800 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001801 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1802 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001803 goto failed;
1804 }
1805
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001806 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001807 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1808 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001809 goto failed;
1810 }
1811
1812 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001813 bool changed = false;
1814
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001815 /* Setting limited discoverable when powered off is
1816 * not a valid operation since it requires a timeout
1817 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1818 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001819 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001820 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001821 changed = true;
1822 }
1823
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001824 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001825 if (err < 0)
1826 goto failed;
1827
1828 if (changed)
1829 err = new_settings(hdev, sk);
1830
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001831 goto failed;
1832 }
1833
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001834 /* If the current mode is the same, then just update the timeout
1835 * value with the new value. And if only the timeout gets updated,
1836 * then no need for any HCI transactions.
1837 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001838 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1839 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1840 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001841 cancel_delayed_work(&hdev->discov_off);
1842 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001843
Marcel Holtmann36261542013-10-15 08:28:51 -07001844 if (cp->val && hdev->discov_timeout > 0) {
1845 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001846 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001847 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001848 }
1849
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001850 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001851 goto failed;
1852 }
1853
1854 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1855 if (!cmd) {
1856 err = -ENOMEM;
1857 goto failed;
1858 }
1859
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001860 /* Cancel any potential discoverable timeout that might be
1861 * still active and store new timeout value. The arming of
1862 * the timeout happens in the complete handler.
1863 */
1864 cancel_delayed_work(&hdev->discov_off);
1865 hdev->discov_timeout = timeout;
1866
Johan Hedbergb456f872013-10-19 23:38:22 +03001867 /* Limited discoverable mode */
1868 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001869 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001870 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001871 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001872
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001873 hci_req_init(&req, hdev);
1874
Johan Hedberg9a43e252013-10-20 19:00:07 +03001875 /* The procedure for LE-only controllers is much simpler - just
1876 * update the advertising data.
1877 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001878 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001879 goto update_ad;
1880
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001881 scan = SCAN_PAGE;
1882
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001883 if (cp->val) {
1884 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001885
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001886 if (cp->val == 0x02) {
1887 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001888 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001889 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1890 hci_cp.iac_lap[1] = 0x8b;
1891 hci_cp.iac_lap[2] = 0x9e;
1892 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1893 hci_cp.iac_lap[4] = 0x8b;
1894 hci_cp.iac_lap[5] = 0x9e;
1895 } else {
1896 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001897 hci_cp.num_iac = 1;
1898 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1899 hci_cp.iac_lap[1] = 0x8b;
1900 hci_cp.iac_lap[2] = 0x9e;
1901 }
1902
1903 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1904 (hci_cp.num_iac * 3) + 1, &hci_cp);
1905
1906 scan |= SCAN_INQUIRY;
1907 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001908 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001909 }
1910
1911 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001912
Johan Hedberg9a43e252013-10-20 19:00:07 +03001913update_ad:
1914 update_adv_data(&req);
1915
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001916 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001917 if (err < 0)
1918 mgmt_pending_remove(cmd);
1919
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001920failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001921 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001922 return err;
1923}
1924
Johan Hedberg406d7802013-03-15 17:07:09 -05001925static void write_fast_connectable(struct hci_request *req, bool enable)
1926{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001927 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001928 struct hci_cp_write_page_scan_activity acp;
1929 u8 type;
1930
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001931 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001932 return;
1933
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001934 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1935 return;
1936
Johan Hedberg406d7802013-03-15 17:07:09 -05001937 if (enable) {
1938 type = PAGE_SCAN_TYPE_INTERLACED;
1939
1940 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001941 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001942 } else {
1943 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1944
1945 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001946 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001947 }
1948
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001949 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001950
Johan Hedbergbd98b992013-03-15 17:07:13 -05001951 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1952 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1953 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1954 sizeof(acp), &acp);
1955
1956 if (hdev->page_scan_type != type)
1957 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001958}
1959
Marcel Holtmann1904a852015-01-11 13:50:44 -08001960static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1961 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001962{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001963 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001964 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001965 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001966
1967 BT_DBG("status 0x%02x", status);
1968
1969 hci_dev_lock(hdev);
1970
Johan Hedberg333ae952015-03-17 13:48:47 +02001971 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001972 if (!cmd)
1973 goto unlock;
1974
Johan Hedberg37438c12013-10-14 16:20:05 +03001975 if (status) {
1976 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001977 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001978 goto remove_cmd;
1979 }
1980
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001981 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001982 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001983 conn_changed = !hci_dev_test_and_set_flag(hdev,
1984 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001985 discov_changed = false;
1986 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001987 conn_changed = hci_dev_test_and_clear_flag(hdev,
1988 HCI_CONNECTABLE);
1989 discov_changed = hci_dev_test_and_clear_flag(hdev,
1990 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001991 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001992
Johan Hedberg2b76f452013-03-15 17:07:04 -05001993 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1994
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001995 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001996 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001997 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001998 if (discov_changed)
1999 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03002000 hci_update_background_scan(hdev);
2001 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002002
Johan Hedberg37438c12013-10-14 16:20:05 +03002003remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002004 mgmt_pending_remove(cmd);
2005
2006unlock:
2007 hci_dev_unlock(hdev);
2008}
2009
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002010static int set_connectable_update_settings(struct hci_dev *hdev,
2011 struct sock *sk, u8 val)
2012{
2013 bool changed = false;
2014 int err;
2015
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002016 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002017 changed = true;
2018
2019 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002020 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002021 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002022 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2023 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002024 }
2025
2026 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2027 if (err < 0)
2028 return err;
2029
Johan Hedberg562064e2014-07-08 16:35:34 +03002030 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002031 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002032 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002033 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002034 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002035
2036 return 0;
2037}
2038
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002039static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002040 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002041{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002042 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002043 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002044 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002045 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002046 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002047
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002048 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002049
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002050 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2051 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002052 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2053 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002054
Johan Hedberga7e80f22013-01-09 16:05:19 +02002055 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002056 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2057 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002058
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002059 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002060
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002061 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002062 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002063 goto failed;
2064 }
2065
Johan Hedberg333ae952015-03-17 13:48:47 +02002066 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2067 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002068 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2069 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002070 goto failed;
2071 }
2072
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002073 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2074 if (!cmd) {
2075 err = -ENOMEM;
2076 goto failed;
2077 }
2078
Johan Hedberg2b76f452013-03-15 17:07:04 -05002079 hci_req_init(&req, hdev);
2080
Johan Hedberg9a43e252013-10-20 19:00:07 +03002081 /* If BR/EDR is not enabled and we disable advertising as a
2082 * by-product of disabling connectable, we need to update the
2083 * advertising flags.
2084 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002085 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002086 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002087 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2088 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002089 }
2090 update_adv_data(&req);
2091 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002092 if (cp->val) {
2093 scan = SCAN_PAGE;
2094 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002095 /* If we don't have any whitelist entries just
2096 * disable all scanning. If there are entries
2097 * and we had both page and inquiry scanning
2098 * enabled then fall back to only page scanning.
2099 * Otherwise no changes are needed.
2100 */
2101 if (list_empty(&hdev->whitelist))
2102 scan = SCAN_DISABLED;
2103 else if (test_bit(HCI_ISCAN, &hdev->flags))
2104 scan = SCAN_PAGE;
2105 else
2106 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002107
2108 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002109 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002110 cancel_delayed_work(&hdev->discov_off);
2111 }
2112
2113 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2114 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002115
Johan Hedberg3bd27242014-07-28 20:53:58 +03002116no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002117 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002118 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2119 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002120 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002121
Johan Hedberg2b76f452013-03-15 17:07:04 -05002122 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002123 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002124 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002125 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002126 err = set_connectable_update_settings(hdev, sk,
2127 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002128 goto failed;
2129 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002130
2131failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002132 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002133 return err;
2134}
2135
Johan Hedbergb2939472014-07-30 09:22:23 +03002136static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002137 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002138{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002139 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002140 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002141 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002142
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002143 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002144
Johan Hedberga7e80f22013-01-09 16:05:19 +02002145 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002146 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2147 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002148
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002149 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002150
2151 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002152 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002153 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002154 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002155
Johan Hedbergb2939472014-07-30 09:22:23 +03002156 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002157 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002158 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002159
Marcel Holtmann55594352013-10-06 16:11:57 -07002160 if (changed)
2161 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002162
Marcel Holtmann55594352013-10-06 16:11:57 -07002163unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002164 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002165 return err;
2166}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002167
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002168static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2169 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002170{
2171 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002172 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002173 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002174 int err;
2175
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002176 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002177
Johan Hedberge6fe7982013-10-02 15:45:22 +03002178 status = mgmt_bredr_support(hdev);
2179 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002180 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2181 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002182
Johan Hedberga7e80f22013-01-09 16:05:19 +02002183 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002184 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2185 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002186
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002187 hci_dev_lock(hdev);
2188
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002189 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002190 bool changed = false;
2191
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002192 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002193 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002194 changed = true;
2195 }
2196
2197 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2198 if (err < 0)
2199 goto failed;
2200
2201 if (changed)
2202 err = new_settings(hdev, sk);
2203
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002204 goto failed;
2205 }
2206
Johan Hedberg333ae952015-03-17 13:48:47 +02002207 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002208 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2209 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002210 goto failed;
2211 }
2212
2213 val = !!cp->val;
2214
2215 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2216 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2217 goto failed;
2218 }
2219
2220 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2221 if (!cmd) {
2222 err = -ENOMEM;
2223 goto failed;
2224 }
2225
2226 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2227 if (err < 0) {
2228 mgmt_pending_remove(cmd);
2229 goto failed;
2230 }
2231
2232failed:
2233 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002234 return err;
2235}
2236
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002237static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002238{
2239 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002240 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002241 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002242 int err;
2243
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002244 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002245
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002246 status = mgmt_bredr_support(hdev);
2247 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002248 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002249
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002250 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002251 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2252 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002253
Johan Hedberga7e80f22013-01-09 16:05:19 +02002254 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002255 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2256 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002257
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002258 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002259
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002260 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002261 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002262
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002263 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002264 changed = !hci_dev_test_and_set_flag(hdev,
2265 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002266 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002267 changed = hci_dev_test_and_clear_flag(hdev,
2268 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002269 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002270 changed = hci_dev_test_and_clear_flag(hdev,
2271 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002272 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002273 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002274 }
2275
2276 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2277 if (err < 0)
2278 goto failed;
2279
2280 if (changed)
2281 err = new_settings(hdev, sk);
2282
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002283 goto failed;
2284 }
2285
Johan Hedberg333ae952015-03-17 13:48:47 +02002286 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002287 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2288 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002289 goto failed;
2290 }
2291
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002292 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002293 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2294 goto failed;
2295 }
2296
2297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2298 if (!cmd) {
2299 err = -ENOMEM;
2300 goto failed;
2301 }
2302
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002303 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002304 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2305 sizeof(cp->val), &cp->val);
2306
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002307 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002308 if (err < 0) {
2309 mgmt_pending_remove(cmd);
2310 goto failed;
2311 }
2312
2313failed:
2314 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002315 return err;
2316}
2317
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002318static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002319{
2320 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002321 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002322 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002323 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002325 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002326
Johan Hedberge6fe7982013-10-02 15:45:22 +03002327 status = mgmt_bredr_support(hdev);
2328 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002329 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002330
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002331 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002332 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2333 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002334
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002335 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002336 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2337 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002338
Johan Hedberga7e80f22013-01-09 16:05:19 +02002339 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002340 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2341 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002342
Marcel Holtmannee392692013-10-01 22:59:23 -07002343 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002344
Johan Hedberg333ae952015-03-17 13:48:47 +02002345 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002346 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2347 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002348 goto unlock;
2349 }
2350
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002351 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002352 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002353 } else {
2354 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002355 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2356 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002357 goto unlock;
2358 }
2359
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002360 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002361 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002362
2363 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2364 if (err < 0)
2365 goto unlock;
2366
2367 if (changed)
2368 err = new_settings(hdev, sk);
2369
2370unlock:
2371 hci_dev_unlock(hdev);
2372 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002373}
2374
Marcel Holtmann1904a852015-01-11 13:50:44 -08002375static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002376{
2377 struct cmd_lookup match = { NULL, hdev };
2378
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302379 hci_dev_lock(hdev);
2380
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002381 if (status) {
2382 u8 mgmt_err = mgmt_status(status);
2383
2384 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2385 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302386 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002387 }
2388
2389 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2390
2391 new_settings(hdev, match.sk);
2392
2393 if (match.sk)
2394 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002395
2396 /* Make sure the controller has a good default for
2397 * advertising data. Restrict the update to when LE
2398 * has actually been enabled. During power on, the
2399 * update in powered_update_hci will take care of it.
2400 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002401 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002402 struct hci_request req;
2403
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002404 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002405 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002406 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002407 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002408 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002409 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302410
2411unlock:
2412 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002413}
2414
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002415static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002416{
2417 struct mgmt_mode *cp = data;
2418 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002419 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002420 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002421 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002422 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002423
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002424 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002425
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002426 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002427 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2428 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002429
Johan Hedberga7e80f22013-01-09 16:05:19 +02002430 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002431 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2432 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002433
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002434 /* Bluetooth single mode LE only controllers or dual-mode
2435 * controllers configured as LE only devices, do not allow
2436 * switching LE off. These have either LE enabled explicitly
2437 * or BR/EDR has been previously switched off.
2438 *
2439 * When trying to enable an already enabled LE, then gracefully
2440 * send a positive response. Trying to disable it however will
2441 * result into rejection.
2442 */
2443 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2444 if (cp->val == 0x01)
2445 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2446
Johan Hedberga69e8372015-03-06 21:08:53 +02002447 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2448 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002449 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002450
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002451 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002452
2453 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002454 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002455
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002456 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002457 bool changed = false;
2458
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002459 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002460 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002461 changed = true;
2462 }
2463
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002464 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002465 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002466 changed = true;
2467 }
2468
Johan Hedberg06199cf2012-02-22 16:37:11 +02002469 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2470 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002471 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002472
2473 if (changed)
2474 err = new_settings(hdev, sk);
2475
Johan Hedberg1de028c2012-02-29 19:55:35 -08002476 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002477 }
2478
Johan Hedberg333ae952015-03-17 13:48:47 +02002479 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2480 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002481 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2482 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002483 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002484 }
2485
2486 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2487 if (!cmd) {
2488 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002489 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002490 }
2491
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002492 hci_req_init(&req, hdev);
2493
Johan Hedberg06199cf2012-02-22 16:37:11 +02002494 memset(&hci_cp, 0, sizeof(hci_cp));
2495
2496 if (val) {
2497 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002498 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002499 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002500 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002501 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002502 }
2503
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002504 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2505 &hci_cp);
2506
2507 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302508 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002509 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002510
Johan Hedberg1de028c2012-02-29 19:55:35 -08002511unlock:
2512 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002513 return err;
2514}
2515
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002516/* This is a helper function to test for pending mgmt commands that can
2517 * cause CoD or EIR HCI commands. We can only allow one such pending
2518 * mgmt command at a time since otherwise we cannot easily track what
2519 * the current values are, will be, and based on that calculate if a new
2520 * HCI command needs to be sent and if yes with what value.
2521 */
2522static bool pending_eir_or_class(struct hci_dev *hdev)
2523{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002524 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002525
2526 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2527 switch (cmd->opcode) {
2528 case MGMT_OP_ADD_UUID:
2529 case MGMT_OP_REMOVE_UUID:
2530 case MGMT_OP_SET_DEV_CLASS:
2531 case MGMT_OP_SET_POWERED:
2532 return true;
2533 }
2534 }
2535
2536 return false;
2537}
2538
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002539static const u8 bluetooth_base_uuid[] = {
2540 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2541 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2542};
2543
2544static u8 get_uuid_size(const u8 *uuid)
2545{
2546 u32 val;
2547
2548 if (memcmp(uuid, bluetooth_base_uuid, 12))
2549 return 128;
2550
2551 val = get_unaligned_le32(&uuid[12]);
2552 if (val > 0xffff)
2553 return 32;
2554
2555 return 16;
2556}
2557
Johan Hedberg92da6092013-03-15 17:06:55 -05002558static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2559{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002560 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002561
2562 hci_dev_lock(hdev);
2563
Johan Hedberg333ae952015-03-17 13:48:47 +02002564 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002565 if (!cmd)
2566 goto unlock;
2567
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002568 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2569 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002570
2571 mgmt_pending_remove(cmd);
2572
2573unlock:
2574 hci_dev_unlock(hdev);
2575}
2576
Marcel Holtmann1904a852015-01-11 13:50:44 -08002577static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002578{
2579 BT_DBG("status 0x%02x", status);
2580
2581 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2582}
2583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002584static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002585{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002586 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002587 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002588 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002589 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002590 int err;
2591
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002593
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002594 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002595
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002596 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002597 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2598 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002599 goto failed;
2600 }
2601
Andre Guedes92c4c202012-06-07 19:05:44 -03002602 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002603 if (!uuid) {
2604 err = -ENOMEM;
2605 goto failed;
2606 }
2607
2608 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002609 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002610 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002611
Johan Hedbergde66aa62013-01-27 00:31:27 +02002612 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002613
Johan Hedberg890ea892013-03-15 17:06:52 -05002614 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002615
Johan Hedberg890ea892013-03-15 17:06:52 -05002616 update_class(&req);
2617 update_eir(&req);
2618
Johan Hedberg92da6092013-03-15 17:06:55 -05002619 err = hci_req_run(&req, add_uuid_complete);
2620 if (err < 0) {
2621 if (err != -ENODATA)
2622 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002623
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002624 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2625 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002626 goto failed;
2627 }
2628
2629 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002630 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002631 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002632 goto failed;
2633 }
2634
2635 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002636
2637failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002638 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002639 return err;
2640}
2641
Johan Hedberg24b78d02012-02-23 23:24:30 +02002642static bool enable_service_cache(struct hci_dev *hdev)
2643{
2644 if (!hdev_is_powered(hdev))
2645 return false;
2646
Marcel Holtmann238be782015-03-13 02:11:06 -07002647 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002648 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2649 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002650 return true;
2651 }
2652
2653 return false;
2654}
2655
Marcel Holtmann1904a852015-01-11 13:50:44 -08002656static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002657{
2658 BT_DBG("status 0x%02x", status);
2659
2660 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2661}
2662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002663static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002664 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002665{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002666 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002667 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002668 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002669 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 -05002670 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002671 int err, found;
2672
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002673 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002674
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002675 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002676
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002677 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002678 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2679 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002680 goto unlock;
2681 }
2682
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002683 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002684 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002685
Johan Hedberg24b78d02012-02-23 23:24:30 +02002686 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002687 err = mgmt_cmd_complete(sk, hdev->id,
2688 MGMT_OP_REMOVE_UUID,
2689 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002690 goto unlock;
2691 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002692
Johan Hedberg9246a862012-02-23 21:33:16 +02002693 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002694 }
2695
2696 found = 0;
2697
Johan Hedberg056341c2013-01-27 00:31:30 +02002698 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002699 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2700 continue;
2701
2702 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002703 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002704 found++;
2705 }
2706
2707 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002708 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2709 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002710 goto unlock;
2711 }
2712
Johan Hedberg9246a862012-02-23 21:33:16 +02002713update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002714 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002715
Johan Hedberg890ea892013-03-15 17:06:52 -05002716 update_class(&req);
2717 update_eir(&req);
2718
Johan Hedberg92da6092013-03-15 17:06:55 -05002719 err = hci_req_run(&req, remove_uuid_complete);
2720 if (err < 0) {
2721 if (err != -ENODATA)
2722 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002723
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002724 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2725 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002726 goto unlock;
2727 }
2728
2729 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002730 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002731 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002732 goto unlock;
2733 }
2734
2735 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002736
2737unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002738 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002739 return err;
2740}
2741
Marcel Holtmann1904a852015-01-11 13:50:44 -08002742static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002743{
2744 BT_DBG("status 0x%02x", status);
2745
2746 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2747}
2748
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002749static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002750 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002751{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002752 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002753 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002754 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002755 int err;
2756
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002757 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002758
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002759 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002760 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2761 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002762
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002763 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002764
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002765 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002766 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2767 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002768 goto unlock;
2769 }
2770
2771 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002772 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2773 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002774 goto unlock;
2775 }
2776
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002777 hdev->major_class = cp->major;
2778 hdev->minor_class = cp->minor;
2779
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002780 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002781 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2782 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002783 goto unlock;
2784 }
2785
Johan Hedberg890ea892013-03-15 17:06:52 -05002786 hci_req_init(&req, hdev);
2787
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002788 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002789 hci_dev_unlock(hdev);
2790 cancel_delayed_work_sync(&hdev->service_cache);
2791 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002792 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002793 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002794
Johan Hedberg890ea892013-03-15 17:06:52 -05002795 update_class(&req);
2796
Johan Hedberg92da6092013-03-15 17:06:55 -05002797 err = hci_req_run(&req, set_class_complete);
2798 if (err < 0) {
2799 if (err != -ENODATA)
2800 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002801
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002802 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2803 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002804 goto unlock;
2805 }
2806
2807 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002808 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002809 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002810 goto unlock;
2811 }
2812
2813 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002814
Johan Hedbergb5235a62012-02-21 14:32:24 +02002815unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002816 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002817 return err;
2818}
2819
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002820static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002821 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002822{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002823 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002824 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2825 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002826 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002827 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002828 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002829
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002830 BT_DBG("request for %s", hdev->name);
2831
2832 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002833 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2834 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002835
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002836 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002837 if (key_count > max_key_count) {
2838 BT_ERR("load_link_keys: too big key_count value %u",
2839 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002840 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2841 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002842 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002843
Johan Hedberg86742e12011-11-07 23:13:38 +02002844 expected_len = sizeof(*cp) + key_count *
2845 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002846 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002847 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002848 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002849 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2850 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002851 }
2852
Johan Hedberg4ae14302013-01-20 14:27:13 +02002853 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002854 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2855 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002856
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002857 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002858 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002859
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002860 for (i = 0; i < key_count; i++) {
2861 struct mgmt_link_key_info *key = &cp->keys[i];
2862
Marcel Holtmann8e991132014-01-10 02:07:25 -08002863 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002864 return mgmt_cmd_status(sk, hdev->id,
2865 MGMT_OP_LOAD_LINK_KEYS,
2866 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002867 }
2868
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002869 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002870
2871 hci_link_keys_clear(hdev);
2872
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002873 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002874 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002875 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002876 changed = hci_dev_test_and_clear_flag(hdev,
2877 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002878
2879 if (changed)
2880 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002881
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002882 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002883 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002884
Johan Hedberg58e92932014-06-24 14:00:26 +03002885 /* Always ignore debug keys and require a new pairing if
2886 * the user wants to use them.
2887 */
2888 if (key->type == HCI_LK_DEBUG_COMBINATION)
2889 continue;
2890
Johan Hedberg7652ff62014-06-24 13:15:49 +03002891 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2892 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002893 }
2894
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002895 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002896
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002897 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002898
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002899 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002900}
2901
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002902static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002903 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002904{
2905 struct mgmt_ev_device_unpaired ev;
2906
2907 bacpy(&ev.addr.bdaddr, bdaddr);
2908 ev.addr.type = addr_type;
2909
2910 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002911 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002912}
2913
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002914static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002915 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002916{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002917 struct mgmt_cp_unpair_device *cp = data;
2918 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002919 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002920 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002921 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002922 int err;
2923
Johan Hedberga8a1d192011-11-10 15:54:38 +02002924 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002925 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2926 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002927
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002928 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002929 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2930 MGMT_STATUS_INVALID_PARAMS,
2931 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002932
Johan Hedberg118da702013-01-20 14:27:20 +02002933 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002934 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2935 MGMT_STATUS_INVALID_PARAMS,
2936 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002937
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002938 hci_dev_lock(hdev);
2939
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002940 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002941 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2942 MGMT_STATUS_NOT_POWERED, &rp,
2943 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002944 goto unlock;
2945 }
2946
Johan Hedberge0b2b272014-02-18 17:14:31 +02002947 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002948 /* If disconnection is requested, then look up the
2949 * connection. If the remote device is connected, it
2950 * will be later used to terminate the link.
2951 *
2952 * Setting it to NULL explicitly will cause no
2953 * termination of the link.
2954 */
2955 if (cp->disconnect)
2956 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2957 &cp->addr.bdaddr);
2958 else
2959 conn = NULL;
2960
Johan Hedberg124f6e32012-02-09 13:50:12 +02002961 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002962 } else {
2963 u8 addr_type;
2964
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002965 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2966 &cp->addr.bdaddr);
2967 if (conn) {
2968 /* Defer clearing up the connection parameters
2969 * until closing to give a chance of keeping
2970 * them if a repairing happens.
2971 */
2972 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2973
2974 /* If disconnection is not requested, then
2975 * clear the connection variable so that the
2976 * link is not terminated.
2977 */
2978 if (!cp->disconnect)
2979 conn = NULL;
2980 }
2981
Johan Hedberge0b2b272014-02-18 17:14:31 +02002982 if (cp->addr.type == BDADDR_LE_PUBLIC)
2983 addr_type = ADDR_LE_DEV_PUBLIC;
2984 else
2985 addr_type = ADDR_LE_DEV_RANDOM;
2986
Johan Hedberga7ec7332014-02-18 17:14:35 +02002987 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2988
Johan Hedberge0b2b272014-02-18 17:14:31 +02002989 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2990 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002991
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002992 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002993 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2994 MGMT_STATUS_NOT_PAIRED, &rp,
2995 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002996 goto unlock;
2997 }
2998
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002999 /* If the connection variable is set, then termination of the
3000 * link is requested.
3001 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02003002 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003003 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3004 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003005 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003006 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003007 }
3008
Johan Hedberg124f6e32012-02-09 13:50:12 +02003009 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003010 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003011 if (!cmd) {
3012 err = -ENOMEM;
3013 goto unlock;
3014 }
3015
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003016 cmd->cmd_complete = addr_cmd_complete;
3017
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003018 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003019 dc.reason = 0x13; /* Remote User Terminated Connection */
3020 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3021 if (err < 0)
3022 mgmt_pending_remove(cmd);
3023
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003024unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003025 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003026 return err;
3027}
3028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003029static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003030 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003031{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003032 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003033 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003034 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003035 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003036 int err;
3037
3038 BT_DBG("");
3039
Johan Hedberg06a63b12013-01-20 14:27:21 +02003040 memset(&rp, 0, sizeof(rp));
3041 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3042 rp.addr.type = cp->addr.type;
3043
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003044 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003045 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3046 MGMT_STATUS_INVALID_PARAMS,
3047 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003048
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003049 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003050
3051 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003052 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3053 MGMT_STATUS_NOT_POWERED, &rp,
3054 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003055 goto failed;
3056 }
3057
Johan Hedberg333ae952015-03-17 13:48:47 +02003058 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003059 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3060 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003061 goto failed;
3062 }
3063
Andre Guedes591f47f2012-04-24 21:02:49 -03003064 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003065 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3066 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003067 else
3068 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003069
Vishal Agarwalf9607272012-06-13 05:32:43 +05303070 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003071 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3072 MGMT_STATUS_NOT_CONNECTED, &rp,
3073 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003074 goto failed;
3075 }
3076
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003077 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003078 if (!cmd) {
3079 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003080 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003081 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003082
Johan Hedbergf5818c22014-12-05 13:36:02 +02003083 cmd->cmd_complete = generic_cmd_complete;
3084
Johan Hedberge3f2f922014-08-18 20:33:33 +03003085 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003086 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003087 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003088
3089failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003090 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003091 return err;
3092}
3093
Andre Guedes57c14772012-04-24 21:02:50 -03003094static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003095{
3096 switch (link_type) {
3097 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003098 switch (addr_type) {
3099 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003100 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003101
Johan Hedberg48264f02011-11-09 13:58:58 +02003102 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003103 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003104 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003105 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003106
Johan Hedberg4c659c32011-11-07 23:13:39 +02003107 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003108 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003109 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003110 }
3111}
3112
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003113static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3114 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003115{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003116 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003117 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003118 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003119 int err;
3120 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003121
3122 BT_DBG("");
3123
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003124 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003125
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003126 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003127 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3128 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003129 goto unlock;
3130 }
3131
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003132 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003133 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3134 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003135 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003136 }
3137
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003138 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003139 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003140 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003141 err = -ENOMEM;
3142 goto unlock;
3143 }
3144
Johan Hedberg2784eb42011-01-21 13:56:35 +02003145 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003146 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003147 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3148 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003149 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003150 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003151 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003152 continue;
3153 i++;
3154 }
3155
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003156 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003157
Johan Hedberg4c659c32011-11-07 23:13:39 +02003158 /* Recalculate length in case of filtered SCO connections, etc */
3159 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003160
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003161 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3162 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003163
Johan Hedberga38528f2011-01-22 06:46:43 +02003164 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003165
3166unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003167 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003168 return err;
3169}
3170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003171static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003172 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003173{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003174 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003175 int err;
3176
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003177 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003178 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003179 if (!cmd)
3180 return -ENOMEM;
3181
Johan Hedbergd8457692012-02-17 14:24:57 +02003182 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003183 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003184 if (err < 0)
3185 mgmt_pending_remove(cmd);
3186
3187 return err;
3188}
3189
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003190static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003191 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003192{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003193 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003194 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003195 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003196 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003197 int err;
3198
3199 BT_DBG("");
3200
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003201 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003202
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003203 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003204 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3205 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003206 goto failed;
3207 }
3208
Johan Hedbergd8457692012-02-17 14:24:57 +02003209 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003210 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003211 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3212 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003213 goto failed;
3214 }
3215
3216 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003217 struct mgmt_cp_pin_code_neg_reply ncp;
3218
3219 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003220
3221 BT_ERR("PIN code is not 16 bytes long");
3222
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003223 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003224 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003225 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3226 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003227
3228 goto failed;
3229 }
3230
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003231 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003232 if (!cmd) {
3233 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003234 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003235 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003236
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003237 cmd->cmd_complete = addr_cmd_complete;
3238
Johan Hedbergd8457692012-02-17 14:24:57 +02003239 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003240 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003241 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003242
3243 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3244 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003245 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003246
3247failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003248 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003249 return err;
3250}
3251
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003252static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3253 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003254{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003255 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003256
3257 BT_DBG("");
3258
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003259 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003260 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3261 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003262
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003263 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003264
3265 hdev->io_capability = cp->io_capability;
3266
3267 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003268 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003269
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003270 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003271
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003272 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3273 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003274}
3275
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003276static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003277{
3278 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003279 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003280
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003281 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3283 continue;
3284
Johan Hedberge9a416b2011-02-19 12:05:56 -03003285 if (cmd->user_data != conn)
3286 continue;
3287
3288 return cmd;
3289 }
3290
3291 return NULL;
3292}
3293
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003294static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003295{
3296 struct mgmt_rp_pair_device rp;
3297 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003298 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003299
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003300 bacpy(&rp.addr.bdaddr, &conn->dst);
3301 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003302
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003303 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3304 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003305
3306 /* So we don't get further callbacks for this connection */
3307 conn->connect_cfm_cb = NULL;
3308 conn->security_cfm_cb = NULL;
3309 conn->disconn_cfm_cb = NULL;
3310
David Herrmann76a68ba2013-04-06 20:28:37 +02003311 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003312
3313 /* The device is paired so there is no need to remove
3314 * its connection parameters anymore.
3315 */
3316 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003317
3318 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003319
3320 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003321}
3322
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003323void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3324{
3325 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003326 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003327
3328 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003329 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003330 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003331 mgmt_pending_remove(cmd);
3332 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003333}
3334
Johan Hedberge9a416b2011-02-19 12:05:56 -03003335static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3336{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003337 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003338
3339 BT_DBG("status %u", status);
3340
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003341 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003342 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003343 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003344 return;
3345 }
3346
3347 cmd->cmd_complete(cmd, mgmt_status(status));
3348 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003349}
3350
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003351static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303352{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003353 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303354
3355 BT_DBG("status %u", status);
3356
3357 if (!status)
3358 return;
3359
3360 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003361 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303362 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003363 return;
3364 }
3365
3366 cmd->cmd_complete(cmd, mgmt_status(status));
3367 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303368}
3369
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003370static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003371 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003372{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003373 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003374 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003375 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003376 u8 sec_level, auth_type;
3377 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003378 int err;
3379
3380 BT_DBG("");
3381
Szymon Jancf950a30e2013-01-18 12:48:07 +01003382 memset(&rp, 0, sizeof(rp));
3383 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3384 rp.addr.type = cp->addr.type;
3385
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003386 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003387 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3388 MGMT_STATUS_INVALID_PARAMS,
3389 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003390
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003391 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003392 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3393 MGMT_STATUS_INVALID_PARAMS,
3394 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003395
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003396 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003397
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003398 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003399 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3400 MGMT_STATUS_NOT_POWERED, &rp,
3401 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003402 goto unlock;
3403 }
3404
Johan Hedberg55e76b32015-03-10 22:34:40 +02003405 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3406 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3407 MGMT_STATUS_ALREADY_PAIRED, &rp,
3408 sizeof(rp));
3409 goto unlock;
3410 }
3411
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003412 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003413 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003414
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003415 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003416 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3417 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003418 } else {
3419 u8 addr_type;
3420
3421 /* Convert from L2CAP channel address type to HCI address type
3422 */
3423 if (cp->addr.type == BDADDR_LE_PUBLIC)
3424 addr_type = ADDR_LE_DEV_PUBLIC;
3425 else
3426 addr_type = ADDR_LE_DEV_RANDOM;
3427
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003428 /* When pairing a new device, it is expected to remember
3429 * this device for future connections. Adding the connection
3430 * parameter information ahead of time allows tracking
3431 * of the slave preferred values and will speed up any
3432 * further connection establishment.
3433 *
3434 * If connection parameters already exist, then they
3435 * will be kept and this function does nothing.
3436 */
3437 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3438
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003439 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003440 sec_level, HCI_LE_CONN_TIMEOUT,
3441 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003442 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003443
Ville Tervo30e76272011-02-22 16:10:53 -03003444 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003445 int status;
3446
3447 if (PTR_ERR(conn) == -EBUSY)
3448 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003449 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3450 status = MGMT_STATUS_NOT_SUPPORTED;
3451 else if (PTR_ERR(conn) == -ECONNREFUSED)
3452 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003453 else
3454 status = MGMT_STATUS_CONNECT_FAILED;
3455
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003456 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3457 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003458 goto unlock;
3459 }
3460
3461 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003462 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003463 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3464 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003465 goto unlock;
3466 }
3467
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003468 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003469 if (!cmd) {
3470 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003471 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003472 goto unlock;
3473 }
3474
Johan Hedberg04ab2742014-12-05 13:36:04 +02003475 cmd->cmd_complete = pairing_complete;
3476
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003477 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003478 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003479 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003480 conn->security_cfm_cb = pairing_complete_cb;
3481 conn->disconn_cfm_cb = pairing_complete_cb;
3482 } else {
3483 conn->connect_cfm_cb = le_pairing_complete_cb;
3484 conn->security_cfm_cb = le_pairing_complete_cb;
3485 conn->disconn_cfm_cb = le_pairing_complete_cb;
3486 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003487
Johan Hedberge9a416b2011-02-19 12:05:56 -03003488 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003489 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003490
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003491 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003492 hci_conn_security(conn, sec_level, auth_type, true)) {
3493 cmd->cmd_complete(cmd, 0);
3494 mgmt_pending_remove(cmd);
3495 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003496
3497 err = 0;
3498
3499unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003500 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003501 return err;
3502}
3503
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003504static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3505 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003506{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003507 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003508 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003509 struct hci_conn *conn;
3510 int err;
3511
3512 BT_DBG("");
3513
Johan Hedberg28424702012-02-02 04:02:29 +02003514 hci_dev_lock(hdev);
3515
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003516 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003517 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3518 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003519 goto unlock;
3520 }
3521
Johan Hedberg333ae952015-03-17 13:48:47 +02003522 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003523 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003524 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3525 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003526 goto unlock;
3527 }
3528
3529 conn = cmd->user_data;
3530
3531 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003532 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3533 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003534 goto unlock;
3535 }
3536
Johan Hedberga511b352014-12-11 21:45:45 +02003537 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3538 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003539
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003540 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3541 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003542unlock:
3543 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003544 return err;
3545}
3546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003547static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003548 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003549 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003550{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003551 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003552 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003553 int err;
3554
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003555 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003556
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003557 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003558 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3559 MGMT_STATUS_NOT_POWERED, addr,
3560 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003561 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003562 }
3563
Johan Hedberg1707c602013-03-15 17:07:15 -05003564 if (addr->type == BDADDR_BREDR)
3565 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003566 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003567 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003568
Johan Hedberg272d90d2012-02-09 15:26:12 +02003569 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003570 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3571 MGMT_STATUS_NOT_CONNECTED, addr,
3572 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003573 goto done;
3574 }
3575
Johan Hedberg1707c602013-03-15 17:07:15 -05003576 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003577 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003578 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003579 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3580 MGMT_STATUS_SUCCESS, addr,
3581 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003582 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003583 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3584 MGMT_STATUS_FAILED, addr,
3585 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003586
Brian Gix47c15e22011-11-16 13:53:14 -08003587 goto done;
3588 }
3589
Johan Hedberg1707c602013-03-15 17:07:15 -05003590 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003591 if (!cmd) {
3592 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003593 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003594 }
3595
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003596 cmd->cmd_complete = addr_cmd_complete;
3597
Brian Gix0df4c182011-11-16 13:53:13 -08003598 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003599 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3600 struct hci_cp_user_passkey_reply cp;
3601
Johan Hedberg1707c602013-03-15 17:07:15 -05003602 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003603 cp.passkey = passkey;
3604 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3605 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003606 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3607 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003608
Johan Hedberga664b5b2011-02-19 12:06:02 -03003609 if (err < 0)
3610 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003611
Brian Gix0df4c182011-11-16 13:53:13 -08003612done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003613 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003614 return err;
3615}
3616
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303617static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3618 void *data, u16 len)
3619{
3620 struct mgmt_cp_pin_code_neg_reply *cp = data;
3621
3622 BT_DBG("");
3623
Johan Hedberg1707c602013-03-15 17:07:15 -05003624 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303625 MGMT_OP_PIN_CODE_NEG_REPLY,
3626 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3627}
3628
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003629static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3630 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003631{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003632 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003633
3634 BT_DBG("");
3635
3636 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003637 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3638 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003639
Johan Hedberg1707c602013-03-15 17:07:15 -05003640 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003641 MGMT_OP_USER_CONFIRM_REPLY,
3642 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003643}
3644
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003645static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003646 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003647{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003648 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003649
3650 BT_DBG("");
3651
Johan Hedberg1707c602013-03-15 17:07:15 -05003652 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003653 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3654 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003655}
3656
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003657static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3658 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003659{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003660 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003661
3662 BT_DBG("");
3663
Johan Hedberg1707c602013-03-15 17:07:15 -05003664 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003665 MGMT_OP_USER_PASSKEY_REPLY,
3666 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003667}
3668
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003669static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003670 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003671{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003672 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003673
3674 BT_DBG("");
3675
Johan Hedberg1707c602013-03-15 17:07:15 -05003676 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003677 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3678 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003679}
3680
Johan Hedberg13928972013-03-15 17:07:00 -05003681static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003682{
Johan Hedberg13928972013-03-15 17:07:00 -05003683 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003684 struct hci_cp_write_local_name cp;
3685
Johan Hedberg13928972013-03-15 17:07:00 -05003686 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003687
Johan Hedberg890ea892013-03-15 17:06:52 -05003688 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003689}
3690
Marcel Holtmann1904a852015-01-11 13:50:44 -08003691static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003692{
3693 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003694 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003695
3696 BT_DBG("status 0x%02x", status);
3697
3698 hci_dev_lock(hdev);
3699
Johan Hedberg333ae952015-03-17 13:48:47 +02003700 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003701 if (!cmd)
3702 goto unlock;
3703
3704 cp = cmd->param;
3705
3706 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003707 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3708 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003709 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003710 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3711 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003712
3713 mgmt_pending_remove(cmd);
3714
3715unlock:
3716 hci_dev_unlock(hdev);
3717}
3718
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003719static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003720 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003721{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003722 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003723 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003724 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003725 int err;
3726
3727 BT_DBG("");
3728
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003729 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003730
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003731 /* If the old values are the same as the new ones just return a
3732 * direct command complete event.
3733 */
3734 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3735 !memcmp(hdev->short_name, cp->short_name,
3736 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003737 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3738 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003739 goto failed;
3740 }
3741
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003742 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003743
Johan Hedbergb5235a62012-02-21 14:32:24 +02003744 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003745 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003746
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003747 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3748 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003749 if (err < 0)
3750 goto failed;
3751
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003752 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3753 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003754
Johan Hedbergb5235a62012-02-21 14:32:24 +02003755 goto failed;
3756 }
3757
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003758 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003759 if (!cmd) {
3760 err = -ENOMEM;
3761 goto failed;
3762 }
3763
Johan Hedberg13928972013-03-15 17:07:00 -05003764 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3765
Johan Hedberg890ea892013-03-15 17:06:52 -05003766 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003767
3768 if (lmp_bredr_capable(hdev)) {
3769 update_name(&req);
3770 update_eir(&req);
3771 }
3772
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003773 /* The name is stored in the scan response data and so
3774 * no need to udpate the advertising data here.
3775 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003776 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003777 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003778
Johan Hedberg13928972013-03-15 17:07:00 -05003779 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003780 if (err < 0)
3781 mgmt_pending_remove(cmd);
3782
3783failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003784 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003785 return err;
3786}
3787
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003788static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3789 u16 opcode, struct sk_buff *skb)
3790{
3791 struct mgmt_rp_read_local_oob_data mgmt_rp;
3792 size_t rp_size = sizeof(mgmt_rp);
3793 struct mgmt_pending_cmd *cmd;
3794
3795 BT_DBG("%s status %u", hdev->name, status);
3796
3797 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3798 if (!cmd)
3799 return;
3800
3801 if (status || !skb) {
3802 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3803 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3804 goto remove;
3805 }
3806
3807 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3808
3809 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3810 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3811
3812 if (skb->len < sizeof(*rp)) {
3813 mgmt_cmd_status(cmd->sk, hdev->id,
3814 MGMT_OP_READ_LOCAL_OOB_DATA,
3815 MGMT_STATUS_FAILED);
3816 goto remove;
3817 }
3818
3819 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3820 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3821
3822 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3823 } else {
3824 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3825
3826 if (skb->len < sizeof(*rp)) {
3827 mgmt_cmd_status(cmd->sk, hdev->id,
3828 MGMT_OP_READ_LOCAL_OOB_DATA,
3829 MGMT_STATUS_FAILED);
3830 goto remove;
3831 }
3832
3833 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3834 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3835
3836 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3837 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3838 }
3839
3840 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3841 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3842
3843remove:
3844 mgmt_pending_remove(cmd);
3845}
3846
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003847static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003848 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003849{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003850 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003851 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003852 int err;
3853
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003854 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003855
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003856 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003857
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003858 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003859 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3860 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003861 goto unlock;
3862 }
3863
Andre Guedes9a1a1992012-07-24 15:03:48 -03003864 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003865 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3866 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003867 goto unlock;
3868 }
3869
Johan Hedberg333ae952015-03-17 13:48:47 +02003870 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003871 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3872 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003873 goto unlock;
3874 }
3875
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003876 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003877 if (!cmd) {
3878 err = -ENOMEM;
3879 goto unlock;
3880 }
3881
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003882 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003883
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003884 if (bredr_sc_enabled(hdev))
3885 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3886 else
3887 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3888
3889 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003890 if (err < 0)
3891 mgmt_pending_remove(cmd);
3892
3893unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003894 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003895 return err;
3896}
3897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003898static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003899 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003900{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003901 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003902 int err;
3903
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003904 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003905
Johan Hedberg5d57e792015-01-23 10:10:38 +02003906 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003907 return mgmt_cmd_complete(sk, hdev->id,
3908 MGMT_OP_ADD_REMOTE_OOB_DATA,
3909 MGMT_STATUS_INVALID_PARAMS,
3910 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003911
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003912 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003913
Marcel Holtmannec109112014-01-10 02:07:30 -08003914 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3915 struct mgmt_cp_add_remote_oob_data *cp = data;
3916 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003917
Johan Hedbergc19a4952014-11-17 20:52:19 +02003918 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003919 err = mgmt_cmd_complete(sk, hdev->id,
3920 MGMT_OP_ADD_REMOTE_OOB_DATA,
3921 MGMT_STATUS_INVALID_PARAMS,
3922 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003923 goto unlock;
3924 }
3925
Marcel Holtmannec109112014-01-10 02:07:30 -08003926 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003927 cp->addr.type, cp->hash,
3928 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003929 if (err < 0)
3930 status = MGMT_STATUS_FAILED;
3931 else
3932 status = MGMT_STATUS_SUCCESS;
3933
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003934 err = mgmt_cmd_complete(sk, hdev->id,
3935 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3936 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003937 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3938 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003939 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003940 u8 status;
3941
Johan Hedberg86df9202014-10-26 20:52:27 +01003942 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003943 /* Enforce zero-valued 192-bit parameters as
3944 * long as legacy SMP OOB isn't implemented.
3945 */
3946 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3947 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003948 err = mgmt_cmd_complete(sk, hdev->id,
3949 MGMT_OP_ADD_REMOTE_OOB_DATA,
3950 MGMT_STATUS_INVALID_PARAMS,
3951 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003952 goto unlock;
3953 }
3954
Johan Hedberg86df9202014-10-26 20:52:27 +01003955 rand192 = NULL;
3956 hash192 = NULL;
3957 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003958 /* In case one of the P-192 values is set to zero,
3959 * then just disable OOB data for P-192.
3960 */
3961 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3962 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3963 rand192 = NULL;
3964 hash192 = NULL;
3965 } else {
3966 rand192 = cp->rand192;
3967 hash192 = cp->hash192;
3968 }
3969 }
3970
3971 /* In case one of the P-256 values is set to zero, then just
3972 * disable OOB data for P-256.
3973 */
3974 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3975 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3976 rand256 = NULL;
3977 hash256 = NULL;
3978 } else {
3979 rand256 = cp->rand256;
3980 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003981 }
3982
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003983 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003984 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003985 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003986 if (err < 0)
3987 status = MGMT_STATUS_FAILED;
3988 else
3989 status = MGMT_STATUS_SUCCESS;
3990
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003991 err = mgmt_cmd_complete(sk, hdev->id,
3992 MGMT_OP_ADD_REMOTE_OOB_DATA,
3993 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003994 } else {
3995 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003996 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3997 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003998 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003999
Johan Hedbergc19a4952014-11-17 20:52:19 +02004000unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004001 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004002 return err;
4003}
4004
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004005static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004006 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01004007{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004008 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004009 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01004010 int err;
4011
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004012 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01004013
Johan Hedbergc19a4952014-11-17 20:52:19 +02004014 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004015 return mgmt_cmd_complete(sk, hdev->id,
4016 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4017 MGMT_STATUS_INVALID_PARAMS,
4018 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004019
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004020 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004021
Johan Hedbergeedbd582014-11-15 09:34:23 +02004022 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4023 hci_remote_oob_data_clear(hdev);
4024 status = MGMT_STATUS_SUCCESS;
4025 goto done;
4026 }
4027
Johan Hedberg6928a922014-10-26 20:46:09 +01004028 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004029 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004030 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004031 else
Szymon Janca6785be2012-12-13 15:11:21 +01004032 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004033
Johan Hedbergeedbd582014-11-15 09:34:23 +02004034done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004035 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4036 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004037
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004038 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004039 return err;
4040}
4041
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004042static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
4043{
4044 struct hci_dev *hdev = req->hdev;
4045 struct hci_cp_inquiry cp;
4046 /* General inquiry access code (GIAC) */
4047 u8 lap[3] = { 0x33, 0x8b, 0x9e };
4048
4049 *status = mgmt_bredr_support(hdev);
4050 if (*status)
4051 return false;
4052
4053 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
4054 *status = MGMT_STATUS_BUSY;
4055 return false;
4056 }
4057
4058 hci_inquiry_cache_flush(hdev);
4059
4060 memset(&cp, 0, sizeof(cp));
4061 memcpy(&cp.lap, lap, sizeof(cp.lap));
4062 cp.length = DISCOV_BREDR_INQUIRY_LEN;
4063
4064 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4065
4066 return true;
4067}
4068
4069static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004070{
Marcel Holtmann80190442014-12-04 11:36:36 +01004071 struct hci_dev *hdev = req->hdev;
4072 struct hci_cp_le_set_scan_param param_cp;
4073 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004074 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004075 int err;
4076
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004077 *status = mgmt_le_support(hdev);
4078 if (*status)
4079 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004080
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004081 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4082 /* Don't let discovery abort an outgoing connection attempt
4083 * that's using directed advertising.
4084 */
4085 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4086 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004087 return false;
4088 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004089
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004090 disable_advertising(req);
4091 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004092
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004093 /* If controller is scanning, it means the background scanning is
4094 * running. Thus, we should temporarily stop it in order to set the
4095 * discovery scanning parameters.
4096 */
4097 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4098 hci_req_add_le_scan_disable(req);
4099
4100 /* All active scans will be done with either a resolvable private
4101 * address (when privacy feature has been enabled) or non-resolvable
4102 * private address.
4103 */
4104 err = hci_update_random_address(req, true, &own_addr_type);
4105 if (err < 0) {
4106 *status = MGMT_STATUS_FAILED;
4107 return false;
4108 }
4109
4110 memset(&param_cp, 0, sizeof(param_cp));
4111 param_cp.type = LE_SCAN_ACTIVE;
4112 param_cp.interval = cpu_to_le16(interval);
4113 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4114 param_cp.own_address_type = own_addr_type;
4115
4116 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4117 &param_cp);
4118
4119 memset(&enable_cp, 0, sizeof(enable_cp));
4120 enable_cp.enable = LE_SCAN_ENABLE;
4121 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4122
4123 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4124 &enable_cp);
4125
4126 return true;
4127}
4128
4129static bool trigger_discovery(struct hci_request *req, u8 *status)
4130{
4131 struct hci_dev *hdev = req->hdev;
4132
4133 switch (hdev->discovery.type) {
4134 case DISCOV_TYPE_BREDR:
4135 if (!trigger_bredr_inquiry(req, status))
4136 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004137 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004138
Marcel Holtmann80190442014-12-04 11:36:36 +01004139 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004140 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4141 &hdev->quirks)) {
4142 /* During simultaneous discovery, we double LE scan
4143 * interval. We must leave some time for the controller
4144 * to do BR/EDR inquiry.
4145 */
4146 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4147 status))
4148 return false;
4149
4150 if (!trigger_bredr_inquiry(req, status))
4151 return false;
4152
4153 return true;
4154 }
4155
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004156 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004157 *status = MGMT_STATUS_NOT_SUPPORTED;
4158 return false;
4159 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004160 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004161
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004162 case DISCOV_TYPE_LE:
4163 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004164 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004165 break;
4166
4167 default:
4168 *status = MGMT_STATUS_INVALID_PARAMS;
4169 return false;
4170 }
4171
4172 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004173}
4174
Marcel Holtmann1904a852015-01-11 13:50:44 -08004175static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4176 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004177{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004178 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004179 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004180
Andre Guedes7c307722013-04-30 15:29:28 -03004181 BT_DBG("status %d", status);
4182
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004183 hci_dev_lock(hdev);
4184
Johan Hedberg333ae952015-03-17 13:48:47 +02004185 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004186 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004187 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004188
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004189 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004190 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004191 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004192 }
4193
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004194 if (status) {
4195 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4196 goto unlock;
4197 }
4198
Andre Guedes7c307722013-04-30 15:29:28 -03004199 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004200
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004201 /* If the scan involves LE scan, pick proper timeout to schedule
4202 * hdev->le_scan_disable that will stop it.
4203 */
Andre Guedes7c307722013-04-30 15:29:28 -03004204 switch (hdev->discovery.type) {
4205 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004206 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004207 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004208 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004209 /* When running simultaneous discovery, the LE scanning time
4210 * should occupy the whole discovery time sine BR/EDR inquiry
4211 * and LE scanning are scheduled by the controller.
4212 *
4213 * For interleaving discovery in comparison, BR/EDR inquiry
4214 * and LE scanning are done sequentially with separate
4215 * timeouts.
4216 */
4217 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4218 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4219 else
4220 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004221 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004222 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004223 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004224 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004225 default:
4226 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004227 timeout = 0;
4228 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004229 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004230
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004231 if (timeout) {
4232 /* When service discovery is used and the controller has
4233 * a strict duplicate filter, it is important to remember
4234 * the start and duration of the scan. This is required
4235 * for restarting scanning during the discovery phase.
4236 */
4237 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4238 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004239 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004240 hdev->discovery.scan_start = jiffies;
4241 hdev->discovery.scan_duration = timeout;
4242 }
4243
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004244 queue_delayed_work(hdev->workqueue,
4245 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004246 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004247
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004248unlock:
4249 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004250}
4251
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004252static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004253 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004254{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004255 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004256 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004257 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004258 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004259 int err;
4260
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004261 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004262
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004263 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004264
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004265 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004266 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4267 MGMT_STATUS_NOT_POWERED,
4268 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004269 goto failed;
4270 }
4271
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004272 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004273 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004274 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4275 MGMT_STATUS_BUSY, &cp->type,
4276 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004277 goto failed;
4278 }
4279
Johan Hedberg2922a942014-12-05 13:36:06 +02004280 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004281 if (!cmd) {
4282 err = -ENOMEM;
4283 goto failed;
4284 }
4285
Johan Hedberg2922a942014-12-05 13:36:06 +02004286 cmd->cmd_complete = generic_cmd_complete;
4287
Marcel Holtmann22078802014-12-05 11:45:22 +01004288 /* Clear the discovery filter first to free any previously
4289 * allocated memory for the UUID list.
4290 */
4291 hci_discovery_filter_clear(hdev);
4292
Andre Guedes4aab14e2012-02-17 20:39:36 -03004293 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004294 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004295
Andre Guedes7c307722013-04-30 15:29:28 -03004296 hci_req_init(&req, hdev);
4297
Marcel Holtmann80190442014-12-04 11:36:36 +01004298 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004299 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4300 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004301 mgmt_pending_remove(cmd);
4302 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004303 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004304
Andre Guedes7c307722013-04-30 15:29:28 -03004305 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004306 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004307 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004308 goto failed;
4309 }
4310
4311 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004312
4313failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004314 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004315 return err;
4316}
4317
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004318static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4319 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004320{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004321 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4322 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004323}
4324
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004325static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4326 void *data, u16 len)
4327{
4328 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004329 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004330 struct hci_request req;
4331 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4332 u16 uuid_count, expected_len;
4333 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004334 int err;
4335
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004336 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004337
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004338 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004339
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004340 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004341 err = mgmt_cmd_complete(sk, hdev->id,
4342 MGMT_OP_START_SERVICE_DISCOVERY,
4343 MGMT_STATUS_NOT_POWERED,
4344 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004345 goto failed;
4346 }
4347
4348 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004349 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004350 err = mgmt_cmd_complete(sk, hdev->id,
4351 MGMT_OP_START_SERVICE_DISCOVERY,
4352 MGMT_STATUS_BUSY, &cp->type,
4353 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004354 goto failed;
4355 }
4356
4357 uuid_count = __le16_to_cpu(cp->uuid_count);
4358 if (uuid_count > max_uuid_count) {
4359 BT_ERR("service_discovery: too big uuid_count value %u",
4360 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004361 err = mgmt_cmd_complete(sk, hdev->id,
4362 MGMT_OP_START_SERVICE_DISCOVERY,
4363 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4364 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004365 goto failed;
4366 }
4367
4368 expected_len = sizeof(*cp) + uuid_count * 16;
4369 if (expected_len != len) {
4370 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4371 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004372 err = mgmt_cmd_complete(sk, hdev->id,
4373 MGMT_OP_START_SERVICE_DISCOVERY,
4374 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4375 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004376 goto failed;
4377 }
4378
4379 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004380 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004381 if (!cmd) {
4382 err = -ENOMEM;
4383 goto failed;
4384 }
4385
Johan Hedberg2922a942014-12-05 13:36:06 +02004386 cmd->cmd_complete = service_discovery_cmd_complete;
4387
Marcel Holtmann22078802014-12-05 11:45:22 +01004388 /* Clear the discovery filter first to free any previously
4389 * allocated memory for the UUID list.
4390 */
4391 hci_discovery_filter_clear(hdev);
4392
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004393 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004394 hdev->discovery.type = cp->type;
4395 hdev->discovery.rssi = cp->rssi;
4396 hdev->discovery.uuid_count = uuid_count;
4397
4398 if (uuid_count > 0) {
4399 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4400 GFP_KERNEL);
4401 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004402 err = mgmt_cmd_complete(sk, hdev->id,
4403 MGMT_OP_START_SERVICE_DISCOVERY,
4404 MGMT_STATUS_FAILED,
4405 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004406 mgmt_pending_remove(cmd);
4407 goto failed;
4408 }
4409 }
4410
4411 hci_req_init(&req, hdev);
4412
4413 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004414 err = mgmt_cmd_complete(sk, hdev->id,
4415 MGMT_OP_START_SERVICE_DISCOVERY,
4416 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004417 mgmt_pending_remove(cmd);
4418 goto failed;
4419 }
4420
4421 err = hci_req_run(&req, start_discovery_complete);
4422 if (err < 0) {
4423 mgmt_pending_remove(cmd);
4424 goto failed;
4425 }
4426
4427 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4428
4429failed:
4430 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004431 return err;
4432}
4433
Marcel Holtmann1904a852015-01-11 13:50:44 -08004434static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004435{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004436 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004437
Andre Guedes0e05bba2013-04-30 15:29:33 -03004438 BT_DBG("status %d", status);
4439
4440 hci_dev_lock(hdev);
4441
Johan Hedberg333ae952015-03-17 13:48:47 +02004442 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004443 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004444 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004445 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004446 }
4447
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004448 if (!status)
4449 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004450
Andre Guedes0e05bba2013-04-30 15:29:33 -03004451 hci_dev_unlock(hdev);
4452}
4453
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004454static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004455 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004456{
Johan Hedbergd9306502012-02-20 23:25:18 +02004457 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004458 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004459 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004460 int err;
4461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004462 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004463
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004464 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004465
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004466 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004467 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4468 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4469 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004470 goto unlock;
4471 }
4472
4473 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004474 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4475 MGMT_STATUS_INVALID_PARAMS,
4476 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004477 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004478 }
4479
Johan Hedberg2922a942014-12-05 13:36:06 +02004480 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004481 if (!cmd) {
4482 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004483 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004484 }
4485
Johan Hedberg2922a942014-12-05 13:36:06 +02004486 cmd->cmd_complete = generic_cmd_complete;
4487
Andre Guedes0e05bba2013-04-30 15:29:33 -03004488 hci_req_init(&req, hdev);
4489
Johan Hedberg21a60d32014-06-10 14:05:58 +03004490 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004491
Johan Hedberg21a60d32014-06-10 14:05:58 +03004492 err = hci_req_run(&req, stop_discovery_complete);
4493 if (!err) {
4494 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004495 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004496 }
4497
Johan Hedberg21a60d32014-06-10 14:05:58 +03004498 mgmt_pending_remove(cmd);
4499
4500 /* If no HCI commands were sent we're done */
4501 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004502 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4503 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004504 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4505 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004506
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004507unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004508 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004509 return err;
4510}
4511
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004512static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004513 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004514{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004515 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004516 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004517 int err;
4518
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004519 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004520
Johan Hedberg561aafb2012-01-04 13:31:59 +02004521 hci_dev_lock(hdev);
4522
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004523 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004524 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4525 MGMT_STATUS_FAILED, &cp->addr,
4526 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004527 goto failed;
4528 }
4529
Johan Hedberga198e7b2012-02-17 14:27:06 +02004530 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004531 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004532 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4533 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4534 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004535 goto failed;
4536 }
4537
4538 if (cp->name_known) {
4539 e->name_state = NAME_KNOWN;
4540 list_del(&e->list);
4541 } else {
4542 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004543 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004544 }
4545
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004546 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4547 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004548
4549failed:
4550 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004551 return err;
4552}
4553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004554static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004555 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004556{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004557 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004558 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004559 int err;
4560
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004561 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004562
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004563 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004564 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4565 MGMT_STATUS_INVALID_PARAMS,
4566 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004567
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004568 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004569
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004570 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4571 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004572 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004573 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004574 goto done;
4575 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004576
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004577 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4578 sk);
4579 status = MGMT_STATUS_SUCCESS;
4580
4581done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004582 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4583 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004584
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004585 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004586
4587 return err;
4588}
4589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004590static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004591 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004592{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004593 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004594 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004595 int err;
4596
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004597 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004598
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004599 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004600 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4601 MGMT_STATUS_INVALID_PARAMS,
4602 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004603
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004604 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004605
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004606 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4607 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004608 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004609 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004610 goto done;
4611 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004612
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004613 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4614 sk);
4615 status = MGMT_STATUS_SUCCESS;
4616
4617done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004618 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4619 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004620
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004621 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004622
4623 return err;
4624}
4625
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004626static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4627 u16 len)
4628{
4629 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004630 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004631 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004632 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004633
4634 BT_DBG("%s", hdev->name);
4635
Szymon Jancc72d4b82012-03-16 16:02:57 +01004636 source = __le16_to_cpu(cp->source);
4637
4638 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004639 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4640 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004641
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004642 hci_dev_lock(hdev);
4643
Szymon Jancc72d4b82012-03-16 16:02:57 +01004644 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004645 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4646 hdev->devid_product = __le16_to_cpu(cp->product);
4647 hdev->devid_version = __le16_to_cpu(cp->version);
4648
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004649 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4650 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004651
Johan Hedberg890ea892013-03-15 17:06:52 -05004652 hci_req_init(&req, hdev);
4653 update_eir(&req);
4654 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004655
4656 hci_dev_unlock(hdev);
4657
4658 return err;
4659}
4660
Arman Uguray24b4f382015-03-23 15:57:12 -07004661static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4662 u16 opcode)
4663{
4664 BT_DBG("status %d", status);
4665}
4666
Marcel Holtmann1904a852015-01-11 13:50:44 -08004667static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4668 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004669{
4670 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004671 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004672
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304673 hci_dev_lock(hdev);
4674
Johan Hedberg4375f102013-09-25 13:26:10 +03004675 if (status) {
4676 u8 mgmt_err = mgmt_status(status);
4677
4678 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4679 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304680 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004681 }
4682
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004683 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004684 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004685 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004686 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004687
Johan Hedberg4375f102013-09-25 13:26:10 +03004688 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4689 &match);
4690
4691 new_settings(hdev, match.sk);
4692
4693 if (match.sk)
4694 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304695
Arman Uguray24b4f382015-03-23 15:57:12 -07004696 /* If "Set Advertising" was just disabled and instance advertising was
4697 * set up earlier, then enable the advertising instance.
4698 */
4699 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4700 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4701 goto unlock;
4702
4703 hci_req_init(&req, hdev);
4704
4705 update_adv_data(&req);
4706 enable_advertising(&req);
4707
4708 if (hci_req_run(&req, enable_advertising_instance) < 0)
4709 BT_ERR("Failed to re-configure advertising");
4710
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304711unlock:
4712 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004713}
4714
Marcel Holtmann21b51872013-10-10 09:47:53 -07004715static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4716 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004717{
4718 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004719 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004720 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004721 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004722 int err;
4723
4724 BT_DBG("request for %s", hdev->name);
4725
Johan Hedberge6fe7982013-10-02 15:45:22 +03004726 status = mgmt_le_support(hdev);
4727 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004728 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4729 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004730
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004731 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004732 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4733 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004734
4735 hci_dev_lock(hdev);
4736
4737 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004738
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004739 /* The following conditions are ones which mean that we should
4740 * not do any HCI communication but directly send a mgmt
4741 * response to user space (after toggling the flag if
4742 * necessary).
4743 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004744 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004745 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4746 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004747 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004748 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004749 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004750 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004751
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004752 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004753 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004754 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004755 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004756 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004757 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004758 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004759 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004760 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004761 }
4762
4763 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4764 if (err < 0)
4765 goto unlock;
4766
4767 if (changed)
4768 err = new_settings(hdev, sk);
4769
4770 goto unlock;
4771 }
4772
Johan Hedberg333ae952015-03-17 13:48:47 +02004773 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4774 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004775 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4776 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004777 goto unlock;
4778 }
4779
4780 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4781 if (!cmd) {
4782 err = -ENOMEM;
4783 goto unlock;
4784 }
4785
4786 hci_req_init(&req, hdev);
4787
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004788 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004789 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004790 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004791 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004792
Arman Uguray24b4f382015-03-23 15:57:12 -07004793 if (val) {
4794 /* Switch to instance "0" for the Set Advertising setting. */
4795 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004796 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004797 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004798 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004799 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004800 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004801
4802 err = hci_req_run(&req, set_advertising_complete);
4803 if (err < 0)
4804 mgmt_pending_remove(cmd);
4805
4806unlock:
4807 hci_dev_unlock(hdev);
4808 return err;
4809}
4810
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004811static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4812 void *data, u16 len)
4813{
4814 struct mgmt_cp_set_static_address *cp = data;
4815 int err;
4816
4817 BT_DBG("%s", hdev->name);
4818
Marcel Holtmann62af4442013-10-02 22:10:32 -07004819 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004820 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4821 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004822
4823 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004824 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4825 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004826
4827 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4828 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004829 return mgmt_cmd_status(sk, hdev->id,
4830 MGMT_OP_SET_STATIC_ADDRESS,
4831 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004832
4833 /* Two most significant bits shall be set */
4834 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004835 return mgmt_cmd_status(sk, hdev->id,
4836 MGMT_OP_SET_STATIC_ADDRESS,
4837 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004838 }
4839
4840 hci_dev_lock(hdev);
4841
4842 bacpy(&hdev->static_addr, &cp->bdaddr);
4843
Marcel Holtmann93690c22015-03-06 10:11:21 -08004844 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4845 if (err < 0)
4846 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004847
Marcel Holtmann93690c22015-03-06 10:11:21 -08004848 err = new_settings(hdev, sk);
4849
4850unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004851 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004852 return err;
4853}
4854
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004855static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4856 void *data, u16 len)
4857{
4858 struct mgmt_cp_set_scan_params *cp = data;
4859 __u16 interval, window;
4860 int err;
4861
4862 BT_DBG("%s", hdev->name);
4863
4864 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004865 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4866 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004867
4868 interval = __le16_to_cpu(cp->interval);
4869
4870 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004871 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4872 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004873
4874 window = __le16_to_cpu(cp->window);
4875
4876 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004877 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4878 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004879
Marcel Holtmann899e1072013-10-14 09:55:32 -07004880 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004881 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4882 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004883
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004884 hci_dev_lock(hdev);
4885
4886 hdev->le_scan_interval = interval;
4887 hdev->le_scan_window = window;
4888
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004889 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4890 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004891
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004892 /* If background scan is running, restart it so new parameters are
4893 * loaded.
4894 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004895 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004896 hdev->discovery.state == DISCOVERY_STOPPED) {
4897 struct hci_request req;
4898
4899 hci_req_init(&req, hdev);
4900
4901 hci_req_add_le_scan_disable(&req);
4902 hci_req_add_le_passive_scan(&req);
4903
4904 hci_req_run(&req, NULL);
4905 }
4906
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004907 hci_dev_unlock(hdev);
4908
4909 return err;
4910}
4911
Marcel Holtmann1904a852015-01-11 13:50:44 -08004912static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4913 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004914{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004915 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004916
4917 BT_DBG("status 0x%02x", status);
4918
4919 hci_dev_lock(hdev);
4920
Johan Hedberg333ae952015-03-17 13:48:47 +02004921 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004922 if (!cmd)
4923 goto unlock;
4924
4925 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004926 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4927 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004928 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004929 struct mgmt_mode *cp = cmd->param;
4930
4931 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004932 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004933 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004934 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004935
Johan Hedberg33e38b32013-03-15 17:07:05 -05004936 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4937 new_settings(hdev, cmd->sk);
4938 }
4939
4940 mgmt_pending_remove(cmd);
4941
4942unlock:
4943 hci_dev_unlock(hdev);
4944}
4945
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004946static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004947 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004948{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004949 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004950 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004951 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004952 int err;
4953
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004954 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004955
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004956 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004957 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004958 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4959 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004960
Johan Hedberga7e80f22013-01-09 16:05:19 +02004961 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004962 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4963 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004964
Antti Julkuf6422ec2011-06-22 13:11:56 +03004965 hci_dev_lock(hdev);
4966
Johan Hedberg333ae952015-03-17 13:48:47 +02004967 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004968 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4969 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004970 goto unlock;
4971 }
4972
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004973 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004974 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4975 hdev);
4976 goto unlock;
4977 }
4978
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004979 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004980 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004981 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4982 hdev);
4983 new_settings(hdev, sk);
4984 goto unlock;
4985 }
4986
Johan Hedberg33e38b32013-03-15 17:07:05 -05004987 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4988 data, len);
4989 if (!cmd) {
4990 err = -ENOMEM;
4991 goto unlock;
4992 }
4993
4994 hci_req_init(&req, hdev);
4995
Johan Hedberg406d7802013-03-15 17:07:09 -05004996 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004997
4998 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004999 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005000 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5001 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005002 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03005003 }
5004
Johan Hedberg33e38b32013-03-15 17:07:05 -05005005unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03005006 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005007
Antti Julkuf6422ec2011-06-22 13:11:56 +03005008 return err;
5009}
5010
Marcel Holtmann1904a852015-01-11 13:50:44 -08005011static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03005012{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005013 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005014
5015 BT_DBG("status 0x%02x", status);
5016
5017 hci_dev_lock(hdev);
5018
Johan Hedberg333ae952015-03-17 13:48:47 +02005019 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005020 if (!cmd)
5021 goto unlock;
5022
5023 if (status) {
5024 u8 mgmt_err = mgmt_status(status);
5025
5026 /* We need to restore the flag if related HCI commands
5027 * failed.
5028 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005029 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005030
Johan Hedberga69e8372015-03-06 21:08:53 +02005031 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005032 } else {
5033 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
5034 new_settings(hdev, cmd->sk);
5035 }
5036
5037 mgmt_pending_remove(cmd);
5038
5039unlock:
5040 hci_dev_unlock(hdev);
5041}
5042
5043static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
5044{
5045 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005046 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005047 struct hci_request req;
5048 int err;
5049
5050 BT_DBG("request for %s", hdev->name);
5051
5052 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005053 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5054 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005055
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005056 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005057 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5058 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005059
5060 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005061 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5062 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005063
5064 hci_dev_lock(hdev);
5065
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005066 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005067 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5068 goto unlock;
5069 }
5070
5071 if (!hdev_is_powered(hdev)) {
5072 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005073 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5074 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5075 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5076 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5077 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005078 }
5079
Marcel Holtmannce05d602015-03-13 02:11:03 -07005080 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005081
5082 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5083 if (err < 0)
5084 goto unlock;
5085
5086 err = new_settings(hdev, sk);
5087 goto unlock;
5088 }
5089
5090 /* Reject disabling when powered on */
5091 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005092 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5093 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005094 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005095 } else {
5096 /* When configuring a dual-mode controller to operate
5097 * with LE only and using a static address, then switching
5098 * BR/EDR back on is not allowed.
5099 *
5100 * Dual-mode controllers shall operate with the public
5101 * address as its identity address for BR/EDR and LE. So
5102 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005103 *
5104 * The same restrictions applies when secure connections
5105 * has been enabled. For BR/EDR this is a controller feature
5106 * while for LE it is a host stack feature. This means that
5107 * switching BR/EDR back on when secure connections has been
5108 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005109 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005110 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005111 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005112 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005113 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5114 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005115 goto unlock;
5116 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005117 }
5118
Johan Hedberg333ae952015-03-17 13:48:47 +02005119 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005120 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5121 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005122 goto unlock;
5123 }
5124
5125 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5126 if (!cmd) {
5127 err = -ENOMEM;
5128 goto unlock;
5129 }
5130
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005131 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005132 * generates the correct flags.
5133 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005134 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005135
5136 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005137
Johan Hedberg432df052014-08-01 11:13:31 +03005138 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005139 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005140
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005141 /* Since only the advertising data flags will change, there
5142 * is no need to update the scan response data.
5143 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005144 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005145
Johan Hedberg0663ca22013-10-02 13:43:14 +03005146 err = hci_req_run(&req, set_bredr_complete);
5147 if (err < 0)
5148 mgmt_pending_remove(cmd);
5149
5150unlock:
5151 hci_dev_unlock(hdev);
5152 return err;
5153}
5154
Johan Hedberga1443f52015-01-23 15:42:46 +02005155static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5156{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005157 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005158 struct mgmt_mode *cp;
5159
5160 BT_DBG("%s status %u", hdev->name, status);
5161
5162 hci_dev_lock(hdev);
5163
Johan Hedberg333ae952015-03-17 13:48:47 +02005164 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005165 if (!cmd)
5166 goto unlock;
5167
5168 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005169 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5170 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005171 goto remove;
5172 }
5173
5174 cp = cmd->param;
5175
5176 switch (cp->val) {
5177 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005178 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5179 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005180 break;
5181 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005182 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005183 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005184 break;
5185 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005186 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5187 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005188 break;
5189 }
5190
5191 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5192 new_settings(hdev, cmd->sk);
5193
5194remove:
5195 mgmt_pending_remove(cmd);
5196unlock:
5197 hci_dev_unlock(hdev);
5198}
5199
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005200static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5201 void *data, u16 len)
5202{
5203 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005204 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005205 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005206 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005207 int err;
5208
5209 BT_DBG("request for %s", hdev->name);
5210
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005211 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005212 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005213 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5214 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005215
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005216 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005217 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005218 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005219 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5220 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005221
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005222 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005223 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005224 MGMT_STATUS_INVALID_PARAMS);
5225
5226 hci_dev_lock(hdev);
5227
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005228 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005229 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005230 bool changed;
5231
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005232 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005233 changed = !hci_dev_test_and_set_flag(hdev,
5234 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005235 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005236 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005237 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005238 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005239 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005240 changed = hci_dev_test_and_clear_flag(hdev,
5241 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005242 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005243 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005244
5245 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5246 if (err < 0)
5247 goto failed;
5248
5249 if (changed)
5250 err = new_settings(hdev, sk);
5251
5252 goto failed;
5253 }
5254
Johan Hedberg333ae952015-03-17 13:48:47 +02005255 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005256 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5257 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005258 goto failed;
5259 }
5260
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005261 val = !!cp->val;
5262
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005263 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5264 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005265 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5266 goto failed;
5267 }
5268
5269 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5270 if (!cmd) {
5271 err = -ENOMEM;
5272 goto failed;
5273 }
5274
Johan Hedberga1443f52015-01-23 15:42:46 +02005275 hci_req_init(&req, hdev);
5276 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5277 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005278 if (err < 0) {
5279 mgmt_pending_remove(cmd);
5280 goto failed;
5281 }
5282
5283failed:
5284 hci_dev_unlock(hdev);
5285 return err;
5286}
5287
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005288static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5289 void *data, u16 len)
5290{
5291 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005292 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005293 int err;
5294
5295 BT_DBG("request for %s", hdev->name);
5296
Johan Hedbergb97109792014-06-24 14:00:28 +03005297 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005298 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5299 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005300
5301 hci_dev_lock(hdev);
5302
5303 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005304 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005305 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005306 changed = hci_dev_test_and_clear_flag(hdev,
5307 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005308
Johan Hedbergb97109792014-06-24 14:00:28 +03005309 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005310 use_changed = !hci_dev_test_and_set_flag(hdev,
5311 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005312 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005313 use_changed = hci_dev_test_and_clear_flag(hdev,
5314 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005315
5316 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005317 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005318 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5319 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5320 sizeof(mode), &mode);
5321 }
5322
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005323 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5324 if (err < 0)
5325 goto unlock;
5326
5327 if (changed)
5328 err = new_settings(hdev, sk);
5329
5330unlock:
5331 hci_dev_unlock(hdev);
5332 return err;
5333}
5334
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005335static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5336 u16 len)
5337{
5338 struct mgmt_cp_set_privacy *cp = cp_data;
5339 bool changed;
5340 int err;
5341
5342 BT_DBG("request for %s", hdev->name);
5343
5344 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005345 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5346 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005347
5348 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005349 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5350 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005351
5352 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005353 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5354 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005355
5356 hci_dev_lock(hdev);
5357
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005358 /* If user space supports this command it is also expected to
5359 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5360 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005361 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005362
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005363 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005364 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005365 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005366 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005367 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005368 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005369 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005370 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005371 }
5372
5373 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5374 if (err < 0)
5375 goto unlock;
5376
5377 if (changed)
5378 err = new_settings(hdev, sk);
5379
5380unlock:
5381 hci_dev_unlock(hdev);
5382 return err;
5383}
5384
Johan Hedberg41edf162014-02-18 10:19:35 +02005385static bool irk_is_valid(struct mgmt_irk_info *irk)
5386{
5387 switch (irk->addr.type) {
5388 case BDADDR_LE_PUBLIC:
5389 return true;
5390
5391 case BDADDR_LE_RANDOM:
5392 /* Two most significant bits shall be set */
5393 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5394 return false;
5395 return true;
5396 }
5397
5398 return false;
5399}
5400
5401static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5402 u16 len)
5403{
5404 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005405 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5406 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005407 u16 irk_count, expected_len;
5408 int i, err;
5409
5410 BT_DBG("request for %s", hdev->name);
5411
5412 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005413 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5414 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005415
5416 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005417 if (irk_count > max_irk_count) {
5418 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005419 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5420 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005421 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005422
5423 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5424 if (expected_len != len) {
5425 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005426 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005427 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5428 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005429 }
5430
5431 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5432
5433 for (i = 0; i < irk_count; i++) {
5434 struct mgmt_irk_info *key = &cp->irks[i];
5435
5436 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005437 return mgmt_cmd_status(sk, hdev->id,
5438 MGMT_OP_LOAD_IRKS,
5439 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005440 }
5441
5442 hci_dev_lock(hdev);
5443
5444 hci_smp_irks_clear(hdev);
5445
5446 for (i = 0; i < irk_count; i++) {
5447 struct mgmt_irk_info *irk = &cp->irks[i];
5448 u8 addr_type;
5449
5450 if (irk->addr.type == BDADDR_LE_PUBLIC)
5451 addr_type = ADDR_LE_DEV_PUBLIC;
5452 else
5453 addr_type = ADDR_LE_DEV_RANDOM;
5454
5455 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5456 BDADDR_ANY);
5457 }
5458
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005459 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005460
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005461 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005462
5463 hci_dev_unlock(hdev);
5464
5465 return err;
5466}
5467
Johan Hedberg3f706b72013-01-20 14:27:16 +02005468static bool ltk_is_valid(struct mgmt_ltk_info *key)
5469{
5470 if (key->master != 0x00 && key->master != 0x01)
5471 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005472
5473 switch (key->addr.type) {
5474 case BDADDR_LE_PUBLIC:
5475 return true;
5476
5477 case BDADDR_LE_RANDOM:
5478 /* Two most significant bits shall be set */
5479 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5480 return false;
5481 return true;
5482 }
5483
5484 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005485}
5486
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005487static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005488 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005489{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005490 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005491 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5492 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005493 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005494 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005495
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005496 BT_DBG("request for %s", hdev->name);
5497
5498 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005499 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5500 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005501
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005502 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005503 if (key_count > max_key_count) {
5504 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005505 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5506 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005507 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005508
5509 expected_len = sizeof(*cp) + key_count *
5510 sizeof(struct mgmt_ltk_info);
5511 if (expected_len != len) {
5512 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005513 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005514 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5515 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005516 }
5517
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005518 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005519
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005520 for (i = 0; i < key_count; i++) {
5521 struct mgmt_ltk_info *key = &cp->keys[i];
5522
Johan Hedberg3f706b72013-01-20 14:27:16 +02005523 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005524 return mgmt_cmd_status(sk, hdev->id,
5525 MGMT_OP_LOAD_LONG_TERM_KEYS,
5526 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005527 }
5528
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005529 hci_dev_lock(hdev);
5530
5531 hci_smp_ltks_clear(hdev);
5532
5533 for (i = 0; i < key_count; i++) {
5534 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005535 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005536
5537 if (key->addr.type == BDADDR_LE_PUBLIC)
5538 addr_type = ADDR_LE_DEV_PUBLIC;
5539 else
5540 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005541
Johan Hedberg61b43352014-05-29 19:36:53 +03005542 switch (key->type) {
5543 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005544 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005545 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005546 break;
5547 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005548 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005549 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005550 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005551 case MGMT_LTK_P256_UNAUTH:
5552 authenticated = 0x00;
5553 type = SMP_LTK_P256;
5554 break;
5555 case MGMT_LTK_P256_AUTH:
5556 authenticated = 0x01;
5557 type = SMP_LTK_P256;
5558 break;
5559 case MGMT_LTK_P256_DEBUG:
5560 authenticated = 0x00;
5561 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005562 default:
5563 continue;
5564 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005565
Johan Hedberg35d70272014-02-19 14:57:47 +02005566 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005567 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005568 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005569 }
5570
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005571 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005572 NULL, 0);
5573
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005574 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005575
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005576 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005577}
5578
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005579static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005580{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005581 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005582 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005583 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005584
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005585 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005586
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005587 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005588 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005589 rp.tx_power = conn->tx_power;
5590 rp.max_tx_power = conn->max_tx_power;
5591 } else {
5592 rp.rssi = HCI_RSSI_INVALID;
5593 rp.tx_power = HCI_TX_POWER_INVALID;
5594 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005595 }
5596
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005597 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5598 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005599
5600 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005601 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005602
5603 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005604}
5605
Marcel Holtmann1904a852015-01-11 13:50:44 -08005606static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5607 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005608{
5609 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005610 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005611 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005612 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005613 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005614
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005615 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005616
5617 hci_dev_lock(hdev);
5618
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005619 /* Commands sent in request are either Read RSSI or Read Transmit Power
5620 * Level so we check which one was last sent to retrieve connection
5621 * handle. Both commands have handle as first parameter so it's safe to
5622 * cast data on the same command struct.
5623 *
5624 * First command sent is always Read RSSI and we fail only if it fails.
5625 * In other case we simply override error to indicate success as we
5626 * already remembered if TX power value is actually valid.
5627 */
5628 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5629 if (!cp) {
5630 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005631 status = MGMT_STATUS_SUCCESS;
5632 } else {
5633 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005634 }
5635
5636 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005637 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005638 goto unlock;
5639 }
5640
5641 handle = __le16_to_cpu(cp->handle);
5642 conn = hci_conn_hash_lookup_handle(hdev, handle);
5643 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005644 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005645 goto unlock;
5646 }
5647
Johan Hedberg333ae952015-03-17 13:48:47 +02005648 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005649 if (!cmd)
5650 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005651
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005652 cmd->cmd_complete(cmd, status);
5653 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005654
5655unlock:
5656 hci_dev_unlock(hdev);
5657}
5658
5659static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5660 u16 len)
5661{
5662 struct mgmt_cp_get_conn_info *cp = data;
5663 struct mgmt_rp_get_conn_info rp;
5664 struct hci_conn *conn;
5665 unsigned long conn_info_age;
5666 int err = 0;
5667
5668 BT_DBG("%s", hdev->name);
5669
5670 memset(&rp, 0, sizeof(rp));
5671 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5672 rp.addr.type = cp->addr.type;
5673
5674 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005675 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5676 MGMT_STATUS_INVALID_PARAMS,
5677 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005678
5679 hci_dev_lock(hdev);
5680
5681 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005682 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5683 MGMT_STATUS_NOT_POWERED, &rp,
5684 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005685 goto unlock;
5686 }
5687
5688 if (cp->addr.type == BDADDR_BREDR)
5689 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5690 &cp->addr.bdaddr);
5691 else
5692 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5693
5694 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005695 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5696 MGMT_STATUS_NOT_CONNECTED, &rp,
5697 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005698 goto unlock;
5699 }
5700
Johan Hedberg333ae952015-03-17 13:48:47 +02005701 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005702 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5703 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005704 goto unlock;
5705 }
5706
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005707 /* To avoid client trying to guess when to poll again for information we
5708 * calculate conn info age as random value between min/max set in hdev.
5709 */
5710 conn_info_age = hdev->conn_info_min_age +
5711 prandom_u32_max(hdev->conn_info_max_age -
5712 hdev->conn_info_min_age);
5713
5714 /* Query controller to refresh cached values if they are too old or were
5715 * never read.
5716 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005717 if (time_after(jiffies, conn->conn_info_timestamp +
5718 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005719 !conn->conn_info_timestamp) {
5720 struct hci_request req;
5721 struct hci_cp_read_tx_power req_txp_cp;
5722 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005723 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005724
5725 hci_req_init(&req, hdev);
5726 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5727 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5728 &req_rssi_cp);
5729
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005730 /* For LE links TX power does not change thus we don't need to
5731 * query for it once value is known.
5732 */
5733 if (!bdaddr_type_is_le(cp->addr.type) ||
5734 conn->tx_power == HCI_TX_POWER_INVALID) {
5735 req_txp_cp.handle = cpu_to_le16(conn->handle);
5736 req_txp_cp.type = 0x00;
5737 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5738 sizeof(req_txp_cp), &req_txp_cp);
5739 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005740
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005741 /* Max TX power needs to be read only once per connection */
5742 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5743 req_txp_cp.handle = cpu_to_le16(conn->handle);
5744 req_txp_cp.type = 0x01;
5745 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5746 sizeof(req_txp_cp), &req_txp_cp);
5747 }
5748
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005749 err = hci_req_run(&req, conn_info_refresh_complete);
5750 if (err < 0)
5751 goto unlock;
5752
5753 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5754 data, len);
5755 if (!cmd) {
5756 err = -ENOMEM;
5757 goto unlock;
5758 }
5759
5760 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005761 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005762 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005763
5764 conn->conn_info_timestamp = jiffies;
5765 } else {
5766 /* Cache is valid, just reply with values cached in hci_conn */
5767 rp.rssi = conn->rssi;
5768 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005769 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005770
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005771 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5772 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005773 }
5774
5775unlock:
5776 hci_dev_unlock(hdev);
5777 return err;
5778}
5779
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005780static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005781{
5782 struct hci_conn *conn = cmd->user_data;
5783 struct mgmt_rp_get_clock_info rp;
5784 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005785 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005786
5787 memset(&rp, 0, sizeof(rp));
5788 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5789
5790 if (status)
5791 goto complete;
5792
5793 hdev = hci_dev_get(cmd->index);
5794 if (hdev) {
5795 rp.local_clock = cpu_to_le32(hdev->clock);
5796 hci_dev_put(hdev);
5797 }
5798
5799 if (conn) {
5800 rp.piconet_clock = cpu_to_le32(conn->clock);
5801 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5802 }
5803
5804complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005805 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5806 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005807
5808 if (conn) {
5809 hci_conn_drop(conn);
5810 hci_conn_put(conn);
5811 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005812
5813 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005814}
5815
Marcel Holtmann1904a852015-01-11 13:50:44 -08005816static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005817{
Johan Hedberg95868422014-06-28 17:54:07 +03005818 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005819 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005820 struct hci_conn *conn;
5821
5822 BT_DBG("%s status %u", hdev->name, status);
5823
5824 hci_dev_lock(hdev);
5825
5826 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5827 if (!hci_cp)
5828 goto unlock;
5829
5830 if (hci_cp->which) {
5831 u16 handle = __le16_to_cpu(hci_cp->handle);
5832 conn = hci_conn_hash_lookup_handle(hdev, handle);
5833 } else {
5834 conn = NULL;
5835 }
5836
Johan Hedberg333ae952015-03-17 13:48:47 +02005837 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005838 if (!cmd)
5839 goto unlock;
5840
Johan Hedberg69487372014-12-05 13:36:07 +02005841 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005842 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005843
5844unlock:
5845 hci_dev_unlock(hdev);
5846}
5847
5848static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5849 u16 len)
5850{
5851 struct mgmt_cp_get_clock_info *cp = data;
5852 struct mgmt_rp_get_clock_info rp;
5853 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005854 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005855 struct hci_request req;
5856 struct hci_conn *conn;
5857 int err;
5858
5859 BT_DBG("%s", hdev->name);
5860
5861 memset(&rp, 0, sizeof(rp));
5862 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5863 rp.addr.type = cp->addr.type;
5864
5865 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005866 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5867 MGMT_STATUS_INVALID_PARAMS,
5868 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005869
5870 hci_dev_lock(hdev);
5871
5872 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005873 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5874 MGMT_STATUS_NOT_POWERED, &rp,
5875 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005876 goto unlock;
5877 }
5878
5879 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5880 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5881 &cp->addr.bdaddr);
5882 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005883 err = mgmt_cmd_complete(sk, hdev->id,
5884 MGMT_OP_GET_CLOCK_INFO,
5885 MGMT_STATUS_NOT_CONNECTED,
5886 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005887 goto unlock;
5888 }
5889 } else {
5890 conn = NULL;
5891 }
5892
5893 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5894 if (!cmd) {
5895 err = -ENOMEM;
5896 goto unlock;
5897 }
5898
Johan Hedberg69487372014-12-05 13:36:07 +02005899 cmd->cmd_complete = clock_info_cmd_complete;
5900
Johan Hedberg95868422014-06-28 17:54:07 +03005901 hci_req_init(&req, hdev);
5902
5903 memset(&hci_cp, 0, sizeof(hci_cp));
5904 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5905
5906 if (conn) {
5907 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005908 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005909
5910 hci_cp.handle = cpu_to_le16(conn->handle);
5911 hci_cp.which = 0x01; /* Piconet clock */
5912 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5913 }
5914
5915 err = hci_req_run(&req, get_clock_info_complete);
5916 if (err < 0)
5917 mgmt_pending_remove(cmd);
5918
5919unlock:
5920 hci_dev_unlock(hdev);
5921 return err;
5922}
5923
Johan Hedberg5a154e62014-12-19 22:26:02 +02005924static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5925{
5926 struct hci_conn *conn;
5927
5928 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5929 if (!conn)
5930 return false;
5931
5932 if (conn->dst_type != type)
5933 return false;
5934
5935 if (conn->state != BT_CONNECTED)
5936 return false;
5937
5938 return true;
5939}
5940
5941/* This function requires the caller holds hdev->lock */
5942static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5943 u8 addr_type, u8 auto_connect)
5944{
5945 struct hci_dev *hdev = req->hdev;
5946 struct hci_conn_params *params;
5947
5948 params = hci_conn_params_add(hdev, addr, addr_type);
5949 if (!params)
5950 return -EIO;
5951
5952 if (params->auto_connect == auto_connect)
5953 return 0;
5954
5955 list_del_init(&params->action);
5956
5957 switch (auto_connect) {
5958 case HCI_AUTO_CONN_DISABLED:
5959 case HCI_AUTO_CONN_LINK_LOSS:
5960 __hci_update_background_scan(req);
5961 break;
5962 case HCI_AUTO_CONN_REPORT:
5963 list_add(&params->action, &hdev->pend_le_reports);
5964 __hci_update_background_scan(req);
5965 break;
5966 case HCI_AUTO_CONN_DIRECT:
5967 case HCI_AUTO_CONN_ALWAYS:
5968 if (!is_connected(hdev, addr, addr_type)) {
5969 list_add(&params->action, &hdev->pend_le_conns);
5970 __hci_update_background_scan(req);
5971 }
5972 break;
5973 }
5974
5975 params->auto_connect = auto_connect;
5976
5977 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5978 auto_connect);
5979
5980 return 0;
5981}
5982
Marcel Holtmann8afef092014-06-29 22:28:34 +02005983static void device_added(struct sock *sk, struct hci_dev *hdev,
5984 bdaddr_t *bdaddr, u8 type, u8 action)
5985{
5986 struct mgmt_ev_device_added ev;
5987
5988 bacpy(&ev.addr.bdaddr, bdaddr);
5989 ev.addr.type = type;
5990 ev.action = action;
5991
5992 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5993}
5994
Marcel Holtmann1904a852015-01-11 13:50:44 -08005995static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005996{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005997 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005998
5999 BT_DBG("status 0x%02x", status);
6000
6001 hci_dev_lock(hdev);
6002
Johan Hedberg333ae952015-03-17 13:48:47 +02006003 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006004 if (!cmd)
6005 goto unlock;
6006
6007 cmd->cmd_complete(cmd, mgmt_status(status));
6008 mgmt_pending_remove(cmd);
6009
6010unlock:
6011 hci_dev_unlock(hdev);
6012}
6013
Marcel Holtmann2faade52014-06-29 19:44:03 +02006014static int add_device(struct sock *sk, struct hci_dev *hdev,
6015 void *data, u16 len)
6016{
6017 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006018 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006019 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006020 u8 auto_conn, addr_type;
6021 int err;
6022
6023 BT_DBG("%s", hdev->name);
6024
Johan Hedberg66593582014-07-09 12:59:14 +03006025 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02006026 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006027 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6028 MGMT_STATUS_INVALID_PARAMS,
6029 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006030
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006031 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006032 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6033 MGMT_STATUS_INVALID_PARAMS,
6034 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006035
Johan Hedberg5a154e62014-12-19 22:26:02 +02006036 hci_req_init(&req, hdev);
6037
Marcel Holtmann2faade52014-06-29 19:44:03 +02006038 hci_dev_lock(hdev);
6039
Johan Hedberg5a154e62014-12-19 22:26:02 +02006040 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
6041 if (!cmd) {
6042 err = -ENOMEM;
6043 goto unlock;
6044 }
6045
6046 cmd->cmd_complete = addr_cmd_complete;
6047
Johan Hedberg66593582014-07-09 12:59:14 +03006048 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006049 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03006050 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006051 err = cmd->cmd_complete(cmd,
6052 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006053 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006054 goto unlock;
6055 }
6056
6057 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
6058 cp->addr.type);
6059 if (err)
6060 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03006061
Johan Hedberg5a154e62014-12-19 22:26:02 +02006062 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006063
Johan Hedberg66593582014-07-09 12:59:14 +03006064 goto added;
6065 }
6066
Marcel Holtmann2faade52014-06-29 19:44:03 +02006067 if (cp->addr.type == BDADDR_LE_PUBLIC)
6068 addr_type = ADDR_LE_DEV_PUBLIC;
6069 else
6070 addr_type = ADDR_LE_DEV_RANDOM;
6071
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006072 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006073 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006074 else if (cp->action == 0x01)
6075 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006076 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006077 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006078
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006079 /* If the connection parameters don't exist for this device,
6080 * they will be created and configured with defaults.
6081 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006082 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006083 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006084 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006085 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006086 goto unlock;
6087 }
6088
Johan Hedberg66593582014-07-09 12:59:14 +03006089added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006090 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6091
Johan Hedberg5a154e62014-12-19 22:26:02 +02006092 err = hci_req_run(&req, add_device_complete);
6093 if (err < 0) {
6094 /* ENODATA means no HCI commands were needed (e.g. if
6095 * the adapter is powered off).
6096 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006097 if (err == -ENODATA)
6098 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006099 mgmt_pending_remove(cmd);
6100 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006101
6102unlock:
6103 hci_dev_unlock(hdev);
6104 return err;
6105}
6106
Marcel Holtmann8afef092014-06-29 22:28:34 +02006107static void device_removed(struct sock *sk, struct hci_dev *hdev,
6108 bdaddr_t *bdaddr, u8 type)
6109{
6110 struct mgmt_ev_device_removed ev;
6111
6112 bacpy(&ev.addr.bdaddr, bdaddr);
6113 ev.addr.type = type;
6114
6115 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6116}
6117
Marcel Holtmann1904a852015-01-11 13:50:44 -08006118static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006119{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006120 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006121
6122 BT_DBG("status 0x%02x", status);
6123
6124 hci_dev_lock(hdev);
6125
Johan Hedberg333ae952015-03-17 13:48:47 +02006126 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006127 if (!cmd)
6128 goto unlock;
6129
6130 cmd->cmd_complete(cmd, mgmt_status(status));
6131 mgmt_pending_remove(cmd);
6132
6133unlock:
6134 hci_dev_unlock(hdev);
6135}
6136
Marcel Holtmann2faade52014-06-29 19:44:03 +02006137static int remove_device(struct sock *sk, struct hci_dev *hdev,
6138 void *data, u16 len)
6139{
6140 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006141 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006142 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006143 int err;
6144
6145 BT_DBG("%s", hdev->name);
6146
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006147 hci_req_init(&req, hdev);
6148
Marcel Holtmann2faade52014-06-29 19:44:03 +02006149 hci_dev_lock(hdev);
6150
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006151 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6152 if (!cmd) {
6153 err = -ENOMEM;
6154 goto unlock;
6155 }
6156
6157 cmd->cmd_complete = addr_cmd_complete;
6158
Marcel Holtmann2faade52014-06-29 19:44:03 +02006159 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006160 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006161 u8 addr_type;
6162
Johan Hedberg66593582014-07-09 12:59:14 +03006163 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006164 err = cmd->cmd_complete(cmd,
6165 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006166 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006167 goto unlock;
6168 }
6169
Johan Hedberg66593582014-07-09 12:59:14 +03006170 if (cp->addr.type == BDADDR_BREDR) {
6171 err = hci_bdaddr_list_del(&hdev->whitelist,
6172 &cp->addr.bdaddr,
6173 cp->addr.type);
6174 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006175 err = cmd->cmd_complete(cmd,
6176 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006177 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006178 goto unlock;
6179 }
6180
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006181 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006182
Johan Hedberg66593582014-07-09 12:59:14 +03006183 device_removed(sk, hdev, &cp->addr.bdaddr,
6184 cp->addr.type);
6185 goto complete;
6186 }
6187
Marcel Holtmann2faade52014-06-29 19:44:03 +02006188 if (cp->addr.type == BDADDR_LE_PUBLIC)
6189 addr_type = ADDR_LE_DEV_PUBLIC;
6190 else
6191 addr_type = ADDR_LE_DEV_RANDOM;
6192
Johan Hedbergc71593d2014-07-02 17:37:28 +03006193 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6194 addr_type);
6195 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006196 err = cmd->cmd_complete(cmd,
6197 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006198 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006199 goto unlock;
6200 }
6201
6202 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006203 err = cmd->cmd_complete(cmd,
6204 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006205 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006206 goto unlock;
6207 }
6208
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006209 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006210 list_del(&params->list);
6211 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006212 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006213
6214 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006215 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006216 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006217 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006218
Marcel Holtmann2faade52014-06-29 19:44:03 +02006219 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006220 err = cmd->cmd_complete(cmd,
6221 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006222 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006223 goto unlock;
6224 }
6225
Johan Hedberg66593582014-07-09 12:59:14 +03006226 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6227 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6228 list_del(&b->list);
6229 kfree(b);
6230 }
6231
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006232 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006233
Johan Hedberg19de0822014-07-06 13:06:51 +03006234 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6235 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6236 continue;
6237 device_removed(sk, hdev, &p->addr, p->addr_type);
6238 list_del(&p->action);
6239 list_del(&p->list);
6240 kfree(p);
6241 }
6242
6243 BT_DBG("All LE connection parameters were removed");
6244
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006245 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006246 }
6247
Johan Hedberg66593582014-07-09 12:59:14 +03006248complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006249 err = hci_req_run(&req, remove_device_complete);
6250 if (err < 0) {
6251 /* ENODATA means no HCI commands were needed (e.g. if
6252 * the adapter is powered off).
6253 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006254 if (err == -ENODATA)
6255 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006256 mgmt_pending_remove(cmd);
6257 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006258
6259unlock:
6260 hci_dev_unlock(hdev);
6261 return err;
6262}
6263
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006264static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6265 u16 len)
6266{
6267 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006268 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6269 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006270 u16 param_count, expected_len;
6271 int i;
6272
6273 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006274 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6275 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006276
6277 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006278 if (param_count > max_param_count) {
6279 BT_ERR("load_conn_param: too big param_count value %u",
6280 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006281 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6282 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006283 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006284
6285 expected_len = sizeof(*cp) + param_count *
6286 sizeof(struct mgmt_conn_param);
6287 if (expected_len != len) {
6288 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6289 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006290 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6291 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006292 }
6293
6294 BT_DBG("%s param_count %u", hdev->name, param_count);
6295
6296 hci_dev_lock(hdev);
6297
6298 hci_conn_params_clear_disabled(hdev);
6299
6300 for (i = 0; i < param_count; i++) {
6301 struct mgmt_conn_param *param = &cp->params[i];
6302 struct hci_conn_params *hci_param;
6303 u16 min, max, latency, timeout;
6304 u8 addr_type;
6305
6306 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6307 param->addr.type);
6308
6309 if (param->addr.type == BDADDR_LE_PUBLIC) {
6310 addr_type = ADDR_LE_DEV_PUBLIC;
6311 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6312 addr_type = ADDR_LE_DEV_RANDOM;
6313 } else {
6314 BT_ERR("Ignoring invalid connection parameters");
6315 continue;
6316 }
6317
6318 min = le16_to_cpu(param->min_interval);
6319 max = le16_to_cpu(param->max_interval);
6320 latency = le16_to_cpu(param->latency);
6321 timeout = le16_to_cpu(param->timeout);
6322
6323 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6324 min, max, latency, timeout);
6325
6326 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6327 BT_ERR("Ignoring invalid connection parameters");
6328 continue;
6329 }
6330
6331 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6332 addr_type);
6333 if (!hci_param) {
6334 BT_ERR("Failed to add connection parameters");
6335 continue;
6336 }
6337
6338 hci_param->conn_min_interval = min;
6339 hci_param->conn_max_interval = max;
6340 hci_param->conn_latency = latency;
6341 hci_param->supervision_timeout = timeout;
6342 }
6343
6344 hci_dev_unlock(hdev);
6345
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006346 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6347 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006348}
6349
Marcel Holtmanndbece372014-07-04 18:11:55 +02006350static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6351 void *data, u16 len)
6352{
6353 struct mgmt_cp_set_external_config *cp = data;
6354 bool changed;
6355 int err;
6356
6357 BT_DBG("%s", hdev->name);
6358
6359 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006360 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6361 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006362
6363 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006364 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6365 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006366
6367 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006368 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6369 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006370
6371 hci_dev_lock(hdev);
6372
6373 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006374 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006375 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006376 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006377
6378 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6379 if (err < 0)
6380 goto unlock;
6381
6382 if (!changed)
6383 goto unlock;
6384
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006385 err = new_options(hdev, sk);
6386
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006387 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006388 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006389
Marcel Holtmann516018a2015-03-13 02:11:04 -07006390 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006391 hci_dev_set_flag(hdev, HCI_CONFIG);
6392 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006393
6394 queue_work(hdev->req_workqueue, &hdev->power_on);
6395 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006396 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006397 mgmt_index_added(hdev);
6398 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006399 }
6400
6401unlock:
6402 hci_dev_unlock(hdev);
6403 return err;
6404}
6405
Marcel Holtmann9713c172014-07-06 12:11:15 +02006406static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6407 void *data, u16 len)
6408{
6409 struct mgmt_cp_set_public_address *cp = data;
6410 bool changed;
6411 int err;
6412
6413 BT_DBG("%s", hdev->name);
6414
6415 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006416 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6417 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006418
6419 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006420 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6421 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006422
6423 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006424 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6425 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006426
6427 hci_dev_lock(hdev);
6428
6429 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6430 bacpy(&hdev->public_addr, &cp->bdaddr);
6431
6432 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6433 if (err < 0)
6434 goto unlock;
6435
6436 if (!changed)
6437 goto unlock;
6438
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006439 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006440 err = new_options(hdev, sk);
6441
6442 if (is_configured(hdev)) {
6443 mgmt_index_removed(hdev);
6444
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006445 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006446
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006447 hci_dev_set_flag(hdev, HCI_CONFIG);
6448 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006449
6450 queue_work(hdev->req_workqueue, &hdev->power_on);
6451 }
6452
6453unlock:
6454 hci_dev_unlock(hdev);
6455 return err;
6456}
6457
Marcel Holtmannbea41602015-03-14 22:43:17 -07006458static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6459 u8 data_len)
6460{
6461 eir[eir_len++] = sizeof(type) + data_len;
6462 eir[eir_len++] = type;
6463 memcpy(&eir[eir_len], data, data_len);
6464 eir_len += data_len;
6465
6466 return eir_len;
6467}
6468
Johan Hedberg40f66c02015-04-07 21:52:22 +03006469static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
6470 u16 opcode, struct sk_buff *skb)
6471{
6472 const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
6473 struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
6474 u8 *h192, *r192, *h256, *r256;
6475 struct mgmt_pending_cmd *cmd;
6476 u16 eir_len;
6477 int err;
6478
6479 BT_DBG("%s status %u", hdev->name, status);
6480
6481 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
6482 if (!cmd)
6483 return;
6484
6485 mgmt_cp = cmd->param;
6486
6487 if (status) {
6488 status = mgmt_status(status);
6489 eir_len = 0;
6490
6491 h192 = NULL;
6492 r192 = NULL;
6493 h256 = NULL;
6494 r256 = NULL;
6495 } else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
6496 struct hci_rp_read_local_oob_data *rp;
6497
6498 if (skb->len != sizeof(*rp)) {
6499 status = MGMT_STATUS_FAILED;
6500 eir_len = 0;
6501 } else {
6502 status = MGMT_STATUS_SUCCESS;
6503 rp = (void *)skb->data;
6504
6505 eir_len = 5 + 18 + 18;
6506 h192 = rp->hash;
6507 r192 = rp->rand;
6508 h256 = NULL;
6509 r256 = NULL;
6510 }
6511 } else {
6512 struct hci_rp_read_local_oob_ext_data *rp;
6513
6514 if (skb->len != sizeof(*rp)) {
6515 status = MGMT_STATUS_FAILED;
6516 eir_len = 0;
6517 } else {
6518 status = MGMT_STATUS_SUCCESS;
6519 rp = (void *)skb->data;
6520
6521 if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
6522 eir_len = 5 + 18 + 18;
6523 h192 = NULL;
6524 r192 = NULL;
6525 } else {
6526 eir_len = 5 + 18 + 18 + 18 + 18;
6527 h192 = rp->hash192;
6528 r192 = rp->rand192;
6529 }
6530
6531 h256 = rp->hash256;
6532 r256 = rp->rand256;
6533 }
6534 }
6535
6536 mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
6537 if (!mgmt_rp)
6538 goto done;
6539
6540 if (status)
6541 goto send_rsp;
6542
6543 eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
6544 hdev->dev_class, 3);
6545
6546 if (h192 && r192) {
6547 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6548 EIR_SSP_HASH_C192, h192, 16);
6549 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6550 EIR_SSP_RAND_R192, r192, 16);
6551 }
6552
6553 if (h256 && r256) {
6554 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6555 EIR_SSP_HASH_C256, h256, 16);
6556 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6557 EIR_SSP_RAND_R256, r256, 16);
6558 }
6559
6560send_rsp:
6561 mgmt_rp->type = mgmt_cp->type;
6562 mgmt_rp->eir_len = cpu_to_le16(eir_len);
6563
6564 err = mgmt_cmd_complete(cmd->sk, hdev->id,
6565 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
6566 mgmt_rp, sizeof(*mgmt_rp) + eir_len);
6567 if (err < 0 || status)
6568 goto done;
6569
6570 hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
6571
6572 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6573 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
6574 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
6575done:
6576 kfree(mgmt_rp);
6577 mgmt_pending_remove(cmd);
6578}
6579
6580static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
6581 struct mgmt_cp_read_local_oob_ext_data *cp)
6582{
6583 struct mgmt_pending_cmd *cmd;
6584 struct hci_request req;
6585 int err;
6586
6587 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
6588 cp, sizeof(*cp));
6589 if (!cmd)
6590 return -ENOMEM;
6591
6592 hci_req_init(&req, hdev);
6593
6594 if (bredr_sc_enabled(hdev))
6595 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
6596 else
6597 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
6598
6599 err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
6600 if (err < 0) {
6601 mgmt_pending_remove(cmd);
6602 return err;
6603 }
6604
6605 return 0;
6606}
6607
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006608static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6609 void *data, u16 data_len)
6610{
6611 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6612 struct mgmt_rp_read_local_oob_ext_data *rp;
6613 size_t rp_len;
6614 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006615 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006616 int err;
6617
6618 BT_DBG("%s", hdev->name);
6619
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006620 if (hdev_is_powered(hdev)) {
6621 switch (cp->type) {
6622 case BIT(BDADDR_BREDR):
6623 status = mgmt_bredr_support(hdev);
6624 if (status)
6625 eir_len = 0;
6626 else
6627 eir_len = 5;
6628 break;
6629 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6630 status = mgmt_le_support(hdev);
6631 if (status)
6632 eir_len = 0;
6633 else
6634 eir_len = 9 + 3 + 18 + 18 + 3;
6635 break;
6636 default:
6637 status = MGMT_STATUS_INVALID_PARAMS;
6638 eir_len = 0;
6639 break;
6640 }
6641 } else {
6642 status = MGMT_STATUS_NOT_POWERED;
6643 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006644 }
6645
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006646 rp_len = sizeof(*rp) + eir_len;
6647 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006648 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006649 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006650
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006651 if (status)
6652 goto complete;
6653
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006654 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006655
6656 eir_len = 0;
6657 switch (cp->type) {
6658 case BIT(BDADDR_BREDR):
Johan Hedberg40f66c02015-04-07 21:52:22 +03006659 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
6660 err = read_local_ssp_oob_req(hdev, sk, cp);
6661 hci_dev_unlock(hdev);
6662 if (!err)
6663 goto done;
6664
6665 status = MGMT_STATUS_FAILED;
6666 goto complete;
6667 } else {
6668 eir_len = eir_append_data(rp->eir, eir_len,
6669 EIR_CLASS_OF_DEV,
6670 hdev->dev_class, 3);
6671 }
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006672 break;
6673 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006674 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6675 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006676 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006677 status = MGMT_STATUS_FAILED;
6678 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006679 }
6680
Marcel Holtmanne2135682015-04-02 12:00:58 -07006681 /* This should return the active RPA, but since the RPA
6682 * is only programmed on demand, it is really hard to fill
6683 * this in at the moment. For now disallow retrieving
6684 * local out-of-band data when privacy is in use.
6685 *
6686 * Returning the identity address will not help here since
6687 * pairing happens before the identity resolving key is
6688 * known and thus the connection establishment happens
6689 * based on the RPA and not the identity address.
6690 */
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006691 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
Marcel Holtmanne2135682015-04-02 12:00:58 -07006692 hci_dev_unlock(hdev);
6693 status = MGMT_STATUS_REJECTED;
6694 goto complete;
6695 }
6696
6697 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6698 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6699 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6700 bacmp(&hdev->static_addr, BDADDR_ANY))) {
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006701 memcpy(addr, &hdev->static_addr, 6);
6702 addr[6] = 0x01;
6703 } else {
6704 memcpy(addr, &hdev->bdaddr, 6);
6705 addr[6] = 0x00;
6706 }
6707
6708 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6709 addr, sizeof(addr));
6710
6711 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6712 role = 0x02;
6713 else
6714 role = 0x01;
6715
6716 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6717 &role, sizeof(role));
6718
Marcel Holtmann5082a592015-03-16 12:39:00 -07006719 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6720 eir_len = eir_append_data(rp->eir, eir_len,
6721 EIR_LE_SC_CONFIRM,
6722 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006723
Marcel Holtmann5082a592015-03-16 12:39:00 -07006724 eir_len = eir_append_data(rp->eir, eir_len,
6725 EIR_LE_SC_RANDOM,
6726 rand, sizeof(rand));
6727 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006728
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006729 flags = get_adv_discov_flags(hdev);
6730
6731 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6732 flags |= LE_AD_NO_BREDR;
6733
6734 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6735 &flags, sizeof(flags));
6736 break;
6737 }
6738
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006739 hci_dev_unlock(hdev);
6740
Marcel Holtmann72000df2015-03-16 16:11:21 -07006741 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6742
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006743 status = MGMT_STATUS_SUCCESS;
6744
6745complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006746 rp->type = cp->type;
6747 rp->eir_len = cpu_to_le16(eir_len);
6748
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006749 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006750 status, rp, sizeof(*rp) + eir_len);
6751 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006752 goto done;
6753
6754 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6755 rp, sizeof(*rp) + eir_len,
6756 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006757
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006758done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006759 kfree(rp);
6760
6761 return err;
6762}
6763
Arman Uguray089fa8c2015-03-25 18:53:45 -07006764static u32 get_supported_adv_flags(struct hci_dev *hdev)
6765{
6766 u32 flags = 0;
6767
6768 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6769 flags |= MGMT_ADV_FLAG_DISCOV;
6770 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6771 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6772
6773 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6774 flags |= MGMT_ADV_FLAG_TX_POWER;
6775
6776 return flags;
6777}
6778
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006779static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6780 void *data, u16 data_len)
6781{
6782 struct mgmt_rp_read_adv_features *rp;
6783 size_t rp_len;
6784 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006785 bool instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006786 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006787
6788 BT_DBG("%s", hdev->name);
6789
Arman Uguray089fa8c2015-03-25 18:53:45 -07006790 if (!lmp_le_capable(hdev))
6791 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6792 MGMT_STATUS_REJECTED);
6793
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006794 hci_dev_lock(hdev);
6795
6796 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006797
6798 /* Currently only one instance is supported, so just add 1 to the
6799 * response length.
6800 */
6801 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6802 if (instance)
6803 rp_len++;
6804
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006805 rp = kmalloc(rp_len, GFP_ATOMIC);
6806 if (!rp) {
6807 hci_dev_unlock(hdev);
6808 return -ENOMEM;
6809 }
6810
Arman Uguray089fa8c2015-03-25 18:53:45 -07006811 supported_flags = get_supported_adv_flags(hdev);
6812
6813 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006814 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6815 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Florian Grandeld2609b32015-06-18 03:16:34 +02006816 rp->max_instances = HCI_MAX_ADV_INSTANCES;
Arman Uguray24b4f382015-03-23 15:57:12 -07006817
6818 /* Currently only one instance is supported, so simply return the
6819 * current instance number.
6820 */
6821 if (instance) {
6822 rp->num_instances = 1;
6823 rp->instance[0] = 1;
6824 } else {
6825 rp->num_instances = 0;
6826 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006827
6828 hci_dev_unlock(hdev);
6829
6830 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6831 MGMT_STATUS_SUCCESS, rp, rp_len);
6832
6833 kfree(rp);
6834
6835 return err;
6836}
6837
Arman Uguray4117ed72015-03-23 15:57:14 -07006838static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006839 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006840{
Arman Uguray4117ed72015-03-23 15:57:14 -07006841 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006842 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006843 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006844 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006845 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6846 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006847
Arman Uguray807ec772015-03-25 18:53:42 -07006848 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006849 flags_managed = true;
6850 max_len -= 3;
6851 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006852
Arman Uguray5507e352015-03-25 18:53:44 -07006853 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6854 tx_power_managed = true;
6855 max_len -= 3;
6856 }
6857
Arman Uguray4117ed72015-03-23 15:57:14 -07006858 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006859 return false;
6860
Arman Uguray4117ed72015-03-23 15:57:14 -07006861 /* Make sure that the data is correctly formatted. */
6862 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6863 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006864
Arman Ugurayb44133f2015-03-25 18:53:41 -07006865 if (flags_managed && data[i + 1] == EIR_FLAGS)
6866 return false;
6867
Arman Uguray5507e352015-03-25 18:53:44 -07006868 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6869 return false;
6870
Arman Uguray24b4f382015-03-23 15:57:12 -07006871 /* If the current field length would exceed the total data
6872 * length, then it's invalid.
6873 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006874 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006875 return false;
6876 }
6877
6878 return true;
6879}
6880
Arman Uguray24b4f382015-03-23 15:57:12 -07006881static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6882 u16 opcode)
6883{
6884 struct mgmt_pending_cmd *cmd;
6885 struct mgmt_rp_add_advertising rp;
6886
6887 BT_DBG("status %d", status);
6888
6889 hci_dev_lock(hdev);
6890
6891 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6892
6893 if (status) {
6894 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6895 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6896 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6897 }
6898
6899 if (!cmd)
6900 goto unlock;
6901
6902 rp.instance = 0x01;
6903
6904 if (status)
6905 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6906 mgmt_status(status));
6907 else
6908 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6909 mgmt_status(status), &rp, sizeof(rp));
6910
6911 mgmt_pending_remove(cmd);
6912
6913unlock:
6914 hci_dev_unlock(hdev);
6915}
6916
Florian Grandel5d900e42015-06-18 03:16:35 +02006917void mgmt_adv_timeout_expired(struct hci_dev *hdev)
Arman Uguray912098a2015-03-23 15:57:15 -07006918{
Florian Grandel5d900e42015-06-18 03:16:35 +02006919 hdev->adv_instance_timeout = 0;
Arman Uguray912098a2015-03-23 15:57:15 -07006920
6921 hci_dev_lock(hdev);
6922 clear_adv_instance(hdev);
6923 hci_dev_unlock(hdev);
6924}
6925
Arman Uguray24b4f382015-03-23 15:57:12 -07006926static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6927 void *data, u16 data_len)
6928{
6929 struct mgmt_cp_add_advertising *cp = data;
6930 struct mgmt_rp_add_advertising rp;
6931 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006932 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006933 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006934 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006935 int err;
6936 struct mgmt_pending_cmd *cmd;
6937 struct hci_request req;
6938
6939 BT_DBG("%s", hdev->name);
6940
6941 status = mgmt_le_support(hdev);
6942 if (status)
6943 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6944 status);
6945
6946 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006947 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006948
Arman Uguray089fa8c2015-03-25 18:53:45 -07006949 /* The current implementation only supports adding one instance and only
6950 * a subset of the specified flags.
6951 */
6952 supported_flags = get_supported_adv_flags(hdev);
6953 if (cp->instance != 0x01 || (flags & ~supported_flags))
Arman Uguray24b4f382015-03-23 15:57:12 -07006954 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6955 MGMT_STATUS_INVALID_PARAMS);
6956
6957 hci_dev_lock(hdev);
6958
Arman Uguray912098a2015-03-23 15:57:15 -07006959 if (timeout && !hdev_is_powered(hdev)) {
6960 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6961 MGMT_STATUS_REJECTED);
6962 goto unlock;
6963 }
6964
Arman Uguray24b4f382015-03-23 15:57:12 -07006965 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006966 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006967 pending_find(MGMT_OP_SET_LE, hdev)) {
6968 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6969 MGMT_STATUS_BUSY);
6970 goto unlock;
6971 }
6972
Arman Ugurayb44133f2015-03-25 18:53:41 -07006973 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006974 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006975 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006976 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6977 MGMT_STATUS_INVALID_PARAMS);
6978 goto unlock;
6979 }
6980
6981 hdev->adv_instance.flags = flags;
6982 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6983 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6984
6985 if (cp->adv_data_len)
6986 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6987
6988 if (cp->scan_rsp_len)
6989 memcpy(hdev->adv_instance.scan_rsp_data,
6990 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6991
Florian Grandel5d900e42015-06-18 03:16:35 +02006992 if (hdev->adv_instance_timeout)
6993 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07006994
Florian Grandel5d900e42015-06-18 03:16:35 +02006995 hdev->adv_instance_timeout = timeout;
Arman Uguray912098a2015-03-23 15:57:15 -07006996
6997 if (timeout)
6998 queue_delayed_work(hdev->workqueue,
Florian Grandel5d900e42015-06-18 03:16:35 +02006999 &hdev->adv_instance_expire,
Arman Uguray912098a2015-03-23 15:57:15 -07007000 msecs_to_jiffies(timeout * 1000));
7001
Arman Uguray24b4f382015-03-23 15:57:12 -07007002 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
7003 advertising_added(sk, hdev, 1);
7004
7005 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7006 * we have no HCI communication to make. Simply return.
7007 */
7008 if (!hdev_is_powered(hdev) ||
7009 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7010 rp.instance = 0x01;
7011 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7012 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7013 goto unlock;
7014 }
7015
7016 /* We're good to go, update advertising data, parameters, and start
7017 * advertising.
7018 */
7019 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
7020 data_len);
7021 if (!cmd) {
7022 err = -ENOMEM;
7023 goto unlock;
7024 }
7025
7026 hci_req_init(&req, hdev);
7027
7028 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07007029 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007030 enable_advertising(&req);
7031
7032 err = hci_req_run(&req, add_advertising_complete);
7033 if (err < 0)
7034 mgmt_pending_remove(cmd);
7035
7036unlock:
7037 hci_dev_unlock(hdev);
7038
7039 return err;
7040}
7041
Arman Ugurayda9293352015-03-23 15:57:13 -07007042static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
7043 u16 opcode)
7044{
7045 struct mgmt_pending_cmd *cmd;
7046 struct mgmt_rp_remove_advertising rp;
7047
7048 BT_DBG("status %d", status);
7049
7050 hci_dev_lock(hdev);
7051
7052 /* A failure status here only means that we failed to disable
7053 * advertising. Otherwise, the advertising instance has been removed,
7054 * so report success.
7055 */
7056 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
7057 if (!cmd)
7058 goto unlock;
7059
7060 rp.instance = 1;
7061
7062 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
7063 &rp, sizeof(rp));
7064 mgmt_pending_remove(cmd);
7065
7066unlock:
7067 hci_dev_unlock(hdev);
7068}
7069
7070static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
7071 void *data, u16 data_len)
7072{
7073 struct mgmt_cp_remove_advertising *cp = data;
7074 struct mgmt_rp_remove_advertising rp;
7075 int err;
7076 struct mgmt_pending_cmd *cmd;
7077 struct hci_request req;
7078
7079 BT_DBG("%s", hdev->name);
7080
7081 /* The current implementation only allows modifying instance no 1. A
7082 * value of 0 indicates that all instances should be cleared.
7083 */
7084 if (cp->instance > 1)
7085 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7086 MGMT_STATUS_INVALID_PARAMS);
7087
7088 hci_dev_lock(hdev);
7089
7090 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
7091 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
7092 pending_find(MGMT_OP_SET_LE, hdev)) {
7093 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7094 MGMT_STATUS_BUSY);
7095 goto unlock;
7096 }
7097
7098 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
7099 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7100 MGMT_STATUS_INVALID_PARAMS);
7101 goto unlock;
7102 }
7103
Florian Grandel5d900e42015-06-18 03:16:35 +02007104 if (hdev->adv_instance_timeout)
7105 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07007106
Arman Ugurayda9293352015-03-23 15:57:13 -07007107 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
7108
7109 advertising_removed(sk, hdev, 1);
7110
7111 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
7112
7113 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7114 * we have no HCI communication to make. Simply return.
7115 */
7116 if (!hdev_is_powered(hdev) ||
7117 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7118 rp.instance = 1;
7119 err = mgmt_cmd_complete(sk, hdev->id,
7120 MGMT_OP_REMOVE_ADVERTISING,
7121 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7122 goto unlock;
7123 }
7124
7125 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
7126 data_len);
7127 if (!cmd) {
7128 err = -ENOMEM;
7129 goto unlock;
7130 }
7131
7132 hci_req_init(&req, hdev);
7133 disable_advertising(&req);
7134
7135 err = hci_req_run(&req, remove_advertising_complete);
7136 if (err < 0)
7137 mgmt_pending_remove(cmd);
7138
7139unlock:
7140 hci_dev_unlock(hdev);
7141
7142 return err;
7143}
7144
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007145static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007146 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007147 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007148 HCI_MGMT_NO_HDEV |
7149 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007150 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007151 HCI_MGMT_NO_HDEV |
7152 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007153 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007154 HCI_MGMT_NO_HDEV |
7155 HCI_MGMT_UNTRUSTED },
7156 { read_controller_info, MGMT_READ_INFO_SIZE,
7157 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007158 { set_powered, MGMT_SETTING_SIZE },
7159 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7160 { set_connectable, MGMT_SETTING_SIZE },
7161 { set_fast_connectable, MGMT_SETTING_SIZE },
7162 { set_bondable, MGMT_SETTING_SIZE },
7163 { set_link_security, MGMT_SETTING_SIZE },
7164 { set_ssp, MGMT_SETTING_SIZE },
7165 { set_hs, MGMT_SETTING_SIZE },
7166 { set_le, MGMT_SETTING_SIZE },
7167 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7168 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7169 { add_uuid, MGMT_ADD_UUID_SIZE },
7170 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007171 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7172 HCI_MGMT_VAR_LEN },
7173 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7174 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007175 { disconnect, MGMT_DISCONNECT_SIZE },
7176 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7177 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7178 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7179 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7180 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7181 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7182 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7183 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7184 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7185 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7186 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007187 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7188 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7189 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007190 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7191 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7192 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7193 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7194 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7195 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7196 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7197 { set_advertising, MGMT_SETTING_SIZE },
7198 { set_bredr, MGMT_SETTING_SIZE },
7199 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7200 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7201 { set_secure_conn, MGMT_SETTING_SIZE },
7202 { set_debug_keys, MGMT_SETTING_SIZE },
7203 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007204 { load_irks, MGMT_LOAD_IRKS_SIZE,
7205 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007206 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7207 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7208 { add_device, MGMT_ADD_DEVICE_SIZE },
7209 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007210 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7211 HCI_MGMT_VAR_LEN },
7212 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007213 HCI_MGMT_NO_HDEV |
7214 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007215 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007216 HCI_MGMT_UNCONFIGURED |
7217 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007218 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7219 HCI_MGMT_UNCONFIGURED },
7220 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7221 HCI_MGMT_UNCONFIGURED },
7222 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7223 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007224 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007225 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007226 HCI_MGMT_NO_HDEV |
7227 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007228 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007229 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7230 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007231 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007232};
7233
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007234void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007235{
Marcel Holtmannced85542015-03-14 19:27:56 -07007236 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007237
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007238 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7239 return;
7240
Marcel Holtmannf9207332015-03-14 19:27:55 -07007241 switch (hdev->dev_type) {
7242 case HCI_BREDR:
7243 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7244 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7245 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007246 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007247 } else {
7248 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7249 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007250 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007251 }
7252 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007253 case HCI_AMP:
7254 ev.type = 0x02;
7255 break;
7256 default:
7257 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007258 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007259
7260 ev.bus = hdev->bus;
7261
7262 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7263 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007264}
7265
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007266void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007267{
Marcel Holtmannced85542015-03-14 19:27:56 -07007268 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007269 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007270
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007271 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7272 return;
7273
Marcel Holtmannf9207332015-03-14 19:27:55 -07007274 switch (hdev->dev_type) {
7275 case HCI_BREDR:
7276 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007277
Marcel Holtmannf9207332015-03-14 19:27:55 -07007278 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7279 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7280 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007281 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007282 } else {
7283 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7284 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007285 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007286 }
7287 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007288 case HCI_AMP:
7289 ev.type = 0x02;
7290 break;
7291 default:
7292 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007293 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007294
7295 ev.bus = hdev->bus;
7296
7297 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7298 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007299}
7300
Andre Guedes6046dc32014-02-26 20:21:51 -03007301/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007302static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007303{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007304 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007305 struct hci_conn_params *p;
7306
7307 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007308 /* Needed for AUTO_OFF case where might not "really"
7309 * have been powered off.
7310 */
7311 list_del_init(&p->action);
7312
7313 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007314 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007315 case HCI_AUTO_CONN_ALWAYS:
7316 list_add(&p->action, &hdev->pend_le_conns);
7317 break;
7318 case HCI_AUTO_CONN_REPORT:
7319 list_add(&p->action, &hdev->pend_le_reports);
7320 break;
7321 default:
7322 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007323 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007324 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007325
Johan Hedberg2cf22212014-12-19 22:26:00 +02007326 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007327}
7328
Marcel Holtmann1904a852015-01-11 13:50:44 -08007329static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007330{
7331 struct cmd_lookup match = { NULL, hdev };
7332
7333 BT_DBG("status 0x%02x", status);
7334
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007335 if (!status) {
7336 /* Register the available SMP channels (BR/EDR and LE) only
7337 * when successfully powering on the controller. This late
7338 * registration is required so that LE SMP can clearly
7339 * decide if the public address or static address is used.
7340 */
7341 smp_register(hdev);
7342 }
7343
Johan Hedberg229ab392013-03-15 17:06:53 -05007344 hci_dev_lock(hdev);
7345
7346 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7347
7348 new_settings(hdev, match.sk);
7349
7350 hci_dev_unlock(hdev);
7351
7352 if (match.sk)
7353 sock_put(match.sk);
7354}
7355
Johan Hedberg70da6242013-03-15 17:06:51 -05007356static int powered_update_hci(struct hci_dev *hdev)
7357{
Johan Hedberg890ea892013-03-15 17:06:52 -05007358 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007359 u8 link_sec;
7360
Johan Hedberg890ea892013-03-15 17:06:52 -05007361 hci_req_init(&req, hdev);
7362
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007363 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007364 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007365 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007366
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007367 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007368
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007369 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7370 u8 support = 0x01;
7371
7372 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7373 sizeof(support), &support);
7374 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007375 }
7376
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007377 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007378 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007379 struct hci_cp_write_le_host_supported cp;
7380
Marcel Holtmann32226e42014-07-24 20:04:16 +02007381 cp.le = 0x01;
7382 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007383
7384 /* Check first if we already have the right
7385 * host state (host features set)
7386 */
7387 if (cp.le != lmp_host_le_capable(hdev) ||
7388 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007389 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7390 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007391 }
7392
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007393 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007394 /* Make sure the controller has a good default for
7395 * advertising data. This also applies to the case
7396 * where BR/EDR was toggled during the AUTO_OFF phase.
7397 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007398 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007399 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007400 update_scan_rsp_data(&req);
7401 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007402
Arman Uguray24b4f382015-03-23 15:57:12 -07007403 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7404 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007405 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007406
7407 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007408 }
7409
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007410 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007411 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007412 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7413 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007414
7415 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007416 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007417 write_fast_connectable(&req, true);
7418 else
7419 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007420 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007421 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007422 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007423 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007424 }
7425
Johan Hedberg229ab392013-03-15 17:06:53 -05007426 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007427}
7428
Johan Hedberg744cf192011-11-08 20:40:14 +02007429int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007430{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007431 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007432 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007433 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007434
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007435 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007436 return 0;
7437
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007438 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007439 if (powered_update_hci(hdev) == 0)
7440 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007441
Johan Hedberg229ab392013-03-15 17:06:53 -05007442 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7443 &match);
7444 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007445 }
7446
Johan Hedberg229ab392013-03-15 17:06:53 -05007447 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007448
7449 /* If the power off is because of hdev unregistration let
7450 * use the appropriate INVALID_INDEX status. Otherwise use
7451 * NOT_POWERED. We cover both scenarios here since later in
7452 * mgmt_index_removed() any hci_conn callbacks will have already
7453 * been triggered, potentially causing misleading DISCONNECTED
7454 * status responses.
7455 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007456 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007457 status = MGMT_STATUS_INVALID_INDEX;
7458 else
7459 status = MGMT_STATUS_NOT_POWERED;
7460
7461 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007462
7463 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007464 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7465 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007466
7467new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007468 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007469
7470 if (match.sk)
7471 sock_put(match.sk);
7472
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007473 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007474}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007475
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007476void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007477{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007478 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007479 u8 status;
7480
Johan Hedberg333ae952015-03-17 13:48:47 +02007481 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007482 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007483 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007484
7485 if (err == -ERFKILL)
7486 status = MGMT_STATUS_RFKILLED;
7487 else
7488 status = MGMT_STATUS_FAILED;
7489
Johan Hedberga69e8372015-03-06 21:08:53 +02007490 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007491
7492 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007493}
7494
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007495void mgmt_discoverable_timeout(struct hci_dev *hdev)
7496{
7497 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007498
7499 hci_dev_lock(hdev);
7500
7501 /* When discoverable timeout triggers, then just make sure
7502 * the limited discoverable flag is cleared. Even in the case
7503 * of a timeout triggered from general discoverable, it is
7504 * safe to unconditionally clear the flag.
7505 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007506 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7507 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007508
7509 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007510 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007511 u8 scan = SCAN_PAGE;
7512 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7513 sizeof(scan), &scan);
7514 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007515 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007516
7517 /* Advertising instances don't use the global discoverable setting, so
7518 * only update AD if advertising was enabled using Set Advertising.
7519 */
7520 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7521 update_adv_data(&req);
7522
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007523 hci_req_run(&req, NULL);
7524
7525 hdev->discov_timeout = 0;
7526
Johan Hedberg9a43e252013-10-20 19:00:07 +03007527 new_settings(hdev, NULL);
7528
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007529 hci_dev_unlock(hdev);
7530}
7531
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007532void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7533 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007534{
Johan Hedberg86742e12011-11-07 23:13:38 +02007535 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007536
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007537 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007538
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007539 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007540 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007541 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007542 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007543 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007544 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007545
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007546 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007547}
Johan Hedbergf7520542011-01-20 12:34:39 +02007548
Johan Hedbergd7b25452014-05-23 13:19:53 +03007549static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7550{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007551 switch (ltk->type) {
7552 case SMP_LTK:
7553 case SMP_LTK_SLAVE:
7554 if (ltk->authenticated)
7555 return MGMT_LTK_AUTHENTICATED;
7556 return MGMT_LTK_UNAUTHENTICATED;
7557 case SMP_LTK_P256:
7558 if (ltk->authenticated)
7559 return MGMT_LTK_P256_AUTH;
7560 return MGMT_LTK_P256_UNAUTH;
7561 case SMP_LTK_P256_DEBUG:
7562 return MGMT_LTK_P256_DEBUG;
7563 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007564
7565 return MGMT_LTK_UNAUTHENTICATED;
7566}
7567
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007568void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007569{
7570 struct mgmt_ev_new_long_term_key ev;
7571
7572 memset(&ev, 0, sizeof(ev));
7573
Marcel Holtmann5192d302014-02-19 17:11:58 -08007574 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007575 * without providing an identity resolving key don't require
Marcel Holtmann5192d302014-02-19 17:11:58 -08007576 * to store long term keys. Their addresses will change the
7577 * next time around.
7578 *
7579 * Only when a remote device provides an identity address
7580 * make sure the long term key is stored. If the remote
7581 * identity is known, the long term keys are internally
7582 * mapped to the identity address. So allow static random
7583 * and public addresses here.
7584 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007585 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7586 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7587 ev.store_hint = 0x00;
7588 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007589 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007590
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007591 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007592 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007593 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007594 ev.key.enc_size = key->enc_size;
7595 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007596 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007597
Johan Hedberg2ceba532014-06-16 19:25:16 +03007598 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007599 ev.key.master = 1;
7600
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007601 /* Make sure we copy only the significant bytes based on the
7602 * encryption key size, and set the rest of the value to zeroes.
7603 */
7604 memcpy(ev.key.val, key->val, sizeof(key->enc_size));
7605 memset(ev.key.val + key->enc_size, 0,
7606 sizeof(ev.key.val) - key->enc_size);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007607
Marcel Holtmann083368f2013-10-15 14:26:29 -07007608 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007609}
7610
Johan Hedberg95fbac82014-02-19 15:18:31 +02007611void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7612{
7613 struct mgmt_ev_new_irk ev;
7614
7615 memset(&ev, 0, sizeof(ev));
7616
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007617 /* For identity resolving keys from devices that are already
7618 * using a public address or static random address, do not
7619 * ask for storing this key. The identity resolving key really
Florian Grandelf72186d2015-05-26 03:31:09 +02007620 * is only mandatory for devices using resolvable random
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007621 * addresses.
7622 *
7623 * Storing all identity resolving keys has the downside that
7624 * they will be also loaded on next boot of they system. More
7625 * identity resolving keys, means more time during scanning is
7626 * needed to actually resolve these addresses.
7627 */
7628 if (bacmp(&irk->rpa, BDADDR_ANY))
7629 ev.store_hint = 0x01;
7630 else
7631 ev.store_hint = 0x00;
7632
Johan Hedberg95fbac82014-02-19 15:18:31 +02007633 bacpy(&ev.rpa, &irk->rpa);
7634 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7635 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7636 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7637
7638 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7639}
7640
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007641void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7642 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007643{
7644 struct mgmt_ev_new_csrk ev;
7645
7646 memset(&ev, 0, sizeof(ev));
7647
7648 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007649 * without providing an identity resolving key don't require
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007650 * to store signature resolving keys. Their addresses will change
7651 * the next time around.
7652 *
7653 * Only when a remote device provides an identity address
7654 * make sure the signature resolving key is stored. So allow
7655 * static random and public addresses here.
7656 */
7657 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7658 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7659 ev.store_hint = 0x00;
7660 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007661 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007662
7663 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7664 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007665 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007666 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7667
7668 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7669}
7670
Andre Guedesffb5a8272014-07-01 18:10:11 -03007671void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007672 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7673 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007674{
7675 struct mgmt_ev_new_conn_param ev;
7676
Johan Hedbergc103aea2014-07-02 17:37:34 +03007677 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7678 return;
7679
Andre Guedesffb5a8272014-07-01 18:10:11 -03007680 memset(&ev, 0, sizeof(ev));
7681 bacpy(&ev.addr.bdaddr, bdaddr);
7682 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007683 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007684 ev.min_interval = cpu_to_le16(min_interval);
7685 ev.max_interval = cpu_to_le16(max_interval);
7686 ev.latency = cpu_to_le16(latency);
7687 ev.timeout = cpu_to_le16(timeout);
7688
7689 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7690}
7691
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007692void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7693 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007694{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007695 char buf[512];
7696 struct mgmt_ev_device_connected *ev = (void *) buf;
7697 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007698
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007699 bacpy(&ev->addr.bdaddr, &conn->dst);
7700 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007701
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007702 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007703
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007704 /* We must ensure that the EIR Data fields are ordered and
7705 * unique. Keep it simple for now and avoid the problem by not
7706 * adding any BR/EDR data to the LE adv.
7707 */
7708 if (conn->le_adv_data_len > 0) {
7709 memcpy(&ev->eir[eir_len],
7710 conn->le_adv_data, conn->le_adv_data_len);
7711 eir_len = conn->le_adv_data_len;
7712 } else {
7713 if (name_len > 0)
7714 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7715 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007716
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007717 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007718 eir_len = eir_append_data(ev->eir, eir_len,
7719 EIR_CLASS_OF_DEV,
7720 conn->dev_class, 3);
7721 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007722
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007723 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007724
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007725 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7726 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007727}
7728
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007729static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007730{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007731 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007732
Johan Hedbergf5818c22014-12-05 13:36:02 +02007733 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007734
7735 *sk = cmd->sk;
7736 sock_hold(*sk);
7737
Johan Hedberga664b5b2011-02-19 12:06:02 -03007738 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007739}
7740
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007741static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007742{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007743 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007744 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007745
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007746 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7747
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007748 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007749 mgmt_pending_remove(cmd);
7750}
7751
Johan Hedberg84c61d92014-08-01 11:13:30 +03007752bool mgmt_powering_down(struct hci_dev *hdev)
7753{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007754 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007755 struct mgmt_mode *cp;
7756
Johan Hedberg333ae952015-03-17 13:48:47 +02007757 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007758 if (!cmd)
7759 return false;
7760
7761 cp = cmd->param;
7762 if (!cp->val)
7763 return true;
7764
7765 return false;
7766}
7767
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007768void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007769 u8 link_type, u8 addr_type, u8 reason,
7770 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007771{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007772 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007773 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007774
Johan Hedberg84c61d92014-08-01 11:13:30 +03007775 /* The connection is still in hci_conn_hash so test for 1
7776 * instead of 0 to know if this is the last one.
7777 */
7778 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7779 cancel_delayed_work(&hdev->power_off);
7780 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007781 }
7782
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007783 if (!mgmt_connected)
7784 return;
7785
Andre Guedes57eb7762013-10-30 19:01:41 -03007786 if (link_type != ACL_LINK && link_type != LE_LINK)
7787 return;
7788
Johan Hedberg744cf192011-11-08 20:40:14 +02007789 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007790
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007791 bacpy(&ev.addr.bdaddr, bdaddr);
7792 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7793 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007794
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007795 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007796
7797 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007798 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007799
Johan Hedberg124f6e32012-02-09 13:50:12 +02007800 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007801 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007802}
7803
Marcel Holtmann78929242013-10-06 23:55:47 -07007804void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7805 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007806{
Andre Guedes3655bba2013-10-30 19:01:40 -03007807 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7808 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007809 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007810
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007811 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7812 hdev);
7813
Johan Hedberg333ae952015-03-17 13:48:47 +02007814 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007815 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007816 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007817
Andre Guedes3655bba2013-10-30 19:01:40 -03007818 cp = cmd->param;
7819
7820 if (bacmp(bdaddr, &cp->addr.bdaddr))
7821 return;
7822
7823 if (cp->addr.type != bdaddr_type)
7824 return;
7825
Johan Hedbergf5818c22014-12-05 13:36:02 +02007826 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007827 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007828}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007829
Marcel Holtmann445608d2013-10-06 23:55:48 -07007830void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7831 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007832{
7833 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007834
Johan Hedberg84c61d92014-08-01 11:13:30 +03007835 /* The connection is still in hci_conn_hash so test for 1
7836 * instead of 0 to know if this is the last one.
7837 */
7838 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7839 cancel_delayed_work(&hdev->power_off);
7840 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007841 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007842
Johan Hedberg4c659c32011-11-07 23:13:39 +02007843 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007844 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007845 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007846
Marcel Holtmann445608d2013-10-06 23:55:48 -07007847 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007848}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007849
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007850void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007851{
7852 struct mgmt_ev_pin_code_request ev;
7853
Johan Hedbergd8457692012-02-17 14:24:57 +02007854 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007855 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007856 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007857
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007858 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007859}
7860
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007861void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7862 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007863{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007864 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007865
Johan Hedberg333ae952015-03-17 13:48:47 +02007866 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007867 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007868 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007869
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007870 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007871 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007872}
7873
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007874void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7875 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007876{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007877 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007878
Johan Hedberg333ae952015-03-17 13:48:47 +02007879 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007880 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007881 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007882
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007883 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007884 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007885}
Johan Hedberga5c29682011-02-19 12:05:57 -03007886
Johan Hedberg744cf192011-11-08 20:40:14 +02007887int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007888 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007889 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007890{
7891 struct mgmt_ev_user_confirm_request ev;
7892
Johan Hedberg744cf192011-11-08 20:40:14 +02007893 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007894
Johan Hedberg272d90d2012-02-09 15:26:12 +02007895 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007896 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007897 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007898 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007899
Johan Hedberg744cf192011-11-08 20:40:14 +02007900 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007901 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007902}
7903
Johan Hedberg272d90d2012-02-09 15:26:12 +02007904int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007905 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007906{
7907 struct mgmt_ev_user_passkey_request ev;
7908
7909 BT_DBG("%s", hdev->name);
7910
Johan Hedberg272d90d2012-02-09 15:26:12 +02007911 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007912 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007913
7914 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007915 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007916}
7917
Brian Gix0df4c182011-11-16 13:53:13 -08007918static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007919 u8 link_type, u8 addr_type, u8 status,
7920 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007921{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007922 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007923
Johan Hedberg333ae952015-03-17 13:48:47 +02007924 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007925 if (!cmd)
7926 return -ENOENT;
7927
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007928 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007929 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007930
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007931 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007932}
7933
Johan Hedberg744cf192011-11-08 20:40:14 +02007934int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007935 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007936{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007937 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007938 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007939}
7940
Johan Hedberg272d90d2012-02-09 15:26:12 +02007941int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007942 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007943{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007944 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007945 status,
7946 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007947}
Johan Hedberg2a611692011-02-19 12:06:00 -03007948
Brian Gix604086b2011-11-23 08:28:33 -08007949int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007950 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007951{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007952 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007953 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007954}
7955
Johan Hedberg272d90d2012-02-09 15:26:12 +02007956int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007957 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007958{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007959 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007960 status,
7961 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007962}
7963
Johan Hedberg92a25252012-09-06 18:39:26 +03007964int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7965 u8 link_type, u8 addr_type, u32 passkey,
7966 u8 entered)
7967{
7968 struct mgmt_ev_passkey_notify ev;
7969
7970 BT_DBG("%s", hdev->name);
7971
7972 bacpy(&ev.addr.bdaddr, bdaddr);
7973 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7974 ev.passkey = __cpu_to_le32(passkey);
7975 ev.entered = entered;
7976
7977 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7978}
7979
Johan Hedberge1e930f2014-09-08 17:09:49 -07007980void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007981{
7982 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007983 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007984 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007985
Johan Hedberge1e930f2014-09-08 17:09:49 -07007986 bacpy(&ev.addr.bdaddr, &conn->dst);
7987 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7988 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007989
Johan Hedberge1e930f2014-09-08 17:09:49 -07007990 cmd = find_pairing(conn);
7991
7992 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7993 cmd ? cmd->sk : NULL);
7994
Johan Hedberga511b352014-12-11 21:45:45 +02007995 if (cmd) {
7996 cmd->cmd_complete(cmd, status);
7997 mgmt_pending_remove(cmd);
7998 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007999}
Johan Hedbergb312b1612011-03-16 14:29:37 +02008000
Marcel Holtmann464996a2013-10-15 14:26:24 -07008001void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008002{
8003 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07008004 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008005
8006 if (status) {
8007 u8 mgmt_err = mgmt_status(status);
8008 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008009 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07008010 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008011 }
8012
Marcel Holtmann464996a2013-10-15 14:26:24 -07008013 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07008014 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07008015 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008016 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02008017
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008018 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008019 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008020
Johan Hedberg47990ea2012-02-22 11:58:37 +02008021 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07008022 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008023
8024 if (match.sk)
8025 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008026}
8027
Johan Hedberg890ea892013-03-15 17:06:52 -05008028static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02008029{
Johan Hedberg890ea892013-03-15 17:06:52 -05008030 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008031 struct hci_cp_write_eir cp;
8032
Johan Hedberg976eb202012-10-24 21:12:01 +03008033 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05008034 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008035
Johan Hedbergc80da272012-02-22 15:38:48 +02008036 memset(hdev->eir, 0, sizeof(hdev->eir));
8037
Johan Hedbergcacaf522012-02-21 00:52:42 +02008038 memset(&cp, 0, sizeof(cp));
8039
Johan Hedberg890ea892013-03-15 17:06:52 -05008040 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02008041}
8042
Marcel Holtmann3e248562013-10-15 14:26:25 -07008043void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008044{
8045 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05008046 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008047 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008048
8049 if (status) {
8050 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008051
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008052 if (enable && hci_dev_test_and_clear_flag(hdev,
8053 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008054 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008055 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008056 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008057
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008058 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
8059 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008060 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008061 }
8062
8063 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07008064 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008065 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008066 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008067 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008068 changed = hci_dev_test_and_clear_flag(hdev,
8069 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008070 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008071 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008072 }
8073
8074 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
8075
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008076 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07008077 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008078
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02008079 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008080 sock_put(match.sk);
8081
Johan Hedberg890ea892013-03-15 17:06:52 -05008082 hci_req_init(&req, hdev);
8083
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008084 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
8085 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03008086 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
8087 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05008088 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008089 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05008090 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008091 }
Johan Hedberg890ea892013-03-15 17:06:52 -05008092
8093 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008094}
8095
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008096static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02008097{
8098 struct cmd_lookup *match = data;
8099
Johan Hedberg90e70452012-02-23 23:09:40 +02008100 if (match->sk == NULL) {
8101 match->sk = cmd->sk;
8102 sock_hold(match->sk);
8103 }
Johan Hedberg90e70452012-02-23 23:09:40 +02008104}
8105
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07008106void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
8107 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008108{
Johan Hedberg90e70452012-02-23 23:09:40 +02008109 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008110
Johan Hedberg92da6092013-03-15 17:06:55 -05008111 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
8112 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
8113 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02008114
8115 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008116 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
8117 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02008118
8119 if (match.sk)
8120 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008121}
8122
Marcel Holtmann7667da32013-10-15 14:26:27 -07008123void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02008124{
Johan Hedbergb312b1612011-03-16 14:29:37 +02008125 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008126 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008127
Johan Hedberg13928972013-03-15 17:07:00 -05008128 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07008129 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008130
8131 memset(&ev, 0, sizeof(ev));
8132 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008133 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008134
Johan Hedberg333ae952015-03-17 13:48:47 +02008135 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05008136 if (!cmd) {
8137 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02008138
Johan Hedberg13928972013-03-15 17:07:00 -05008139 /* If this is a HCI command related to powering on the
8140 * HCI dev don't send any mgmt signals.
8141 */
Johan Hedberg333ae952015-03-17 13:48:47 +02008142 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07008143 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008144 }
8145
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008146 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
8147 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008148}
Szymon Jancc35938b2011-03-22 13:12:21 +01008149
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008150static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
8151{
8152 int i;
8153
8154 for (i = 0; i < uuid_count; i++) {
8155 if (!memcmp(uuid, uuids[i], 16))
8156 return true;
8157 }
8158
8159 return false;
8160}
8161
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008162static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
8163{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008164 u16 parsed = 0;
8165
8166 while (parsed < eir_len) {
8167 u8 field_len = eir[0];
8168 u8 uuid[16];
8169 int i;
8170
8171 if (field_len == 0)
8172 break;
8173
8174 if (eir_len - parsed < field_len + 1)
8175 break;
8176
8177 switch (eir[1]) {
8178 case EIR_UUID16_ALL:
8179 case EIR_UUID16_SOME:
8180 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008181 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008182 uuid[13] = eir[i + 3];
8183 uuid[12] = eir[i + 2];
8184 if (has_uuid(uuid, uuid_count, uuids))
8185 return true;
8186 }
8187 break;
8188 case EIR_UUID32_ALL:
8189 case EIR_UUID32_SOME:
8190 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008191 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008192 uuid[15] = eir[i + 5];
8193 uuid[14] = eir[i + 4];
8194 uuid[13] = eir[i + 3];
8195 uuid[12] = eir[i + 2];
8196 if (has_uuid(uuid, uuid_count, uuids))
8197 return true;
8198 }
8199 break;
8200 case EIR_UUID128_ALL:
8201 case EIR_UUID128_SOME:
8202 for (i = 0; i + 17 <= field_len; i += 16) {
8203 memcpy(uuid, eir + i + 2, 16);
8204 if (has_uuid(uuid, uuid_count, uuids))
8205 return true;
8206 }
8207 break;
8208 }
8209
8210 parsed += field_len + 1;
8211 eir += field_len + 1;
8212 }
8213
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008214 return false;
8215}
8216
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008217static void restart_le_scan(struct hci_dev *hdev)
8218{
8219 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008220 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008221 return;
8222
8223 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8224 hdev->discovery.scan_start +
8225 hdev->discovery.scan_duration))
8226 return;
8227
8228 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8229 DISCOV_LE_RESTART_DELAY);
8230}
8231
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008232static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8233 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8234{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008235 /* If a RSSI threshold has been specified, and
8236 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8237 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8238 * is set, let it through for further processing, as we might need to
8239 * restart the scan.
8240 *
8241 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8242 * the results are also dropped.
8243 */
8244 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8245 (rssi == HCI_RSSI_INVALID ||
8246 (rssi < hdev->discovery.rssi &&
8247 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8248 return false;
8249
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008250 if (hdev->discovery.uuid_count != 0) {
8251 /* If a list of UUIDs is provided in filter, results with no
8252 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008253 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008254 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8255 hdev->discovery.uuids) &&
8256 !eir_has_uuids(scan_rsp, scan_rsp_len,
8257 hdev->discovery.uuid_count,
8258 hdev->discovery.uuids))
8259 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008260 }
8261
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008262 /* If duplicate filtering does not report RSSI changes, then restart
8263 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008264 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008265 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8266 restart_le_scan(hdev);
8267
8268 /* Validate RSSI value against the RSSI threshold once more. */
8269 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8270 rssi < hdev->discovery.rssi)
8271 return false;
8272 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008273
8274 return true;
8275}
8276
Marcel Holtmann901801b2013-10-06 23:55:51 -07008277void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008278 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8279 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008280{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008281 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008282 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008283 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008284
Johan Hedberg75ce2082014-07-02 22:42:01 +03008285 /* Don't send events for a non-kernel initiated discovery. With
8286 * LE one exception is if we have pend_le_reports > 0 in which
8287 * case we're doing passive scanning and want these events.
8288 */
8289 if (!hci_discovery_active(hdev)) {
8290 if (link_type == ACL_LINK)
8291 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008292 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008293 return;
8294 }
Andre Guedes12602d02013-04-30 15:29:40 -03008295
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008296 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008297 /* We are using service discovery */
8298 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8299 scan_rsp_len))
8300 return;
8301 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008302
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008303 /* Make sure that the buffer is big enough. The 5 extra bytes
8304 * are for the potential CoD field.
8305 */
8306 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008307 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008308
Johan Hedberg1dc06092012-01-15 21:01:23 +02008309 memset(buf, 0, sizeof(buf));
8310
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008311 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8312 * RSSI value was reported as 0 when not available. This behavior
8313 * is kept when using device discovery. This is required for full
8314 * backwards compatibility with the API.
8315 *
8316 * However when using service discovery, the value 127 will be
8317 * returned when the RSSI is not available.
8318 */
Szymon Janc91200e92015-01-22 16:57:05 +01008319 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8320 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008321 rssi = 0;
8322
Johan Hedberg841c5642014-07-07 12:45:54 +03008323 bacpy(&ev->addr.bdaddr, bdaddr);
8324 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008325 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008326 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008327
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008328 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008329 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008330 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008331
Johan Hedberg1dc06092012-01-15 21:01:23 +02008332 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8333 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008334 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008335
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008336 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008337 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008338 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008339
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008340 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8341 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008342
Marcel Holtmann901801b2013-10-06 23:55:51 -07008343 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008344}
Johan Hedberga88a9652011-03-30 13:18:12 +03008345
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008346void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8347 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008348{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008349 struct mgmt_ev_device_found *ev;
8350 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8351 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008352
Johan Hedbergb644ba32012-01-17 21:48:47 +02008353 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008354
Johan Hedbergb644ba32012-01-17 21:48:47 +02008355 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008356
Johan Hedbergb644ba32012-01-17 21:48:47 +02008357 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008358 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008359 ev->rssi = rssi;
8360
8361 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008362 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008363
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008364 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008365
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008366 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008367}
Johan Hedberg314b2382011-04-27 10:29:57 -04008368
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008369void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008370{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008371 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008372
Andre Guedes343fb142011-11-22 17:14:19 -03008373 BT_DBG("%s discovering %u", hdev->name, discovering);
8374
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008375 memset(&ev, 0, sizeof(ev));
8376 ev.type = hdev->discovery.type;
8377 ev.discovering = discovering;
8378
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008379 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008380}
Antti Julku5e762442011-08-25 16:48:02 +03008381
Marcel Holtmann1904a852015-01-11 13:50:44 -08008382static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008383{
8384 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008385}
8386
8387void mgmt_reenable_advertising(struct hci_dev *hdev)
8388{
8389 struct hci_request req;
8390
Arman Uguray24b4f382015-03-23 15:57:12 -07008391 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8392 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008393 return;
8394
8395 hci_req_init(&req, hdev);
8396 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008397 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008398}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008399
8400static struct hci_mgmt_chan chan = {
8401 .channel = HCI_CHANNEL_CONTROL,
8402 .handler_count = ARRAY_SIZE(mgmt_handlers),
8403 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008404 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008405};
8406
8407int mgmt_init(void)
8408{
8409 return hci_mgmt_chan_register(&chan);
8410}
8411
8412void mgmt_exit(void)
8413{
8414 hci_mgmt_chan_unregister(&chan);
8415}