blob: 05f14c54b7edc6e80ea8da664c58d3d557a515f6 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg71290692015-02-20 13:26:23 +020032#include <net/bluetooth/hci_sock.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030033#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020034#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070035
Johan Hedberg0857dd32014-12-19 13:40:20 +020036#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070037#include "smp.h"
Johan Hedberga380b6c2015-03-17 13:48:48 +020038#include "mgmt_util.h"
Johan Hedberg03811012010-12-08 00:21:06 +020039
Johan Hedberg2da9c552012-02-17 14:39:28 +020040#define MGMT_VERSION 1
Marcel Holtmannbeb1c212015-03-10 14:04:52 -070041#define MGMT_REVISION 9
Johan Hedberg02d98122010-12-13 21:07:04 +020042
Johan Hedberge70bb2e2012-02-13 16:59:33 +020043static const u16 mgmt_commands[] = {
44 MGMT_OP_READ_INDEX_LIST,
45 MGMT_OP_READ_INFO,
46 MGMT_OP_SET_POWERED,
47 MGMT_OP_SET_DISCOVERABLE,
48 MGMT_OP_SET_CONNECTABLE,
49 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030050 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020051 MGMT_OP_SET_LINK_SECURITY,
52 MGMT_OP_SET_SSP,
53 MGMT_OP_SET_HS,
54 MGMT_OP_SET_LE,
55 MGMT_OP_SET_DEV_CLASS,
56 MGMT_OP_SET_LOCAL_NAME,
57 MGMT_OP_ADD_UUID,
58 MGMT_OP_REMOVE_UUID,
59 MGMT_OP_LOAD_LINK_KEYS,
60 MGMT_OP_LOAD_LONG_TERM_KEYS,
61 MGMT_OP_DISCONNECT,
62 MGMT_OP_GET_CONNECTIONS,
63 MGMT_OP_PIN_CODE_REPLY,
64 MGMT_OP_PIN_CODE_NEG_REPLY,
65 MGMT_OP_SET_IO_CAPABILITY,
66 MGMT_OP_PAIR_DEVICE,
67 MGMT_OP_CANCEL_PAIR_DEVICE,
68 MGMT_OP_UNPAIR_DEVICE,
69 MGMT_OP_USER_CONFIRM_REPLY,
70 MGMT_OP_USER_CONFIRM_NEG_REPLY,
71 MGMT_OP_USER_PASSKEY_REPLY,
72 MGMT_OP_USER_PASSKEY_NEG_REPLY,
73 MGMT_OP_READ_LOCAL_OOB_DATA,
74 MGMT_OP_ADD_REMOTE_OOB_DATA,
75 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
76 MGMT_OP_START_DISCOVERY,
77 MGMT_OP_STOP_DISCOVERY,
78 MGMT_OP_CONFIRM_NAME,
79 MGMT_OP_BLOCK_DEVICE,
80 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070081 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030082 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030083 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070084 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070085 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080086 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080087 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020088 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020089 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020090 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030091 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020092 MGMT_OP_ADD_DEVICE,
93 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030094 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020095 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020096 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020097 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020098 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010099 MGMT_OP_START_SERVICE_DISCOVERY,
Marcel Holtmann4f0f1552015-03-14 22:43:19 -0700100 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann96f14742015-03-14 19:27:57 -0700101 MGMT_OP_READ_EXT_INDEX_LIST,
Marcel Holtmannd3d53052015-03-14 20:53:25 -0700102 MGMT_OP_READ_ADV_FEATURES,
Arman Uguray24b4f382015-03-23 15:57:12 -0700103 MGMT_OP_ADD_ADVERTISING,
Arman Ugurayda9293352015-03-23 15:57:13 -0700104 MGMT_OP_REMOVE_ADVERTISING,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200105};
106
107static const u16 mgmt_events[] = {
108 MGMT_EV_CONTROLLER_ERROR,
109 MGMT_EV_INDEX_ADDED,
110 MGMT_EV_INDEX_REMOVED,
111 MGMT_EV_NEW_SETTINGS,
112 MGMT_EV_CLASS_OF_DEV_CHANGED,
113 MGMT_EV_LOCAL_NAME_CHANGED,
114 MGMT_EV_NEW_LINK_KEY,
115 MGMT_EV_NEW_LONG_TERM_KEY,
116 MGMT_EV_DEVICE_CONNECTED,
117 MGMT_EV_DEVICE_DISCONNECTED,
118 MGMT_EV_CONNECT_FAILED,
119 MGMT_EV_PIN_CODE_REQUEST,
120 MGMT_EV_USER_CONFIRM_REQUEST,
121 MGMT_EV_USER_PASSKEY_REQUEST,
122 MGMT_EV_AUTH_FAILED,
123 MGMT_EV_DEVICE_FOUND,
124 MGMT_EV_DISCOVERING,
125 MGMT_EV_DEVICE_BLOCKED,
126 MGMT_EV_DEVICE_UNBLOCKED,
127 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300128 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800129 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700130 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200131 MGMT_EV_DEVICE_ADDED,
132 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300133 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200134 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200135 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200136 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700137 MGMT_EV_EXT_INDEX_ADDED,
138 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700139 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Arman Uguray24b4f382015-03-23 15:57:12 -0700140 MGMT_EV_ADVERTISING_ADDED,
141 MGMT_EV_ADVERTISING_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200142};
143
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700144static const u16 mgmt_untrusted_commands[] = {
145 MGMT_OP_READ_INDEX_LIST,
146 MGMT_OP_READ_INFO,
147 MGMT_OP_READ_UNCONF_INDEX_LIST,
148 MGMT_OP_READ_CONFIG_INFO,
149 MGMT_OP_READ_EXT_INDEX_LIST,
150};
151
152static const u16 mgmt_untrusted_events[] = {
153 MGMT_EV_INDEX_ADDED,
154 MGMT_EV_INDEX_REMOVED,
155 MGMT_EV_NEW_SETTINGS,
156 MGMT_EV_CLASS_OF_DEV_CHANGED,
157 MGMT_EV_LOCAL_NAME_CHANGED,
158 MGMT_EV_UNCONF_INDEX_ADDED,
159 MGMT_EV_UNCONF_INDEX_REMOVED,
160 MGMT_EV_NEW_CONFIG_OPTIONS,
161 MGMT_EV_EXT_INDEX_ADDED,
162 MGMT_EV_EXT_INDEX_REMOVED,
163};
164
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800165#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200166
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200167#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
168 "\x00\x00\x00\x00\x00\x00\x00\x00"
169
Johan Hedbergca69b792011-11-11 18:10:00 +0200170/* HCI to MGMT error code conversion table */
171static u8 mgmt_status_table[] = {
172 MGMT_STATUS_SUCCESS,
173 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
174 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
175 MGMT_STATUS_FAILED, /* Hardware Failure */
176 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
177 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200178 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200179 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
180 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
181 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
182 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
183 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
184 MGMT_STATUS_BUSY, /* Command Disallowed */
185 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
186 MGMT_STATUS_REJECTED, /* Rejected Security */
187 MGMT_STATUS_REJECTED, /* Rejected Personal */
188 MGMT_STATUS_TIMEOUT, /* Host Timeout */
189 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
190 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
191 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
192 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
193 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
194 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
195 MGMT_STATUS_BUSY, /* Repeated Attempts */
196 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
197 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
198 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
199 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
200 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
201 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
202 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
203 MGMT_STATUS_FAILED, /* Unspecified Error */
204 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
205 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
206 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
207 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
208 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
209 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
210 MGMT_STATUS_FAILED, /* Unit Link Key Used */
211 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
212 MGMT_STATUS_TIMEOUT, /* Instant Passed */
213 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
214 MGMT_STATUS_FAILED, /* Transaction Collision */
215 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
216 MGMT_STATUS_REJECTED, /* QoS Rejected */
217 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
218 MGMT_STATUS_REJECTED, /* Insufficient Security */
219 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
220 MGMT_STATUS_BUSY, /* Role Switch Pending */
221 MGMT_STATUS_FAILED, /* Slot Violation */
222 MGMT_STATUS_FAILED, /* Role Switch Failed */
223 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
224 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
225 MGMT_STATUS_BUSY, /* Host Busy Pairing */
226 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
227 MGMT_STATUS_BUSY, /* Controller Busy */
228 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
229 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
230 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
231 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
232 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
233};
234
235static u8 mgmt_status(u8 hci_status)
236{
237 if (hci_status < ARRAY_SIZE(mgmt_status_table))
238 return mgmt_status_table[hci_status];
239
240 return MGMT_STATUS_FAILED;
241}
242
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700243static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
244 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700245{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700246 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
247 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700248}
249
Marcel Holtmann72000df2015-03-16 16:11:21 -0700250static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
251 u16 len, int flag, struct sock *skip_sk)
252{
253 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
254 flag, skip_sk);
255}
256
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700257static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
258 u16 len, struct sock *skip_sk)
259{
260 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
261 HCI_MGMT_GENERIC_EVENTS, skip_sk);
262}
263
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200264static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
265 struct sock *skip_sk)
266{
267 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700268 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200269}
270
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300271static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
272 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200273{
274 struct mgmt_rp_read_version rp;
275
276 BT_DBG("sock %p", sk);
277
278 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700279 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200280
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200281 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
282 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200283}
284
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300285static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
286 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200287{
288 struct mgmt_rp_read_commands *rp;
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700289 u16 num_commands, num_events;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200290 size_t rp_size;
291 int i, err;
292
293 BT_DBG("sock %p", sk);
294
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700295 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
296 num_commands = ARRAY_SIZE(mgmt_commands);
297 num_events = ARRAY_SIZE(mgmt_events);
298 } else {
299 num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
300 num_events = ARRAY_SIZE(mgmt_untrusted_events);
301 }
302
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200303 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
304
305 rp = kmalloc(rp_size, GFP_KERNEL);
306 if (!rp)
307 return -ENOMEM;
308
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700309 rp->num_commands = cpu_to_le16(num_commands);
310 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700312 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
313 __le16 *opcode = rp->opcodes;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200314
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700315 for (i = 0; i < num_commands; i++, opcode++)
316 put_unaligned_le16(mgmt_commands[i], opcode);
317
318 for (i = 0; i < num_events; i++, opcode++)
319 put_unaligned_le16(mgmt_events[i], opcode);
320 } else {
321 __le16 *opcode = rp->opcodes;
322
323 for (i = 0; i < num_commands; i++, opcode++)
324 put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
325
326 for (i = 0; i < num_events; i++, opcode++)
327 put_unaligned_le16(mgmt_untrusted_events[i], opcode);
328 }
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200329
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200330 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
331 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 kfree(rp);
333
334 return err;
335}
336
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300337static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
338 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200341 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200342 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200343 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300344 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345
346 BT_DBG("sock %p", sk);
347
348 read_lock(&hci_dev_list_lock);
349
350 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300351 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200352 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700353 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700354 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200355 }
356
Johan Hedberga38528f2011-01-22 06:46:43 +0200357 rp_len = sizeof(*rp) + (2 * count);
358 rp = kmalloc(rp_len, GFP_ATOMIC);
359 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100360 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100362 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363
Johan Hedberg476e44c2012-10-19 20:10:46 +0300364 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200365 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700366 if (hci_dev_test_flag(d, HCI_SETUP) ||
367 hci_dev_test_flag(d, HCI_CONFIG) ||
368 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200369 continue;
370
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200371 /* Devices marked as raw-only are neither configured
372 * nor unconfigured controllers.
373 */
374 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700375 continue;
376
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200377 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700378 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700379 rp->index[count++] = cpu_to_le16(d->id);
380 BT_DBG("Added hci%u", d->id);
381 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 }
383
Johan Hedberg476e44c2012-10-19 20:10:46 +0300384 rp->num_controllers = cpu_to_le16(count);
385 rp_len = sizeof(*rp) + (2 * count);
386
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200387 read_unlock(&hci_dev_list_lock);
388
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200389 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
390 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200391
Johan Hedberga38528f2011-01-22 06:46:43 +0200392 kfree(rp);
393
394 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200395}
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
398 void *data, u16 data_len)
399{
400 struct mgmt_rp_read_unconf_index_list *rp;
401 struct hci_dev *d;
402 size_t rp_len;
403 u16 count;
404 int err;
405
406 BT_DBG("sock %p", sk);
407
408 read_lock(&hci_dev_list_lock);
409
410 count = 0;
411 list_for_each_entry(d, &hci_dev_list, list) {
412 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700413 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200414 count++;
415 }
416
417 rp_len = sizeof(*rp) + (2 * count);
418 rp = kmalloc(rp_len, GFP_ATOMIC);
419 if (!rp) {
420 read_unlock(&hci_dev_list_lock);
421 return -ENOMEM;
422 }
423
424 count = 0;
425 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700426 if (hci_dev_test_flag(d, HCI_SETUP) ||
427 hci_dev_test_flag(d, HCI_CONFIG) ||
428 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200429 continue;
430
431 /* Devices marked as raw-only are neither configured
432 * nor unconfigured controllers.
433 */
434 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
435 continue;
436
437 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700438 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200439 rp->index[count++] = cpu_to_le16(d->id);
440 BT_DBG("Added hci%u", d->id);
441 }
442 }
443
444 rp->num_controllers = cpu_to_le16(count);
445 rp_len = sizeof(*rp) + (2 * count);
446
447 read_unlock(&hci_dev_list_lock);
448
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200449 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
450 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200451
452 kfree(rp);
453
454 return err;
455}
456
Marcel Holtmann96f14742015-03-14 19:27:57 -0700457static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
458 void *data, u16 data_len)
459{
460 struct mgmt_rp_read_ext_index_list *rp;
461 struct hci_dev *d;
462 size_t rp_len;
463 u16 count;
464 int err;
465
466 BT_DBG("sock %p", sk);
467
468 read_lock(&hci_dev_list_lock);
469
470 count = 0;
471 list_for_each_entry(d, &hci_dev_list, list) {
472 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
473 count++;
474 }
475
476 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
477 rp = kmalloc(rp_len, GFP_ATOMIC);
478 if (!rp) {
479 read_unlock(&hci_dev_list_lock);
480 return -ENOMEM;
481 }
482
483 count = 0;
484 list_for_each_entry(d, &hci_dev_list, list) {
485 if (hci_dev_test_flag(d, HCI_SETUP) ||
486 hci_dev_test_flag(d, HCI_CONFIG) ||
487 hci_dev_test_flag(d, HCI_USER_CHANNEL))
488 continue;
489
490 /* Devices marked as raw-only are neither configured
491 * nor unconfigured controllers.
492 */
493 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
494 continue;
495
496 if (d->dev_type == HCI_BREDR) {
497 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
498 rp->entry[count].type = 0x01;
499 else
500 rp->entry[count].type = 0x00;
501 } else if (d->dev_type == HCI_AMP) {
502 rp->entry[count].type = 0x02;
503 } else {
504 continue;
505 }
506
507 rp->entry[count].bus = d->bus;
508 rp->entry[count++].index = cpu_to_le16(d->id);
509 BT_DBG("Added hci%u", d->id);
510 }
511
512 rp->num_controllers = cpu_to_le16(count);
513 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
514
515 read_unlock(&hci_dev_list_lock);
516
517 /* If this command is called at least once, then all the
518 * default index and unconfigured index events are disabled
519 * and from now on only extended index events are used.
520 */
521 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
522 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
523 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
524
525 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
526 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
527
528 kfree(rp);
529
530 return err;
531}
532
Marcel Holtmanndbece372014-07-04 18:11:55 +0200533static bool is_configured(struct hci_dev *hdev)
534{
535 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700536 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200537 return false;
538
539 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
540 !bacmp(&hdev->public_addr, BDADDR_ANY))
541 return false;
542
543 return true;
544}
545
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200546static __le32 get_missing_options(struct hci_dev *hdev)
547{
548 u32 options = 0;
549
Marcel Holtmanndbece372014-07-04 18:11:55 +0200550 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700551 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200552 options |= MGMT_OPTION_EXTERNAL_CONFIG;
553
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200554 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
555 !bacmp(&hdev->public_addr, BDADDR_ANY))
556 options |= MGMT_OPTION_PUBLIC_ADDRESS;
557
558 return cpu_to_le32(options);
559}
560
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200561static int new_options(struct hci_dev *hdev, struct sock *skip)
562{
563 __le32 options = get_missing_options(hdev);
564
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700565 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
566 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200567}
568
Marcel Holtmanndbece372014-07-04 18:11:55 +0200569static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
570{
571 __le32 options = get_missing_options(hdev);
572
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200573 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
574 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200575}
576
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200577static int read_config_info(struct sock *sk, struct hci_dev *hdev,
578 void *data, u16 data_len)
579{
580 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200581 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200582
583 BT_DBG("sock %p %s", sk, hdev->name);
584
585 hci_dev_lock(hdev);
586
587 memset(&rp, 0, sizeof(rp));
588 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200589
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200590 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
591 options |= MGMT_OPTION_EXTERNAL_CONFIG;
592
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200593 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200594 options |= MGMT_OPTION_PUBLIC_ADDRESS;
595
596 rp.supported_options = cpu_to_le32(options);
597 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200598
599 hci_dev_unlock(hdev);
600
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200601 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
602 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200603}
604
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200606{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200608
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300610 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800611 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300612 settings |= MGMT_SETTING_CONNECTABLE;
613 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200614
Andre Guedesed3fa312012-07-24 15:03:46 -0300615 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500616 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
617 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_BREDR;
619 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700620
621 if (lmp_ssp_capable(hdev)) {
622 settings |= MGMT_SETTING_SSP;
623 settings |= MGMT_SETTING_HS;
624 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800625
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800626 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700628 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100629
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300630 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200631 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300632 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300633 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800635 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300636 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200637
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200638 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
639 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200640 settings |= MGMT_SETTING_CONFIGURATION;
641
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200642 return settings;
643}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200644
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200645static u32 get_current_settings(struct hci_dev *hdev)
646{
647 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200648
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200649 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100650 settings |= MGMT_SETTING_POWERED;
651
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700652 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200653 settings |= MGMT_SETTING_CONNECTABLE;
654
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700655 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500656 settings |= MGMT_SETTING_FAST_CONNECTABLE;
657
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700658 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200659 settings |= MGMT_SETTING_DISCOVERABLE;
660
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700661 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300662 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200663
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700664 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200665 settings |= MGMT_SETTING_BREDR;
666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700667 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200668 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700670 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200672
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700673 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200674 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200675
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700676 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200677 settings |= MGMT_SETTING_HS;
678
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700679 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300680 settings |= MGMT_SETTING_ADVERTISING;
681
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700682 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800683 settings |= MGMT_SETTING_SECURE_CONN;
684
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700685 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800686 settings |= MGMT_SETTING_DEBUG_KEYS;
687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700688 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200689 settings |= MGMT_SETTING_PRIVACY;
690
Marcel Holtmann93690c22015-03-06 10:11:21 -0800691 /* The current setting for static address has two purposes. The
692 * first is to indicate if the static address will be used and
693 * the second is to indicate if it is actually set.
694 *
695 * This means if the static address is not configured, this flag
Marcel Holtmann08dc0e92015-03-25 18:32:13 -0700696 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800697 * address is actually used decides if the flag is set or not.
698 *
699 * For single mode LE only controllers and dual-mode controllers
700 * with BR/EDR disabled, the existence of the static address will
701 * be evaluated.
702 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700703 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700704 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
706 if (bacmp(&hdev->static_addr, BDADDR_ANY))
707 settings |= MGMT_SETTING_STATIC_ADDRESS;
708 }
709
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200710 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200711}
712
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300713#define PNP_INFO_SVCLASS_ID 0x1200
714
Johan Hedberg213202e2013-01-27 00:31:33 +0200715static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 4)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 u16 uuid16;
725
726 if (uuid->size != 16)
727 continue;
728
729 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
730 if (uuid16 < 0x1100)
731 continue;
732
733 if (uuid16 == PNP_INFO_SVCLASS_ID)
734 continue;
735
736 if (!uuids_start) {
737 uuids_start = ptr;
738 uuids_start[0] = 1;
739 uuids_start[1] = EIR_UUID16_ALL;
740 ptr += 2;
741 }
742
743 /* Stop if not enough space to put next UUID */
744 if ((ptr - data) + sizeof(u16) > len) {
745 uuids_start[1] = EIR_UUID16_SOME;
746 break;
747 }
748
749 *ptr++ = (uuid16 & 0x00ff);
750 *ptr++ = (uuid16 & 0xff00) >> 8;
751 uuids_start[0] += sizeof(uuid16);
752 }
753
754 return ptr;
755}
756
Johan Hedbergcdf19632013-01-27 00:31:34 +0200757static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
758{
759 u8 *ptr = data, *uuids_start = NULL;
760 struct bt_uuid *uuid;
761
762 if (len < 6)
763 return ptr;
764
765 list_for_each_entry(uuid, &hdev->uuids, list) {
766 if (uuid->size != 32)
767 continue;
768
769 if (!uuids_start) {
770 uuids_start = ptr;
771 uuids_start[0] = 1;
772 uuids_start[1] = EIR_UUID32_ALL;
773 ptr += 2;
774 }
775
776 /* Stop if not enough space to put next UUID */
777 if ((ptr - data) + sizeof(u32) > len) {
778 uuids_start[1] = EIR_UUID32_SOME;
779 break;
780 }
781
782 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
783 ptr += sizeof(u32);
784 uuids_start[0] += sizeof(u32);
785 }
786
787 return ptr;
788}
789
Johan Hedbergc00d5752013-01-27 00:31:35 +0200790static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
791{
792 u8 *ptr = data, *uuids_start = NULL;
793 struct bt_uuid *uuid;
794
795 if (len < 18)
796 return ptr;
797
798 list_for_each_entry(uuid, &hdev->uuids, list) {
799 if (uuid->size != 128)
800 continue;
801
802 if (!uuids_start) {
803 uuids_start = ptr;
804 uuids_start[0] = 1;
805 uuids_start[1] = EIR_UUID128_ALL;
806 ptr += 2;
807 }
808
809 /* Stop if not enough space to put next UUID */
810 if ((ptr - data) + 16 > len) {
811 uuids_start[1] = EIR_UUID128_SOME;
812 break;
813 }
814
815 memcpy(ptr, uuid->uuid, 16);
816 ptr += 16;
817 uuids_start[0] += 16;
818 }
819
820 return ptr;
821}
822
Johan Hedberg333ae952015-03-17 13:48:47 +0200823static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
824{
825 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
826}
827
Johan Hedberg333ae952015-03-17 13:48:47 +0200828static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
829 struct hci_dev *hdev,
830 const void *data)
831{
832 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
833}
834
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200835static u8 get_current_adv_instance(struct hci_dev *hdev)
836{
837 /* The "Set Advertising" setting supersedes the "Add Advertising"
838 * setting. Here we set the advertising data based on which
839 * setting was set. When neither apply, default to the global settings,
840 * represented by instance "0".
841 */
842 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
843 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Florian Grandel3ff37e62015-06-18 03:16:39 +0200844 return hdev->cur_adv_instance;
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200845
846 return 0x00;
847}
848
Arman Uguray4117ed72015-03-23 15:57:14 -0700849static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700850{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700851 u8 ad_len = 0;
852 size_t name_len;
853
854 name_len = strlen(hdev->dev_name);
855 if (name_len > 0) {
856 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
857
858 if (name_len > max_len) {
859 name_len = max_len;
860 ptr[1] = EIR_NAME_SHORT;
861 } else
862 ptr[1] = EIR_NAME_COMPLETE;
863
864 ptr[0] = name_len + 1;
865
866 memcpy(ptr + 2, hdev->dev_name, name_len);
867
868 ad_len += (name_len + 2);
869 ptr += (name_len + 2);
870 }
871
872 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700873}
874
Arman Uguray4117ed72015-03-23 15:57:14 -0700875static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
876{
877 /* TODO: Set the appropriate entries based on advertising instance flags
878 * here once flags other than 0 are supported.
879 */
880 memcpy(ptr, hdev->adv_instance.scan_rsp_data,
881 hdev->adv_instance.scan_rsp_len);
882
883 return hdev->adv_instance.scan_rsp_len;
884}
885
Florian Grandelefae0022015-06-18 03:16:37 +0200886static void update_inst_scan_rsp_data(struct hci_request *req, u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700887{
888 struct hci_dev *hdev = req->hdev;
889 struct hci_cp_le_set_scan_rsp_data cp;
890 u8 len;
891
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700892 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700893 return;
894
895 memset(&cp, 0, sizeof(cp));
896
Arman Uguray4117ed72015-03-23 15:57:14 -0700897 if (instance)
898 len = create_instance_scan_rsp_data(hdev, cp.data);
899 else
900 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700901
Johan Hedbergeb438b52013-10-16 15:31:07 +0300902 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700903 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700904 return;
905
Johan Hedbergeb438b52013-10-16 15:31:07 +0300906 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
907 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700908
909 cp.length = len;
910
911 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
912}
913
Arman Uguray4117ed72015-03-23 15:57:14 -0700914static void update_scan_rsp_data(struct hci_request *req)
915{
Florian Grandelefae0022015-06-18 03:16:37 +0200916 update_inst_scan_rsp_data(req, get_current_adv_instance(req->hdev));
Arman Uguray4117ed72015-03-23 15:57:14 -0700917}
918
Johan Hedberg9a43e252013-10-20 19:00:07 +0300919static u8 get_adv_discov_flags(struct hci_dev *hdev)
920{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200921 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300922
923 /* If there's a pending mgmt command the flags will not yet have
924 * their final values, so check for this first.
925 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200926 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300927 if (cmd) {
928 struct mgmt_mode *cp = cmd->param;
929 if (cp->val == 0x01)
930 return LE_AD_GENERAL;
931 else if (cp->val == 0x02)
932 return LE_AD_LIMITED;
933 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700934 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300935 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700936 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300937 return LE_AD_GENERAL;
938 }
939
940 return 0;
941}
942
Arman Uguraye7a685d2015-03-25 18:53:40 -0700943static bool get_connectable(struct hci_dev *hdev)
944{
945 struct mgmt_pending_cmd *cmd;
946
947 /* If there's a pending mgmt command the flag will not yet have
948 * it's final value, so check for this first.
949 */
950 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
951 if (cmd) {
952 struct mgmt_mode *cp = cmd->param;
953
954 return cp->val;
955 }
956
957 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
958}
959
960static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
961{
962 u32 flags;
Florian Grandel411b4122015-06-18 03:16:40 +0200963 struct adv_info *adv_instance;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700964
Florian Grandel411b4122015-06-18 03:16:40 +0200965 if (instance != 0x00) {
966 adv_instance = hci_find_adv_instance(hdev, instance);
Arman Uguraye7a685d2015-03-25 18:53:40 -0700967
Florian Grandel411b4122015-06-18 03:16:40 +0200968 /* Return 0 when we got an invalid instance identifier. */
969 if (!adv_instance)
970 return 0;
971
972 return adv_instance->flags;
973 }
Arman Uguraye7a685d2015-03-25 18:53:40 -0700974
Arman Ugurayfdf51782015-03-25 18:53:46 -0700975 /* Instance 0 always manages the "Tx Power" and "Flags" fields */
976 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700977
Arman Ugurayfaccb952015-03-28 12:38:58 -0700978 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting corresponds
979 * to the "connectable" instance flag.
980 */
981 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700982 flags |= MGMT_ADV_FLAG_CONNECTABLE;
983
Arman Uguraye7a685d2015-03-25 18:53:40 -0700984 return flags;
985}
986
Arman Ugurayc7d48832015-03-28 12:38:59 -0700987static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
988{
989 /* Ignore instance 0 and other unsupported instances */
990 if (instance != 0x01)
991 return 0;
992
993 /* TODO: Take into account the "appearance" and "local-name" flags here.
994 * These are currently being ignored as they are not supported.
995 */
996 return hdev->adv_instance.scan_rsp_len;
997}
998
Arman Ugurayfdf51782015-03-25 18:53:46 -0700999static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1000{
1001 u8 ad_len = 0, flags = 0;
1002 u32 instance_flags = get_adv_instance_flags(hdev, instance);
1003
1004 /* The Add Advertising command allows userspace to set both the general
1005 * and limited discoverable flags.
1006 */
1007 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1008 flags |= LE_AD_GENERAL;
1009
1010 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1011 flags |= LE_AD_LIMITED;
1012
1013 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1014 /* If a discovery flag wasn't provided, simply use the global
1015 * settings.
1016 */
1017 if (!flags)
1018 flags |= get_adv_discov_flags(hdev);
1019
1020 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1021 flags |= LE_AD_NO_BREDR;
1022
1023 /* If flags would still be empty, then there is no need to
1024 * include the "Flags" AD field".
1025 */
1026 if (flags) {
1027 ptr[0] = 0x02;
1028 ptr[1] = EIR_FLAGS;
1029 ptr[2] = flags;
1030
1031 ad_len += 3;
1032 ptr += 3;
1033 }
1034 }
1035
Marcel Holtmann38c8af62015-04-03 13:23:12 -07001036 if (instance) {
1037 memcpy(ptr, hdev->adv_instance.adv_data,
1038 hdev->adv_instance.adv_data_len);
1039
1040 ad_len += hdev->adv_instance.adv_data_len;
1041 ptr += hdev->adv_instance.adv_data_len;
1042 }
1043
Arman Ugurayfdf51782015-03-25 18:53:46 -07001044 /* Provide Tx Power only if we can provide a valid value for it */
1045 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1046 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1047 ptr[0] = 0x02;
1048 ptr[1] = EIR_TX_POWER;
1049 ptr[2] = (u8)hdev->adv_tx_power;
1050
1051 ad_len += 3;
1052 ptr += 3;
1053 }
1054
Arman Ugurayfdf51782015-03-25 18:53:46 -07001055 return ad_len;
1056}
1057
Florian Grandelefae0022015-06-18 03:16:37 +02001058static void update_inst_adv_data(struct hci_request *req, u8 instance)
Arman Ugurayfdf51782015-03-25 18:53:46 -07001059{
1060 struct hci_dev *hdev = req->hdev;
1061 struct hci_cp_le_set_adv_data cp;
1062 u8 len;
1063
1064 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1065 return;
1066
1067 memset(&cp, 0, sizeof(cp));
1068
1069 len = create_instance_adv_data(hdev, instance, cp.data);
1070
1071 /* There's nothing to do if the data hasn't changed */
1072 if (hdev->adv_data_len == len &&
1073 memcmp(cp.data, hdev->adv_data, len) == 0)
1074 return;
1075
1076 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1077 hdev->adv_data_len = len;
1078
1079 cp.length = len;
1080
1081 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1082}
1083
Arman Uguraye7a685d2015-03-25 18:53:40 -07001084static void update_adv_data(struct hci_request *req)
1085{
Florian Grandelefae0022015-06-18 03:16:37 +02001086 update_inst_adv_data(req, get_current_adv_instance(req->hdev));
Arman Uguray24b4f382015-03-23 15:57:12 -07001087}
1088
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001089int mgmt_update_adv_data(struct hci_dev *hdev)
1090{
1091 struct hci_request req;
1092
1093 hci_req_init(&req, hdev);
1094 update_adv_data(&req);
1095
1096 return hci_req_run(&req, NULL);
1097}
1098
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001099static void create_eir(struct hci_dev *hdev, u8 *data)
1100{
1101 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001102 size_t name_len;
1103
1104 name_len = strlen(hdev->dev_name);
1105
1106 if (name_len > 0) {
1107 /* EIR Data type */
1108 if (name_len > 48) {
1109 name_len = 48;
1110 ptr[1] = EIR_NAME_SHORT;
1111 } else
1112 ptr[1] = EIR_NAME_COMPLETE;
1113
1114 /* EIR Data length */
1115 ptr[0] = name_len + 1;
1116
1117 memcpy(ptr + 2, hdev->dev_name, name_len);
1118
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001119 ptr += (name_len + 2);
1120 }
1121
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001122 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001123 ptr[0] = 2;
1124 ptr[1] = EIR_TX_POWER;
1125 ptr[2] = (u8) hdev->inq_tx_power;
1126
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001127 ptr += 3;
1128 }
1129
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001130 if (hdev->devid_source > 0) {
1131 ptr[0] = 9;
1132 ptr[1] = EIR_DEVICE_ID;
1133
1134 put_unaligned_le16(hdev->devid_source, ptr + 2);
1135 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1136 put_unaligned_le16(hdev->devid_product, ptr + 6);
1137 put_unaligned_le16(hdev->devid_version, ptr + 8);
1138
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001139 ptr += 10;
1140 }
1141
Johan Hedberg213202e2013-01-27 00:31:33 +02001142 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001143 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001144 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001145}
1146
Johan Hedberg890ea892013-03-15 17:06:52 -05001147static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001148{
Johan Hedberg890ea892013-03-15 17:06:52 -05001149 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001150 struct hci_cp_write_eir cp;
1151
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001152 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001153 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001154
Johan Hedberg976eb202012-10-24 21:12:01 +03001155 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001156 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001157
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001158 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001159 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001160
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001161 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001162 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001163
1164 memset(&cp, 0, sizeof(cp));
1165
1166 create_eir(hdev, cp.data);
1167
1168 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001169 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001170
1171 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1172
Johan Hedberg890ea892013-03-15 17:06:52 -05001173 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001174}
1175
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001176static u8 get_service_classes(struct hci_dev *hdev)
1177{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001178 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001179 u8 val = 0;
1180
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001181 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001182 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001183
1184 return val;
1185}
1186
Johan Hedberg890ea892013-03-15 17:06:52 -05001187static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001188{
Johan Hedberg890ea892013-03-15 17:06:52 -05001189 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001190 u8 cod[3];
1191
1192 BT_DBG("%s", hdev->name);
1193
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001194 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001195 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001196
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001197 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001198 return;
1199
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001200 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001201 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001202
1203 cod[0] = hdev->minor_class;
1204 cod[1] = hdev->major_class;
1205 cod[2] = get_service_classes(hdev);
1206
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001207 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001208 cod[1] |= 0x20;
1209
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001210 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001211 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001212
Johan Hedberg890ea892013-03-15 17:06:52 -05001213 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001214}
1215
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001216static void disable_advertising(struct hci_request *req)
1217{
1218 u8 enable = 0x00;
1219
1220 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1221}
1222
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001223static void enable_advertising(struct hci_request *req)
1224{
1225 struct hci_dev *hdev = req->hdev;
1226 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001227 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001228 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001229 u8 instance;
1230 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001231
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001232 if (hci_conn_num(hdev, LE_LINK) > 0)
1233 return;
1234
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001235 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001236 disable_advertising(req);
1237
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001238 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001239 * hci_update_random_address knows that it's safe to go ahead
1240 * and write a new random address. The flag will be set back on
1241 * as soon as the SET_ADV_ENABLE HCI command completes.
1242 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001243 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001244
Arman Uguraye7a685d2015-03-25 18:53:40 -07001245 instance = get_current_adv_instance(hdev);
1246 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001247
1248 /* If the "connectable" instance flag was not set, then choose between
1249 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1250 */
1251 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1252 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001253
Johan Hedberga4858cb2014-02-25 19:56:31 +02001254 /* Set require_privacy to true only when non-connectable
1255 * advertising is used. In that case it is fine to use a
1256 * non-resolvable private address.
1257 */
1258 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001259 return;
1260
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001261 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001262 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1263 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001264
1265 if (connectable)
1266 cp.type = LE_ADV_IND;
1267 else if (get_adv_instance_scan_rsp_len(hdev, instance))
1268 cp.type = LE_ADV_SCAN_IND;
1269 else
1270 cp.type = LE_ADV_NONCONN_IND;
1271
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001272 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001273 cp.channel_map = hdev->le_adv_channel_map;
1274
1275 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1276
1277 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1278}
1279
Johan Hedberg7d785252011-12-15 00:47:39 +02001280static void service_cache_off(struct work_struct *work)
1281{
1282 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001283 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001284 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001285
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001286 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001287 return;
1288
Johan Hedberg890ea892013-03-15 17:06:52 -05001289 hci_req_init(&req, hdev);
1290
Johan Hedberg7d785252011-12-15 00:47:39 +02001291 hci_dev_lock(hdev);
1292
Johan Hedberg890ea892013-03-15 17:06:52 -05001293 update_eir(&req);
1294 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001295
1296 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001297
1298 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001299}
1300
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001301static void rpa_expired(struct work_struct *work)
1302{
1303 struct hci_dev *hdev = container_of(work, struct hci_dev,
1304 rpa_expired.work);
1305 struct hci_request req;
1306
1307 BT_DBG("");
1308
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001309 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001310
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001311 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001312 return;
1313
1314 /* The generation of a new RPA and programming it into the
1315 * controller happens in the enable_advertising() function.
1316 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001317 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001318 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001319 hci_req_run(&req, NULL);
1320}
1321
Johan Hedberg6a919082012-02-28 06:17:26 +02001322static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001323{
Marcel Holtmann238be782015-03-13 02:11:06 -07001324 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001325 return;
1326
Johan Hedberg4f87da82012-03-02 19:55:56 +02001327 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001328 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001329
Johan Hedberg4f87da82012-03-02 19:55:56 +02001330 /* Non-mgmt controlled devices get this bit set
1331 * implicitly so that pairing works for them, however
1332 * for mgmt we require user-space to explicitly enable
1333 * it
1334 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001335 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001336}
1337
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001338static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001339 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001340{
1341 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001342
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001343 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001344
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001345 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001346
Johan Hedberg03811012010-12-08 00:21:06 +02001347 memset(&rp, 0, sizeof(rp));
1348
Johan Hedberg03811012010-12-08 00:21:06 +02001349 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001350
1351 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001352 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001353
1354 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1355 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1356
1357 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001358
1359 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001360 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001361
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001362 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001363
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001364 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1365 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001366}
1367
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001368static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001369{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001370 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001371
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001372 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1373 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001374}
1375
Marcel Holtmann1904a852015-01-11 13:50:44 -08001376static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001377{
1378 BT_DBG("%s status 0x%02x", hdev->name, status);
1379
Johan Hedberga3172b72014-02-28 09:33:44 +02001380 if (hci_conn_count(hdev) == 0) {
1381 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001382 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001383 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001384}
1385
Johan Hedberg23a48092014-07-08 16:05:06 +03001386static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001387{
1388 struct hci_dev *hdev = req->hdev;
1389 struct hci_cp_remote_name_req_cancel cp;
1390 struct inquiry_entry *e;
1391
1392 switch (hdev->discovery.state) {
1393 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001394 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001395 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001396
1397 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001398 cancel_delayed_work(&hdev->le_scan_disable);
1399 hci_req_add_le_scan_disable(req);
1400 }
1401
Johan Hedberg23a48092014-07-08 16:05:06 +03001402 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001403
1404 case DISCOVERY_RESOLVING:
1405 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1406 NAME_PENDING);
1407 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001408 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001409
1410 bacpy(&cp.bdaddr, &e->data.bdaddr);
1411 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1412 &cp);
1413
Johan Hedberg23a48092014-07-08 16:05:06 +03001414 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001415
1416 default:
1417 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001418 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001419 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001420 return true;
1421 }
1422
Johan Hedberg21a60d32014-06-10 14:05:58 +03001423 break;
1424 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001425
1426 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001427}
1428
Arman Uguray912098a2015-03-23 15:57:15 -07001429static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1430 u8 instance)
1431{
1432 struct mgmt_ev_advertising_added ev;
1433
1434 ev.instance = instance;
1435
1436 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1437}
1438
1439static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1440 u8 instance)
1441{
1442 struct mgmt_ev_advertising_removed ev;
1443
1444 ev.instance = instance;
1445
1446 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1447}
1448
1449static void clear_adv_instance(struct hci_dev *hdev)
1450{
1451 struct hci_request req;
1452
1453 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1454 return;
1455
Florian Grandel5d900e42015-06-18 03:16:35 +02001456 if (hdev->adv_instance_timeout)
1457 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07001458
1459 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1460 advertising_removed(NULL, hdev, 1);
1461 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1462
1463 if (!hdev_is_powered(hdev) ||
1464 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1465 return;
1466
1467 hci_req_init(&req, hdev);
1468 disable_advertising(&req);
1469 hci_req_run(&req, NULL);
1470}
1471
Johan Hedberg8b064a32014-02-24 14:52:22 +02001472static int clean_up_hci_state(struct hci_dev *hdev)
1473{
1474 struct hci_request req;
1475 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001476 bool discov_stopped;
1477 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001478
1479 hci_req_init(&req, hdev);
1480
1481 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1482 test_bit(HCI_PSCAN, &hdev->flags)) {
1483 u8 scan = 0x00;
1484 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1485 }
1486
Florian Grandel5d900e42015-06-18 03:16:35 +02001487 if (hdev->adv_instance_timeout)
Arman Uguray912098a2015-03-23 15:57:15 -07001488 clear_adv_instance(hdev);
1489
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001490 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001491 disable_advertising(&req);
1492
Johan Hedberg23a48092014-07-08 16:05:06 +03001493 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001494
1495 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1496 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001497 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001498
Johan Hedbergc9910d02014-02-27 14:35:12 +02001499 switch (conn->state) {
1500 case BT_CONNECTED:
1501 case BT_CONFIG:
1502 dc.handle = cpu_to_le16(conn->handle);
1503 dc.reason = 0x15; /* Terminated due to Power Off */
1504 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1505 break;
1506 case BT_CONNECT:
1507 if (conn->type == LE_LINK)
1508 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1509 0, NULL);
1510 else if (conn->type == ACL_LINK)
1511 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1512 6, &conn->dst);
1513 break;
1514 case BT_CONNECT2:
1515 bacpy(&rej.bdaddr, &conn->dst);
1516 rej.reason = 0x15; /* Terminated due to Power Off */
1517 if (conn->type == ACL_LINK)
1518 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1519 sizeof(rej), &rej);
1520 else if (conn->type == SCO_LINK)
1521 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1522 sizeof(rej), &rej);
1523 break;
1524 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001525 }
1526
Johan Hedberg23a48092014-07-08 16:05:06 +03001527 err = hci_req_run(&req, clean_up_hci_complete);
1528 if (!err && discov_stopped)
1529 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1530
1531 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001532}
1533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001534static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001535 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001536{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001537 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001538 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001539 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001540
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001541 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001542
Johan Hedberga7e80f22013-01-09 16:05:19 +02001543 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001544 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1545 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001546
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001547 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001548
Johan Hedberg333ae952015-03-17 13:48:47 +02001549 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001550 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1551 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001552 goto failed;
1553 }
1554
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001555 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001556 cancel_delayed_work(&hdev->power_off);
1557
1558 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001559 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1560 data, len);
1561 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001562 goto failed;
1563 }
1564 }
1565
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001566 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001567 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001568 goto failed;
1569 }
1570
Johan Hedberg03811012010-12-08 00:21:06 +02001571 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1572 if (!cmd) {
1573 err = -ENOMEM;
1574 goto failed;
1575 }
1576
Johan Hedberg8b064a32014-02-24 14:52:22 +02001577 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001578 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001579 err = 0;
1580 } else {
1581 /* Disconnect connections, stop scans, etc */
1582 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001583 if (!err)
1584 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1585 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001586
Johan Hedberg8b064a32014-02-24 14:52:22 +02001587 /* ENODATA means there were no HCI commands queued */
1588 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001589 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1591 err = 0;
1592 }
1593 }
Johan Hedberg03811012010-12-08 00:21:06 +02001594
1595failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001596 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001597 return err;
1598}
1599
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001600static int new_settings(struct hci_dev *hdev, struct sock *skip)
1601{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001602 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001603
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001604 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1605 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001606}
1607
Johan Hedberg91a668b2014-07-09 13:28:26 +03001608int mgmt_new_settings(struct hci_dev *hdev)
1609{
1610 return new_settings(hdev, NULL);
1611}
1612
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001613struct cmd_lookup {
1614 struct sock *sk;
1615 struct hci_dev *hdev;
1616 u8 mgmt_status;
1617};
1618
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001619static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001620{
1621 struct cmd_lookup *match = data;
1622
1623 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1624
1625 list_del(&cmd->list);
1626
1627 if (match->sk == NULL) {
1628 match->sk = cmd->sk;
1629 sock_hold(match->sk);
1630 }
1631
1632 mgmt_pending_free(cmd);
1633}
1634
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001635static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001636{
1637 u8 *status = data;
1638
Johan Hedberga69e8372015-03-06 21:08:53 +02001639 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001640 mgmt_pending_remove(cmd);
1641}
1642
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001643static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001644{
1645 if (cmd->cmd_complete) {
1646 u8 *status = data;
1647
1648 cmd->cmd_complete(cmd, *status);
1649 mgmt_pending_remove(cmd);
1650
1651 return;
1652 }
1653
1654 cmd_status_rsp(cmd, data);
1655}
1656
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001657static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001658{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001659 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1660 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001661}
1662
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001663static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001664{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001665 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1666 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001667}
1668
Johan Hedberge6fe7982013-10-02 15:45:22 +03001669static u8 mgmt_bredr_support(struct hci_dev *hdev)
1670{
1671 if (!lmp_bredr_capable(hdev))
1672 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001673 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001674 return MGMT_STATUS_REJECTED;
1675 else
1676 return MGMT_STATUS_SUCCESS;
1677}
1678
1679static u8 mgmt_le_support(struct hci_dev *hdev)
1680{
1681 if (!lmp_le_capable(hdev))
1682 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001683 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001684 return MGMT_STATUS_REJECTED;
1685 else
1686 return MGMT_STATUS_SUCCESS;
1687}
1688
Marcel Holtmann1904a852015-01-11 13:50:44 -08001689static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1690 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001691{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001692 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001694 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001695 bool changed;
1696
1697 BT_DBG("status 0x%02x", status);
1698
1699 hci_dev_lock(hdev);
1700
Johan Hedberg333ae952015-03-17 13:48:47 +02001701 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001702 if (!cmd)
1703 goto unlock;
1704
1705 if (status) {
1706 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001707 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001708 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001709 goto remove_cmd;
1710 }
1711
1712 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001713 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001714 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001715
1716 if (hdev->discov_timeout > 0) {
1717 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1718 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1719 to);
1720 }
1721 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001722 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001723 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001724
1725 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1726
1727 if (changed)
1728 new_settings(hdev, cmd->sk);
1729
Marcel Holtmann970ba522013-10-15 06:33:57 -07001730 /* When the discoverable mode gets changed, make sure
1731 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001732 * bit correctly set. Also update page scan based on whitelist
1733 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001734 */
1735 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001736 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001737 update_class(&req);
1738 hci_req_run(&req, NULL);
1739
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001740remove_cmd:
1741 mgmt_pending_remove(cmd);
1742
1743unlock:
1744 hci_dev_unlock(hdev);
1745}
1746
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001747static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001748 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001749{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001750 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001751 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001752 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001753 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001754 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001755 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001756
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001757 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001758
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001759 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1760 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001761 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1762 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001763
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001764 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001765 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1766 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001767
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001768 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001769
1770 /* Disabling discoverable requires that no timeout is set,
1771 * and enabling limited discoverable requires a timeout.
1772 */
1773 if ((cp->val == 0x00 && timeout > 0) ||
1774 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001775 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1776 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001777
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001778 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001779
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001780 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001781 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1782 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001783 goto failed;
1784 }
1785
Johan Hedberg333ae952015-03-17 13:48:47 +02001786 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1787 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001788 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1789 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001790 goto failed;
1791 }
1792
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001793 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001794 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1795 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001796 goto failed;
1797 }
1798
1799 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001800 bool changed = false;
1801
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001802 /* Setting limited discoverable when powered off is
1803 * not a valid operation since it requires a timeout
1804 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1805 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001806 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001807 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001808 changed = true;
1809 }
1810
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001811 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001812 if (err < 0)
1813 goto failed;
1814
1815 if (changed)
1816 err = new_settings(hdev, sk);
1817
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001818 goto failed;
1819 }
1820
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001821 /* If the current mode is the same, then just update the timeout
1822 * value with the new value. And if only the timeout gets updated,
1823 * then no need for any HCI transactions.
1824 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001825 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1826 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1827 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001828 cancel_delayed_work(&hdev->discov_off);
1829 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001830
Marcel Holtmann36261542013-10-15 08:28:51 -07001831 if (cp->val && hdev->discov_timeout > 0) {
1832 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001833 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001834 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001835 }
1836
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001837 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001838 goto failed;
1839 }
1840
1841 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1842 if (!cmd) {
1843 err = -ENOMEM;
1844 goto failed;
1845 }
1846
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001847 /* Cancel any potential discoverable timeout that might be
1848 * still active and store new timeout value. The arming of
1849 * the timeout happens in the complete handler.
1850 */
1851 cancel_delayed_work(&hdev->discov_off);
1852 hdev->discov_timeout = timeout;
1853
Johan Hedbergb456f872013-10-19 23:38:22 +03001854 /* Limited discoverable mode */
1855 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001856 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001857 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001858 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001859
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001860 hci_req_init(&req, hdev);
1861
Johan Hedberg9a43e252013-10-20 19:00:07 +03001862 /* The procedure for LE-only controllers is much simpler - just
1863 * update the advertising data.
1864 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001865 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001866 goto update_ad;
1867
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001868 scan = SCAN_PAGE;
1869
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001870 if (cp->val) {
1871 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001872
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001873 if (cp->val == 0x02) {
1874 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001875 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001876 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1877 hci_cp.iac_lap[1] = 0x8b;
1878 hci_cp.iac_lap[2] = 0x9e;
1879 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1880 hci_cp.iac_lap[4] = 0x8b;
1881 hci_cp.iac_lap[5] = 0x9e;
1882 } else {
1883 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001884 hci_cp.num_iac = 1;
1885 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1886 hci_cp.iac_lap[1] = 0x8b;
1887 hci_cp.iac_lap[2] = 0x9e;
1888 }
1889
1890 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1891 (hci_cp.num_iac * 3) + 1, &hci_cp);
1892
1893 scan |= SCAN_INQUIRY;
1894 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001895 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001896 }
1897
1898 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001899
Johan Hedberg9a43e252013-10-20 19:00:07 +03001900update_ad:
1901 update_adv_data(&req);
1902
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001903 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001904 if (err < 0)
1905 mgmt_pending_remove(cmd);
1906
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001907failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001908 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001909 return err;
1910}
1911
Johan Hedberg406d7802013-03-15 17:07:09 -05001912static void write_fast_connectable(struct hci_request *req, bool enable)
1913{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001914 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001915 struct hci_cp_write_page_scan_activity acp;
1916 u8 type;
1917
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001918 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001919 return;
1920
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001921 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1922 return;
1923
Johan Hedberg406d7802013-03-15 17:07:09 -05001924 if (enable) {
1925 type = PAGE_SCAN_TYPE_INTERLACED;
1926
1927 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001928 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001929 } else {
1930 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1931
1932 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001933 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001934 }
1935
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001936 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001937
Johan Hedbergbd98b992013-03-15 17:07:13 -05001938 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1939 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1940 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1941 sizeof(acp), &acp);
1942
1943 if (hdev->page_scan_type != type)
1944 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001945}
1946
Marcel Holtmann1904a852015-01-11 13:50:44 -08001947static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1948 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001949{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001950 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001951 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001952 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001953
1954 BT_DBG("status 0x%02x", status);
1955
1956 hci_dev_lock(hdev);
1957
Johan Hedberg333ae952015-03-17 13:48:47 +02001958 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001959 if (!cmd)
1960 goto unlock;
1961
Johan Hedberg37438c12013-10-14 16:20:05 +03001962 if (status) {
1963 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001964 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001965 goto remove_cmd;
1966 }
1967
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001968 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001969 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001970 conn_changed = !hci_dev_test_and_set_flag(hdev,
1971 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001972 discov_changed = false;
1973 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001974 conn_changed = hci_dev_test_and_clear_flag(hdev,
1975 HCI_CONNECTABLE);
1976 discov_changed = hci_dev_test_and_clear_flag(hdev,
1977 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001978 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001979
Johan Hedberg2b76f452013-03-15 17:07:04 -05001980 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1981
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001982 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001983 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001984 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001985 if (discov_changed)
1986 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001987 hci_update_background_scan(hdev);
1988 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001989
Johan Hedberg37438c12013-10-14 16:20:05 +03001990remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001991 mgmt_pending_remove(cmd);
1992
1993unlock:
1994 hci_dev_unlock(hdev);
1995}
1996
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001997static int set_connectable_update_settings(struct hci_dev *hdev,
1998 struct sock *sk, u8 val)
1999{
2000 bool changed = false;
2001 int err;
2002
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002003 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002004 changed = true;
2005
2006 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002007 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002008 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002009 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2010 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002011 }
2012
2013 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2014 if (err < 0)
2015 return err;
2016
Johan Hedberg562064e2014-07-08 16:35:34 +03002017 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002018 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002019 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002020 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002021 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002022
2023 return 0;
2024}
2025
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002026static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002027 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002028{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002029 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002030 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002031 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002032 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002033 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002034
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002035 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002036
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002037 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2038 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002039 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2040 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002041
Johan Hedberga7e80f22013-01-09 16:05:19 +02002042 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002043 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2044 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002045
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002046 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002047
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002048 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002049 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002050 goto failed;
2051 }
2052
Johan Hedberg333ae952015-03-17 13:48:47 +02002053 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2054 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002055 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2056 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002057 goto failed;
2058 }
2059
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002060 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2061 if (!cmd) {
2062 err = -ENOMEM;
2063 goto failed;
2064 }
2065
Johan Hedberg2b76f452013-03-15 17:07:04 -05002066 hci_req_init(&req, hdev);
2067
Johan Hedberg9a43e252013-10-20 19:00:07 +03002068 /* If BR/EDR is not enabled and we disable advertising as a
2069 * by-product of disabling connectable, we need to update the
2070 * advertising flags.
2071 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002072 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002073 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002074 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2075 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002076 }
2077 update_adv_data(&req);
2078 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002079 if (cp->val) {
2080 scan = SCAN_PAGE;
2081 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002082 /* If we don't have any whitelist entries just
2083 * disable all scanning. If there are entries
2084 * and we had both page and inquiry scanning
2085 * enabled then fall back to only page scanning.
2086 * Otherwise no changes are needed.
2087 */
2088 if (list_empty(&hdev->whitelist))
2089 scan = SCAN_DISABLED;
2090 else if (test_bit(HCI_ISCAN, &hdev->flags))
2091 scan = SCAN_PAGE;
2092 else
2093 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002094
2095 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002096 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002097 cancel_delayed_work(&hdev->discov_off);
2098 }
2099
2100 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2101 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002102
Johan Hedberg3bd27242014-07-28 20:53:58 +03002103no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002104 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002105 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2106 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002107 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002108
Johan Hedberg2b76f452013-03-15 17:07:04 -05002109 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002110 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002111 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002112 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002113 err = set_connectable_update_settings(hdev, sk,
2114 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002115 goto failed;
2116 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002117
2118failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002119 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002120 return err;
2121}
2122
Johan Hedbergb2939472014-07-30 09:22:23 +03002123static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002124 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002125{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002126 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002127 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002128 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002129
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002130 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002131
Johan Hedberga7e80f22013-01-09 16:05:19 +02002132 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002133 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2134 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002135
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002136 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002137
2138 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002139 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002140 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002141 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002142
Johan Hedbergb2939472014-07-30 09:22:23 +03002143 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002144 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002145 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002146
Marcel Holtmann55594352013-10-06 16:11:57 -07002147 if (changed)
2148 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002149
Marcel Holtmann55594352013-10-06 16:11:57 -07002150unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002151 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002152 return err;
2153}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002154
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002155static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2156 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002157{
2158 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002159 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002160 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002161 int err;
2162
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002163 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002164
Johan Hedberge6fe7982013-10-02 15:45:22 +03002165 status = mgmt_bredr_support(hdev);
2166 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002167 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2168 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002169
Johan Hedberga7e80f22013-01-09 16:05:19 +02002170 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002171 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2172 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002173
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002174 hci_dev_lock(hdev);
2175
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002176 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002177 bool changed = false;
2178
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002179 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002180 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002181 changed = true;
2182 }
2183
2184 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2185 if (err < 0)
2186 goto failed;
2187
2188 if (changed)
2189 err = new_settings(hdev, sk);
2190
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002191 goto failed;
2192 }
2193
Johan Hedberg333ae952015-03-17 13:48:47 +02002194 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002195 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2196 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002197 goto failed;
2198 }
2199
2200 val = !!cp->val;
2201
2202 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2203 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2204 goto failed;
2205 }
2206
2207 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2208 if (!cmd) {
2209 err = -ENOMEM;
2210 goto failed;
2211 }
2212
2213 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2214 if (err < 0) {
2215 mgmt_pending_remove(cmd);
2216 goto failed;
2217 }
2218
2219failed:
2220 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002221 return err;
2222}
2223
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002224static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002225{
2226 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002227 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002228 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002229 int err;
2230
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002231 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002232
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002233 status = mgmt_bredr_support(hdev);
2234 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002235 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002236
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002237 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002238 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2239 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002240
Johan Hedberga7e80f22013-01-09 16:05:19 +02002241 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002242 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2243 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002244
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002245 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002246
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002247 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002248 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002249
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002250 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002251 changed = !hci_dev_test_and_set_flag(hdev,
2252 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002253 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002254 changed = hci_dev_test_and_clear_flag(hdev,
2255 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002256 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002257 changed = hci_dev_test_and_clear_flag(hdev,
2258 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002259 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002260 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002261 }
2262
2263 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2264 if (err < 0)
2265 goto failed;
2266
2267 if (changed)
2268 err = new_settings(hdev, sk);
2269
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002270 goto failed;
2271 }
2272
Johan Hedberg333ae952015-03-17 13:48:47 +02002273 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002274 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2275 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002276 goto failed;
2277 }
2278
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002279 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002280 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2281 goto failed;
2282 }
2283
2284 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2285 if (!cmd) {
2286 err = -ENOMEM;
2287 goto failed;
2288 }
2289
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002290 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002291 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2292 sizeof(cp->val), &cp->val);
2293
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002294 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002295 if (err < 0) {
2296 mgmt_pending_remove(cmd);
2297 goto failed;
2298 }
2299
2300failed:
2301 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002302 return err;
2303}
2304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002305static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002306{
2307 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002308 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002309 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002310 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002311
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002312 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002313
Johan Hedberge6fe7982013-10-02 15:45:22 +03002314 status = mgmt_bredr_support(hdev);
2315 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002316 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002317
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002318 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002319 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2320 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002321
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002322 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002323 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2324 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002325
Johan Hedberga7e80f22013-01-09 16:05:19 +02002326 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002327 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2328 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002329
Marcel Holtmannee392692013-10-01 22:59:23 -07002330 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002331
Johan Hedberg333ae952015-03-17 13:48:47 +02002332 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002333 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2334 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002335 goto unlock;
2336 }
2337
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002338 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002339 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002340 } else {
2341 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002342 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2343 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002344 goto unlock;
2345 }
2346
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002347 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002348 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002349
2350 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2351 if (err < 0)
2352 goto unlock;
2353
2354 if (changed)
2355 err = new_settings(hdev, sk);
2356
2357unlock:
2358 hci_dev_unlock(hdev);
2359 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002360}
2361
Marcel Holtmann1904a852015-01-11 13:50:44 -08002362static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002363{
2364 struct cmd_lookup match = { NULL, hdev };
2365
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302366 hci_dev_lock(hdev);
2367
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002368 if (status) {
2369 u8 mgmt_err = mgmt_status(status);
2370
2371 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2372 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302373 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002374 }
2375
2376 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2377
2378 new_settings(hdev, match.sk);
2379
2380 if (match.sk)
2381 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002382
2383 /* Make sure the controller has a good default for
2384 * advertising data. Restrict the update to when LE
2385 * has actually been enabled. During power on, the
2386 * update in powered_update_hci will take care of it.
2387 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002388 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002389 struct hci_request req;
2390
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002391 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002392 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002393 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002394 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002395 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002396 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302397
2398unlock:
2399 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002400}
2401
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002402static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002403{
2404 struct mgmt_mode *cp = data;
2405 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002406 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002407 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002408 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002409 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002410
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002411 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002412
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002413 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002414 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2415 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002416
Johan Hedberga7e80f22013-01-09 16:05:19 +02002417 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002418 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2419 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002420
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002421 /* Bluetooth single mode LE only controllers or dual-mode
2422 * controllers configured as LE only devices, do not allow
2423 * switching LE off. These have either LE enabled explicitly
2424 * or BR/EDR has been previously switched off.
2425 *
2426 * When trying to enable an already enabled LE, then gracefully
2427 * send a positive response. Trying to disable it however will
2428 * result into rejection.
2429 */
2430 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2431 if (cp->val == 0x01)
2432 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2433
Johan Hedberga69e8372015-03-06 21:08:53 +02002434 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2435 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002436 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002437
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002438 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002439
2440 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002441 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002442
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002443 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002444 bool changed = false;
2445
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002446 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002447 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002448 changed = true;
2449 }
2450
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002451 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002452 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002453 changed = true;
2454 }
2455
Johan Hedberg06199cf2012-02-22 16:37:11 +02002456 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2457 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002458 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002459
2460 if (changed)
2461 err = new_settings(hdev, sk);
2462
Johan Hedberg1de028c2012-02-29 19:55:35 -08002463 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002464 }
2465
Johan Hedberg333ae952015-03-17 13:48:47 +02002466 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2467 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002468 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2469 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002470 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002471 }
2472
2473 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2474 if (!cmd) {
2475 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002476 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002477 }
2478
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002479 hci_req_init(&req, hdev);
2480
Johan Hedberg06199cf2012-02-22 16:37:11 +02002481 memset(&hci_cp, 0, sizeof(hci_cp));
2482
2483 if (val) {
2484 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002485 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002486 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002487 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002488 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002489 }
2490
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002491 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2492 &hci_cp);
2493
2494 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302495 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002496 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002497
Johan Hedberg1de028c2012-02-29 19:55:35 -08002498unlock:
2499 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002500 return err;
2501}
2502
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002503/* This is a helper function to test for pending mgmt commands that can
2504 * cause CoD or EIR HCI commands. We can only allow one such pending
2505 * mgmt command at a time since otherwise we cannot easily track what
2506 * the current values are, will be, and based on that calculate if a new
2507 * HCI command needs to be sent and if yes with what value.
2508 */
2509static bool pending_eir_or_class(struct hci_dev *hdev)
2510{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002511 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002512
2513 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2514 switch (cmd->opcode) {
2515 case MGMT_OP_ADD_UUID:
2516 case MGMT_OP_REMOVE_UUID:
2517 case MGMT_OP_SET_DEV_CLASS:
2518 case MGMT_OP_SET_POWERED:
2519 return true;
2520 }
2521 }
2522
2523 return false;
2524}
2525
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002526static const u8 bluetooth_base_uuid[] = {
2527 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2528 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2529};
2530
2531static u8 get_uuid_size(const u8 *uuid)
2532{
2533 u32 val;
2534
2535 if (memcmp(uuid, bluetooth_base_uuid, 12))
2536 return 128;
2537
2538 val = get_unaligned_le32(&uuid[12]);
2539 if (val > 0xffff)
2540 return 32;
2541
2542 return 16;
2543}
2544
Johan Hedberg92da6092013-03-15 17:06:55 -05002545static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2546{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002547 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002548
2549 hci_dev_lock(hdev);
2550
Johan Hedberg333ae952015-03-17 13:48:47 +02002551 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002552 if (!cmd)
2553 goto unlock;
2554
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002555 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2556 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002557
2558 mgmt_pending_remove(cmd);
2559
2560unlock:
2561 hci_dev_unlock(hdev);
2562}
2563
Marcel Holtmann1904a852015-01-11 13:50:44 -08002564static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002565{
2566 BT_DBG("status 0x%02x", status);
2567
2568 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2569}
2570
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002571static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002572{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002573 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002574 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002575 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002576 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002577 int err;
2578
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002579 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002580
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002581 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002582
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002583 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002584 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2585 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002586 goto failed;
2587 }
2588
Andre Guedes92c4c202012-06-07 19:05:44 -03002589 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002590 if (!uuid) {
2591 err = -ENOMEM;
2592 goto failed;
2593 }
2594
2595 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002596 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002597 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002598
Johan Hedbergde66aa62013-01-27 00:31:27 +02002599 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002600
Johan Hedberg890ea892013-03-15 17:06:52 -05002601 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002602
Johan Hedberg890ea892013-03-15 17:06:52 -05002603 update_class(&req);
2604 update_eir(&req);
2605
Johan Hedberg92da6092013-03-15 17:06:55 -05002606 err = hci_req_run(&req, add_uuid_complete);
2607 if (err < 0) {
2608 if (err != -ENODATA)
2609 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002610
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002611 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2612 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002613 goto failed;
2614 }
2615
2616 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002617 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002618 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002619 goto failed;
2620 }
2621
2622 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002623
2624failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002625 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002626 return err;
2627}
2628
Johan Hedberg24b78d02012-02-23 23:24:30 +02002629static bool enable_service_cache(struct hci_dev *hdev)
2630{
2631 if (!hdev_is_powered(hdev))
2632 return false;
2633
Marcel Holtmann238be782015-03-13 02:11:06 -07002634 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002635 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2636 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002637 return true;
2638 }
2639
2640 return false;
2641}
2642
Marcel Holtmann1904a852015-01-11 13:50:44 -08002643static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002644{
2645 BT_DBG("status 0x%02x", status);
2646
2647 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2648}
2649
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002650static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002651 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002652{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002653 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002654 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002655 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002656 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 -05002657 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002658 int err, found;
2659
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002660 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002661
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002662 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002663
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002664 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002665 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2666 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002667 goto unlock;
2668 }
2669
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002670 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002671 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002672
Johan Hedberg24b78d02012-02-23 23:24:30 +02002673 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002674 err = mgmt_cmd_complete(sk, hdev->id,
2675 MGMT_OP_REMOVE_UUID,
2676 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002677 goto unlock;
2678 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002679
Johan Hedberg9246a862012-02-23 21:33:16 +02002680 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002681 }
2682
2683 found = 0;
2684
Johan Hedberg056341c2013-01-27 00:31:30 +02002685 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002686 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2687 continue;
2688
2689 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002690 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002691 found++;
2692 }
2693
2694 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002695 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2696 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002697 goto unlock;
2698 }
2699
Johan Hedberg9246a862012-02-23 21:33:16 +02002700update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002701 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002702
Johan Hedberg890ea892013-03-15 17:06:52 -05002703 update_class(&req);
2704 update_eir(&req);
2705
Johan Hedberg92da6092013-03-15 17:06:55 -05002706 err = hci_req_run(&req, remove_uuid_complete);
2707 if (err < 0) {
2708 if (err != -ENODATA)
2709 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002710
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002711 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2712 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002713 goto unlock;
2714 }
2715
2716 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002717 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002718 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002719 goto unlock;
2720 }
2721
2722 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002723
2724unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002725 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002726 return err;
2727}
2728
Marcel Holtmann1904a852015-01-11 13:50:44 -08002729static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002730{
2731 BT_DBG("status 0x%02x", status);
2732
2733 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2734}
2735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002736static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002737 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002738{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002739 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002740 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002741 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002742 int err;
2743
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002744 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002745
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002746 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002747 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2748 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002749
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002750 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002751
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002752 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002753 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2754 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002755 goto unlock;
2756 }
2757
2758 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002759 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2760 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002761 goto unlock;
2762 }
2763
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002764 hdev->major_class = cp->major;
2765 hdev->minor_class = cp->minor;
2766
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002767 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002768 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2769 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002770 goto unlock;
2771 }
2772
Johan Hedberg890ea892013-03-15 17:06:52 -05002773 hci_req_init(&req, hdev);
2774
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002775 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002776 hci_dev_unlock(hdev);
2777 cancel_delayed_work_sync(&hdev->service_cache);
2778 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002779 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002780 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002781
Johan Hedberg890ea892013-03-15 17:06:52 -05002782 update_class(&req);
2783
Johan Hedberg92da6092013-03-15 17:06:55 -05002784 err = hci_req_run(&req, set_class_complete);
2785 if (err < 0) {
2786 if (err != -ENODATA)
2787 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002788
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002789 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2790 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002791 goto unlock;
2792 }
2793
2794 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002795 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002796 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002797 goto unlock;
2798 }
2799
2800 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002801
Johan Hedbergb5235a62012-02-21 14:32:24 +02002802unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002803 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002804 return err;
2805}
2806
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002807static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002808 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002809{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002810 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002811 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2812 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002813 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002814 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002815 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002816
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002817 BT_DBG("request for %s", hdev->name);
2818
2819 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002820 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2821 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002822
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002823 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002824 if (key_count > max_key_count) {
2825 BT_ERR("load_link_keys: too big key_count value %u",
2826 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002827 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2828 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002829 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002830
Johan Hedberg86742e12011-11-07 23:13:38 +02002831 expected_len = sizeof(*cp) + key_count *
2832 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002833 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002834 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002835 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002836 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2837 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002838 }
2839
Johan Hedberg4ae14302013-01-20 14:27:13 +02002840 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002841 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2842 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002843
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002844 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002845 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002846
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002847 for (i = 0; i < key_count; i++) {
2848 struct mgmt_link_key_info *key = &cp->keys[i];
2849
Marcel Holtmann8e991132014-01-10 02:07:25 -08002850 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002851 return mgmt_cmd_status(sk, hdev->id,
2852 MGMT_OP_LOAD_LINK_KEYS,
2853 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002854 }
2855
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002856 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002857
2858 hci_link_keys_clear(hdev);
2859
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002860 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002861 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002862 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002863 changed = hci_dev_test_and_clear_flag(hdev,
2864 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002865
2866 if (changed)
2867 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002868
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002869 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002870 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002871
Johan Hedberg58e92932014-06-24 14:00:26 +03002872 /* Always ignore debug keys and require a new pairing if
2873 * the user wants to use them.
2874 */
2875 if (key->type == HCI_LK_DEBUG_COMBINATION)
2876 continue;
2877
Johan Hedberg7652ff62014-06-24 13:15:49 +03002878 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2879 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002880 }
2881
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002882 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002883
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002884 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002885
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002886 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002887}
2888
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002889static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002890 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002891{
2892 struct mgmt_ev_device_unpaired ev;
2893
2894 bacpy(&ev.addr.bdaddr, bdaddr);
2895 ev.addr.type = addr_type;
2896
2897 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002898 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002899}
2900
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002901static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002902 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002903{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002904 struct mgmt_cp_unpair_device *cp = data;
2905 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002906 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002907 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002908 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002909 int err;
2910
Johan Hedberga8a1d192011-11-10 15:54:38 +02002911 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002912 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2913 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002914
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002915 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002916 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2917 MGMT_STATUS_INVALID_PARAMS,
2918 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002919
Johan Hedberg118da702013-01-20 14:27:20 +02002920 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002921 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2922 MGMT_STATUS_INVALID_PARAMS,
2923 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002924
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002925 hci_dev_lock(hdev);
2926
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002927 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002928 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2929 MGMT_STATUS_NOT_POWERED, &rp,
2930 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002931 goto unlock;
2932 }
2933
Johan Hedberge0b2b272014-02-18 17:14:31 +02002934 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002935 /* If disconnection is requested, then look up the
2936 * connection. If the remote device is connected, it
2937 * will be later used to terminate the link.
2938 *
2939 * Setting it to NULL explicitly will cause no
2940 * termination of the link.
2941 */
2942 if (cp->disconnect)
2943 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2944 &cp->addr.bdaddr);
2945 else
2946 conn = NULL;
2947
Johan Hedberg124f6e32012-02-09 13:50:12 +02002948 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002949 } else {
2950 u8 addr_type;
2951
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002952 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2953 &cp->addr.bdaddr);
2954 if (conn) {
2955 /* Defer clearing up the connection parameters
2956 * until closing to give a chance of keeping
2957 * them if a repairing happens.
2958 */
2959 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2960
2961 /* If disconnection is not requested, then
2962 * clear the connection variable so that the
2963 * link is not terminated.
2964 */
2965 if (!cp->disconnect)
2966 conn = NULL;
2967 }
2968
Johan Hedberge0b2b272014-02-18 17:14:31 +02002969 if (cp->addr.type == BDADDR_LE_PUBLIC)
2970 addr_type = ADDR_LE_DEV_PUBLIC;
2971 else
2972 addr_type = ADDR_LE_DEV_RANDOM;
2973
Johan Hedberga7ec7332014-02-18 17:14:35 +02002974 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2975
Johan Hedberge0b2b272014-02-18 17:14:31 +02002976 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2977 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002978
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002979 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002980 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2981 MGMT_STATUS_NOT_PAIRED, &rp,
2982 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002983 goto unlock;
2984 }
2985
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002986 /* If the connection variable is set, then termination of the
2987 * link is requested.
2988 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002989 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002990 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2991 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002992 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002993 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002994 }
2995
Johan Hedberg124f6e32012-02-09 13:50:12 +02002996 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002997 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002998 if (!cmd) {
2999 err = -ENOMEM;
3000 goto unlock;
3001 }
3002
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003003 cmd->cmd_complete = addr_cmd_complete;
3004
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003005 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003006 dc.reason = 0x13; /* Remote User Terminated Connection */
3007 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3008 if (err < 0)
3009 mgmt_pending_remove(cmd);
3010
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003011unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003012 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003013 return err;
3014}
3015
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003016static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003017 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003018{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003019 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003020 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003021 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003022 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003023 int err;
3024
3025 BT_DBG("");
3026
Johan Hedberg06a63b12013-01-20 14:27:21 +02003027 memset(&rp, 0, sizeof(rp));
3028 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3029 rp.addr.type = cp->addr.type;
3030
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003031 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003032 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3033 MGMT_STATUS_INVALID_PARAMS,
3034 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003035
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003036 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003037
3038 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003039 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3040 MGMT_STATUS_NOT_POWERED, &rp,
3041 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003042 goto failed;
3043 }
3044
Johan Hedberg333ae952015-03-17 13:48:47 +02003045 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003046 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3047 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003048 goto failed;
3049 }
3050
Andre Guedes591f47f2012-04-24 21:02:49 -03003051 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003052 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3053 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003054 else
3055 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003056
Vishal Agarwalf9607272012-06-13 05:32:43 +05303057 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003058 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3059 MGMT_STATUS_NOT_CONNECTED, &rp,
3060 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003061 goto failed;
3062 }
3063
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003064 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003065 if (!cmd) {
3066 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003067 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003068 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003069
Johan Hedbergf5818c22014-12-05 13:36:02 +02003070 cmd->cmd_complete = generic_cmd_complete;
3071
Johan Hedberge3f2f922014-08-18 20:33:33 +03003072 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003073 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003074 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003075
3076failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003077 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003078 return err;
3079}
3080
Andre Guedes57c14772012-04-24 21:02:50 -03003081static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003082{
3083 switch (link_type) {
3084 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003085 switch (addr_type) {
3086 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003087 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003088
Johan Hedberg48264f02011-11-09 13:58:58 +02003089 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003090 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003091 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003092 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003093
Johan Hedberg4c659c32011-11-07 23:13:39 +02003094 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003095 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003096 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003097 }
3098}
3099
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003100static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3101 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003102{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003103 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003104 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003105 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003106 int err;
3107 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003108
3109 BT_DBG("");
3110
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003111 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003112
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003113 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003114 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3115 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003116 goto unlock;
3117 }
3118
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003119 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003120 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3121 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003122 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003123 }
3124
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003125 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003126 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003127 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003128 err = -ENOMEM;
3129 goto unlock;
3130 }
3131
Johan Hedberg2784eb42011-01-21 13:56:35 +02003132 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003133 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003134 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3135 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003136 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003137 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003138 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003139 continue;
3140 i++;
3141 }
3142
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003143 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003144
Johan Hedberg4c659c32011-11-07 23:13:39 +02003145 /* Recalculate length in case of filtered SCO connections, etc */
3146 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003147
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003148 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3149 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003150
Johan Hedberga38528f2011-01-22 06:46:43 +02003151 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003152
3153unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003154 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003155 return err;
3156}
3157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003158static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003159 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003160{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003161 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003162 int err;
3163
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003164 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003165 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003166 if (!cmd)
3167 return -ENOMEM;
3168
Johan Hedbergd8457692012-02-17 14:24:57 +02003169 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003170 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003171 if (err < 0)
3172 mgmt_pending_remove(cmd);
3173
3174 return err;
3175}
3176
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003177static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003178 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003179{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003180 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003181 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003182 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003183 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003184 int err;
3185
3186 BT_DBG("");
3187
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003188 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003189
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003190 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003191 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3192 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003193 goto failed;
3194 }
3195
Johan Hedbergd8457692012-02-17 14:24:57 +02003196 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003197 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003198 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3199 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003200 goto failed;
3201 }
3202
3203 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003204 struct mgmt_cp_pin_code_neg_reply ncp;
3205
3206 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003207
3208 BT_ERR("PIN code is not 16 bytes long");
3209
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003210 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003211 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003212 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3213 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003214
3215 goto failed;
3216 }
3217
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003218 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003219 if (!cmd) {
3220 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003221 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003222 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003223
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003224 cmd->cmd_complete = addr_cmd_complete;
3225
Johan Hedbergd8457692012-02-17 14:24:57 +02003226 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003227 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003228 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003229
3230 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3231 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003232 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003233
3234failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003235 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003236 return err;
3237}
3238
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003239static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3240 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003241{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003242 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003243
3244 BT_DBG("");
3245
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003246 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003247 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3248 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003249
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003250 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003251
3252 hdev->io_capability = cp->io_capability;
3253
3254 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003255 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003256
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003257 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003258
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003259 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3260 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003261}
3262
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003263static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003264{
3265 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003266 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003267
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003268 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003269 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3270 continue;
3271
Johan Hedberge9a416b2011-02-19 12:05:56 -03003272 if (cmd->user_data != conn)
3273 continue;
3274
3275 return cmd;
3276 }
3277
3278 return NULL;
3279}
3280
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003281static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282{
3283 struct mgmt_rp_pair_device rp;
3284 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003285 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003286
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003287 bacpy(&rp.addr.bdaddr, &conn->dst);
3288 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003289
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003290 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3291 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003292
3293 /* So we don't get further callbacks for this connection */
3294 conn->connect_cfm_cb = NULL;
3295 conn->security_cfm_cb = NULL;
3296 conn->disconn_cfm_cb = NULL;
3297
David Herrmann76a68ba2013-04-06 20:28:37 +02003298 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003299
3300 /* The device is paired so there is no need to remove
3301 * its connection parameters anymore.
3302 */
3303 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003304
3305 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003306
3307 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003308}
3309
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003310void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3311{
3312 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003313 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003314
3315 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003316 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003317 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003318 mgmt_pending_remove(cmd);
3319 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003320}
3321
Johan Hedberge9a416b2011-02-19 12:05:56 -03003322static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3323{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003324 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003325
3326 BT_DBG("status %u", status);
3327
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003328 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003329 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003330 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003331 return;
3332 }
3333
3334 cmd->cmd_complete(cmd, mgmt_status(status));
3335 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003336}
3337
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003338static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303339{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003340 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303341
3342 BT_DBG("status %u", status);
3343
3344 if (!status)
3345 return;
3346
3347 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003348 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303349 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003350 return;
3351 }
3352
3353 cmd->cmd_complete(cmd, mgmt_status(status));
3354 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303355}
3356
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003357static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003358 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003359{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003360 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003361 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003362 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003363 u8 sec_level, auth_type;
3364 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003365 int err;
3366
3367 BT_DBG("");
3368
Szymon Jancf950a30e2013-01-18 12:48:07 +01003369 memset(&rp, 0, sizeof(rp));
3370 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3371 rp.addr.type = cp->addr.type;
3372
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003373 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003374 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3375 MGMT_STATUS_INVALID_PARAMS,
3376 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003377
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003378 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003379 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3380 MGMT_STATUS_INVALID_PARAMS,
3381 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003382
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003383 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003384
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003385 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003386 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3387 MGMT_STATUS_NOT_POWERED, &rp,
3388 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003389 goto unlock;
3390 }
3391
Johan Hedberg55e76b32015-03-10 22:34:40 +02003392 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3393 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3394 MGMT_STATUS_ALREADY_PAIRED, &rp,
3395 sizeof(rp));
3396 goto unlock;
3397 }
3398
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003399 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003400 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003401
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003402 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003403 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3404 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003405 } else {
3406 u8 addr_type;
3407
3408 /* Convert from L2CAP channel address type to HCI address type
3409 */
3410 if (cp->addr.type == BDADDR_LE_PUBLIC)
3411 addr_type = ADDR_LE_DEV_PUBLIC;
3412 else
3413 addr_type = ADDR_LE_DEV_RANDOM;
3414
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003415 /* When pairing a new device, it is expected to remember
3416 * this device for future connections. Adding the connection
3417 * parameter information ahead of time allows tracking
3418 * of the slave preferred values and will speed up any
3419 * further connection establishment.
3420 *
3421 * If connection parameters already exist, then they
3422 * will be kept and this function does nothing.
3423 */
3424 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3425
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003426 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003427 sec_level, HCI_LE_CONN_TIMEOUT,
3428 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003429 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003430
Ville Tervo30e76272011-02-22 16:10:53 -03003431 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003432 int status;
3433
3434 if (PTR_ERR(conn) == -EBUSY)
3435 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003436 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3437 status = MGMT_STATUS_NOT_SUPPORTED;
3438 else if (PTR_ERR(conn) == -ECONNREFUSED)
3439 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003440 else
3441 status = MGMT_STATUS_CONNECT_FAILED;
3442
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003443 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3444 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003445 goto unlock;
3446 }
3447
3448 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003449 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003450 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3451 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003452 goto unlock;
3453 }
3454
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003455 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003456 if (!cmd) {
3457 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003458 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003459 goto unlock;
3460 }
3461
Johan Hedberg04ab2742014-12-05 13:36:04 +02003462 cmd->cmd_complete = pairing_complete;
3463
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003464 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003465 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003466 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003467 conn->security_cfm_cb = pairing_complete_cb;
3468 conn->disconn_cfm_cb = pairing_complete_cb;
3469 } else {
3470 conn->connect_cfm_cb = le_pairing_complete_cb;
3471 conn->security_cfm_cb = le_pairing_complete_cb;
3472 conn->disconn_cfm_cb = le_pairing_complete_cb;
3473 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003474
Johan Hedberge9a416b2011-02-19 12:05:56 -03003475 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003476 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003477
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003478 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003479 hci_conn_security(conn, sec_level, auth_type, true)) {
3480 cmd->cmd_complete(cmd, 0);
3481 mgmt_pending_remove(cmd);
3482 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003483
3484 err = 0;
3485
3486unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003487 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003488 return err;
3489}
3490
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003491static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3492 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003493{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003494 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003495 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003496 struct hci_conn *conn;
3497 int err;
3498
3499 BT_DBG("");
3500
Johan Hedberg28424702012-02-02 04:02:29 +02003501 hci_dev_lock(hdev);
3502
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003503 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003504 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3505 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003506 goto unlock;
3507 }
3508
Johan Hedberg333ae952015-03-17 13:48:47 +02003509 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003510 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003511 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3512 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003513 goto unlock;
3514 }
3515
3516 conn = cmd->user_data;
3517
3518 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003519 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3520 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003521 goto unlock;
3522 }
3523
Johan Hedberga511b352014-12-11 21:45:45 +02003524 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3525 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003526
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003527 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3528 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003529unlock:
3530 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003531 return err;
3532}
3533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003534static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003535 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003536 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003537{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003538 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003539 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003540 int err;
3541
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003542 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003543
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003544 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003545 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3546 MGMT_STATUS_NOT_POWERED, addr,
3547 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003548 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003549 }
3550
Johan Hedberg1707c602013-03-15 17:07:15 -05003551 if (addr->type == BDADDR_BREDR)
3552 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003553 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003554 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003555
Johan Hedberg272d90d2012-02-09 15:26:12 +02003556 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003557 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3558 MGMT_STATUS_NOT_CONNECTED, addr,
3559 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003560 goto done;
3561 }
3562
Johan Hedberg1707c602013-03-15 17:07:15 -05003563 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003564 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003565 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003566 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3567 MGMT_STATUS_SUCCESS, addr,
3568 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003569 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003570 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3571 MGMT_STATUS_FAILED, addr,
3572 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003573
Brian Gix47c15e22011-11-16 13:53:14 -08003574 goto done;
3575 }
3576
Johan Hedberg1707c602013-03-15 17:07:15 -05003577 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003578 if (!cmd) {
3579 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003580 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003581 }
3582
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003583 cmd->cmd_complete = addr_cmd_complete;
3584
Brian Gix0df4c182011-11-16 13:53:13 -08003585 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003586 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3587 struct hci_cp_user_passkey_reply cp;
3588
Johan Hedberg1707c602013-03-15 17:07:15 -05003589 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003590 cp.passkey = passkey;
3591 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3592 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003593 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3594 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003595
Johan Hedberga664b5b2011-02-19 12:06:02 -03003596 if (err < 0)
3597 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003598
Brian Gix0df4c182011-11-16 13:53:13 -08003599done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003600 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003601 return err;
3602}
3603
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303604static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3605 void *data, u16 len)
3606{
3607 struct mgmt_cp_pin_code_neg_reply *cp = data;
3608
3609 BT_DBG("");
3610
Johan Hedberg1707c602013-03-15 17:07:15 -05003611 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303612 MGMT_OP_PIN_CODE_NEG_REPLY,
3613 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3614}
3615
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003616static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3617 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003618{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003619 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003620
3621 BT_DBG("");
3622
3623 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003624 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3625 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003626
Johan Hedberg1707c602013-03-15 17:07:15 -05003627 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003628 MGMT_OP_USER_CONFIRM_REPLY,
3629 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003630}
3631
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003632static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003633 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003634{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003635 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003636
3637 BT_DBG("");
3638
Johan Hedberg1707c602013-03-15 17:07:15 -05003639 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003640 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3641 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003642}
3643
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003644static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3645 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003646{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003647 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003648
3649 BT_DBG("");
3650
Johan Hedberg1707c602013-03-15 17:07:15 -05003651 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003652 MGMT_OP_USER_PASSKEY_REPLY,
3653 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003654}
3655
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003656static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003657 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003658{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003659 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003660
3661 BT_DBG("");
3662
Johan Hedberg1707c602013-03-15 17:07:15 -05003663 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003664 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3665 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003666}
3667
Johan Hedberg13928972013-03-15 17:07:00 -05003668static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003669{
Johan Hedberg13928972013-03-15 17:07:00 -05003670 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003671 struct hci_cp_write_local_name cp;
3672
Johan Hedberg13928972013-03-15 17:07:00 -05003673 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003674
Johan Hedberg890ea892013-03-15 17:06:52 -05003675 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003676}
3677
Marcel Holtmann1904a852015-01-11 13:50:44 -08003678static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003679{
3680 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003681 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003682
3683 BT_DBG("status 0x%02x", status);
3684
3685 hci_dev_lock(hdev);
3686
Johan Hedberg333ae952015-03-17 13:48:47 +02003687 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003688 if (!cmd)
3689 goto unlock;
3690
3691 cp = cmd->param;
3692
3693 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003694 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3695 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003696 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003697 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3698 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003699
3700 mgmt_pending_remove(cmd);
3701
3702unlock:
3703 hci_dev_unlock(hdev);
3704}
3705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003706static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003707 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003708{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003709 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003710 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003711 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003712 int err;
3713
3714 BT_DBG("");
3715
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003716 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003717
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003718 /* If the old values are the same as the new ones just return a
3719 * direct command complete event.
3720 */
3721 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3722 !memcmp(hdev->short_name, cp->short_name,
3723 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003724 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3725 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003726 goto failed;
3727 }
3728
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003729 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003730
Johan Hedbergb5235a62012-02-21 14:32:24 +02003731 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003732 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003733
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003734 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3735 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003736 if (err < 0)
3737 goto failed;
3738
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003739 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3740 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003741
Johan Hedbergb5235a62012-02-21 14:32:24 +02003742 goto failed;
3743 }
3744
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003745 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003746 if (!cmd) {
3747 err = -ENOMEM;
3748 goto failed;
3749 }
3750
Johan Hedberg13928972013-03-15 17:07:00 -05003751 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3752
Johan Hedberg890ea892013-03-15 17:06:52 -05003753 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003754
3755 if (lmp_bredr_capable(hdev)) {
3756 update_name(&req);
3757 update_eir(&req);
3758 }
3759
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003760 /* The name is stored in the scan response data and so
3761 * no need to udpate the advertising data here.
3762 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003763 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003764 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003765
Johan Hedberg13928972013-03-15 17:07:00 -05003766 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003767 if (err < 0)
3768 mgmt_pending_remove(cmd);
3769
3770failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003771 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003772 return err;
3773}
3774
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003775static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3776 u16 opcode, struct sk_buff *skb)
3777{
3778 struct mgmt_rp_read_local_oob_data mgmt_rp;
3779 size_t rp_size = sizeof(mgmt_rp);
3780 struct mgmt_pending_cmd *cmd;
3781
3782 BT_DBG("%s status %u", hdev->name, status);
3783
3784 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3785 if (!cmd)
3786 return;
3787
3788 if (status || !skb) {
3789 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3790 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3791 goto remove;
3792 }
3793
3794 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3795
3796 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3797 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3798
3799 if (skb->len < sizeof(*rp)) {
3800 mgmt_cmd_status(cmd->sk, hdev->id,
3801 MGMT_OP_READ_LOCAL_OOB_DATA,
3802 MGMT_STATUS_FAILED);
3803 goto remove;
3804 }
3805
3806 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3807 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3808
3809 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3810 } else {
3811 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3812
3813 if (skb->len < sizeof(*rp)) {
3814 mgmt_cmd_status(cmd->sk, hdev->id,
3815 MGMT_OP_READ_LOCAL_OOB_DATA,
3816 MGMT_STATUS_FAILED);
3817 goto remove;
3818 }
3819
3820 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3821 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3822
3823 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3824 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3825 }
3826
3827 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3828 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3829
3830remove:
3831 mgmt_pending_remove(cmd);
3832}
3833
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003834static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003835 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003836{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003837 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003838 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003839 int err;
3840
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003841 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003842
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003843 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003844
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003845 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003846 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3847 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003848 goto unlock;
3849 }
3850
Andre Guedes9a1a1992012-07-24 15:03:48 -03003851 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003852 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3853 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003854 goto unlock;
3855 }
3856
Johan Hedberg333ae952015-03-17 13:48:47 +02003857 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003858 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3859 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003860 goto unlock;
3861 }
3862
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003863 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003864 if (!cmd) {
3865 err = -ENOMEM;
3866 goto unlock;
3867 }
3868
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003869 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003870
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003871 if (bredr_sc_enabled(hdev))
3872 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3873 else
3874 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3875
3876 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003877 if (err < 0)
3878 mgmt_pending_remove(cmd);
3879
3880unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003881 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003882 return err;
3883}
3884
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003885static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003886 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003887{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003888 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003889 int err;
3890
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003891 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003892
Johan Hedberg5d57e792015-01-23 10:10:38 +02003893 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003894 return mgmt_cmd_complete(sk, hdev->id,
3895 MGMT_OP_ADD_REMOTE_OOB_DATA,
3896 MGMT_STATUS_INVALID_PARAMS,
3897 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003898
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003899 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003900
Marcel Holtmannec109112014-01-10 02:07:30 -08003901 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3902 struct mgmt_cp_add_remote_oob_data *cp = data;
3903 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003904
Johan Hedbergc19a4952014-11-17 20:52:19 +02003905 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003906 err = mgmt_cmd_complete(sk, hdev->id,
3907 MGMT_OP_ADD_REMOTE_OOB_DATA,
3908 MGMT_STATUS_INVALID_PARAMS,
3909 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003910 goto unlock;
3911 }
3912
Marcel Holtmannec109112014-01-10 02:07:30 -08003913 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003914 cp->addr.type, cp->hash,
3915 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003916 if (err < 0)
3917 status = MGMT_STATUS_FAILED;
3918 else
3919 status = MGMT_STATUS_SUCCESS;
3920
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003921 err = mgmt_cmd_complete(sk, hdev->id,
3922 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3923 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003924 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3925 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003926 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003927 u8 status;
3928
Johan Hedberg86df9202014-10-26 20:52:27 +01003929 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003930 /* Enforce zero-valued 192-bit parameters as
3931 * long as legacy SMP OOB isn't implemented.
3932 */
3933 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3934 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003935 err = mgmt_cmd_complete(sk, hdev->id,
3936 MGMT_OP_ADD_REMOTE_OOB_DATA,
3937 MGMT_STATUS_INVALID_PARAMS,
3938 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003939 goto unlock;
3940 }
3941
Johan Hedberg86df9202014-10-26 20:52:27 +01003942 rand192 = NULL;
3943 hash192 = NULL;
3944 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003945 /* In case one of the P-192 values is set to zero,
3946 * then just disable OOB data for P-192.
3947 */
3948 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3949 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3950 rand192 = NULL;
3951 hash192 = NULL;
3952 } else {
3953 rand192 = cp->rand192;
3954 hash192 = cp->hash192;
3955 }
3956 }
3957
3958 /* In case one of the P-256 values is set to zero, then just
3959 * disable OOB data for P-256.
3960 */
3961 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3962 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3963 rand256 = NULL;
3964 hash256 = NULL;
3965 } else {
3966 rand256 = cp->rand256;
3967 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003968 }
3969
Johan Hedberg81328d52014-10-26 20:33:47 +01003970 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003971 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003972 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003973 if (err < 0)
3974 status = MGMT_STATUS_FAILED;
3975 else
3976 status = MGMT_STATUS_SUCCESS;
3977
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003978 err = mgmt_cmd_complete(sk, hdev->id,
3979 MGMT_OP_ADD_REMOTE_OOB_DATA,
3980 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003981 } else {
3982 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003983 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3984 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003985 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003986
Johan Hedbergc19a4952014-11-17 20:52:19 +02003987unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003988 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003989 return err;
3990}
3991
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003992static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003993 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003994{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003995 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003996 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003997 int err;
3998
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003999 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01004000
Johan Hedbergc19a4952014-11-17 20:52:19 +02004001 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004002 return mgmt_cmd_complete(sk, hdev->id,
4003 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4004 MGMT_STATUS_INVALID_PARAMS,
4005 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004006
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004007 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004008
Johan Hedbergeedbd582014-11-15 09:34:23 +02004009 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4010 hci_remote_oob_data_clear(hdev);
4011 status = MGMT_STATUS_SUCCESS;
4012 goto done;
4013 }
4014
Johan Hedberg6928a922014-10-26 20:46:09 +01004015 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004016 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004017 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004018 else
Szymon Janca6785be2012-12-13 15:11:21 +01004019 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004020
Johan Hedbergeedbd582014-11-15 09:34:23 +02004021done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004022 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4023 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004024
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004025 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004026 return err;
4027}
4028
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004029static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
4030{
4031 struct hci_dev *hdev = req->hdev;
4032 struct hci_cp_inquiry cp;
4033 /* General inquiry access code (GIAC) */
4034 u8 lap[3] = { 0x33, 0x8b, 0x9e };
4035
4036 *status = mgmt_bredr_support(hdev);
4037 if (*status)
4038 return false;
4039
4040 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
4041 *status = MGMT_STATUS_BUSY;
4042 return false;
4043 }
4044
4045 hci_inquiry_cache_flush(hdev);
4046
4047 memset(&cp, 0, sizeof(cp));
4048 memcpy(&cp.lap, lap, sizeof(cp.lap));
4049 cp.length = DISCOV_BREDR_INQUIRY_LEN;
4050
4051 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4052
4053 return true;
4054}
4055
4056static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004057{
Marcel Holtmann80190442014-12-04 11:36:36 +01004058 struct hci_dev *hdev = req->hdev;
4059 struct hci_cp_le_set_scan_param param_cp;
4060 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004061 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004062 int err;
4063
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004064 *status = mgmt_le_support(hdev);
4065 if (*status)
4066 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004067
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004068 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4069 /* Don't let discovery abort an outgoing connection attempt
4070 * that's using directed advertising.
4071 */
4072 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4073 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004074 return false;
4075 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004076
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004077 disable_advertising(req);
4078 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004079
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004080 /* If controller is scanning, it means the background scanning is
4081 * running. Thus, we should temporarily stop it in order to set the
4082 * discovery scanning parameters.
4083 */
4084 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4085 hci_req_add_le_scan_disable(req);
4086
4087 /* All active scans will be done with either a resolvable private
4088 * address (when privacy feature has been enabled) or non-resolvable
4089 * private address.
4090 */
4091 err = hci_update_random_address(req, true, &own_addr_type);
4092 if (err < 0) {
4093 *status = MGMT_STATUS_FAILED;
4094 return false;
4095 }
4096
4097 memset(&param_cp, 0, sizeof(param_cp));
4098 param_cp.type = LE_SCAN_ACTIVE;
4099 param_cp.interval = cpu_to_le16(interval);
4100 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4101 param_cp.own_address_type = own_addr_type;
4102
4103 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4104 &param_cp);
4105
4106 memset(&enable_cp, 0, sizeof(enable_cp));
4107 enable_cp.enable = LE_SCAN_ENABLE;
4108 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4109
4110 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4111 &enable_cp);
4112
4113 return true;
4114}
4115
4116static bool trigger_discovery(struct hci_request *req, u8 *status)
4117{
4118 struct hci_dev *hdev = req->hdev;
4119
4120 switch (hdev->discovery.type) {
4121 case DISCOV_TYPE_BREDR:
4122 if (!trigger_bredr_inquiry(req, status))
4123 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004124 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004125
Marcel Holtmann80190442014-12-04 11:36:36 +01004126 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004127 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4128 &hdev->quirks)) {
4129 /* During simultaneous discovery, we double LE scan
4130 * interval. We must leave some time for the controller
4131 * to do BR/EDR inquiry.
4132 */
4133 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4134 status))
4135 return false;
4136
4137 if (!trigger_bredr_inquiry(req, status))
4138 return false;
4139
4140 return true;
4141 }
4142
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004143 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004144 *status = MGMT_STATUS_NOT_SUPPORTED;
4145 return false;
4146 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004147 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004148
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004149 case DISCOV_TYPE_LE:
4150 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004151 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004152 break;
4153
4154 default:
4155 *status = MGMT_STATUS_INVALID_PARAMS;
4156 return false;
4157 }
4158
4159 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004160}
4161
Marcel Holtmann1904a852015-01-11 13:50:44 -08004162static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4163 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004164{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004165 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004166 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004167
Andre Guedes7c307722013-04-30 15:29:28 -03004168 BT_DBG("status %d", status);
4169
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004170 hci_dev_lock(hdev);
4171
Johan Hedberg333ae952015-03-17 13:48:47 +02004172 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004173 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004174 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004175
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004176 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004177 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004178 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004179 }
4180
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004181 if (status) {
4182 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4183 goto unlock;
4184 }
4185
Andre Guedes7c307722013-04-30 15:29:28 -03004186 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004187
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004188 /* If the scan involves LE scan, pick proper timeout to schedule
4189 * hdev->le_scan_disable that will stop it.
4190 */
Andre Guedes7c307722013-04-30 15:29:28 -03004191 switch (hdev->discovery.type) {
4192 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004193 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004194 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004195 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004196 /* When running simultaneous discovery, the LE scanning time
4197 * should occupy the whole discovery time sine BR/EDR inquiry
4198 * and LE scanning are scheduled by the controller.
4199 *
4200 * For interleaving discovery in comparison, BR/EDR inquiry
4201 * and LE scanning are done sequentially with separate
4202 * timeouts.
4203 */
4204 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4205 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4206 else
4207 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004208 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004209 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004210 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004211 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004212 default:
4213 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004214 timeout = 0;
4215 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004216 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004217
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004218 if (timeout) {
4219 /* When service discovery is used and the controller has
4220 * a strict duplicate filter, it is important to remember
4221 * the start and duration of the scan. This is required
4222 * for restarting scanning during the discovery phase.
4223 */
4224 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4225 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004226 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004227 hdev->discovery.scan_start = jiffies;
4228 hdev->discovery.scan_duration = timeout;
4229 }
4230
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004231 queue_delayed_work(hdev->workqueue,
4232 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004233 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004234
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004235unlock:
4236 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004237}
4238
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004239static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004240 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004241{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004242 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004243 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004244 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004245 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004246 int err;
4247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004248 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004249
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004250 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004251
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004252 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004253 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4254 MGMT_STATUS_NOT_POWERED,
4255 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004256 goto failed;
4257 }
4258
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004259 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004260 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004261 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4262 MGMT_STATUS_BUSY, &cp->type,
4263 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004264 goto failed;
4265 }
4266
Johan Hedberg2922a942014-12-05 13:36:06 +02004267 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004268 if (!cmd) {
4269 err = -ENOMEM;
4270 goto failed;
4271 }
4272
Johan Hedberg2922a942014-12-05 13:36:06 +02004273 cmd->cmd_complete = generic_cmd_complete;
4274
Marcel Holtmann22078802014-12-05 11:45:22 +01004275 /* Clear the discovery filter first to free any previously
4276 * allocated memory for the UUID list.
4277 */
4278 hci_discovery_filter_clear(hdev);
4279
Andre Guedes4aab14e2012-02-17 20:39:36 -03004280 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004281 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004282
Andre Guedes7c307722013-04-30 15:29:28 -03004283 hci_req_init(&req, hdev);
4284
Marcel Holtmann80190442014-12-04 11:36:36 +01004285 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004286 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4287 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004288 mgmt_pending_remove(cmd);
4289 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004290 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004291
Andre Guedes7c307722013-04-30 15:29:28 -03004292 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004293 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004294 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004295 goto failed;
4296 }
4297
4298 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004299
4300failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004301 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004302 return err;
4303}
4304
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004305static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4306 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004307{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004308 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4309 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004310}
4311
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004312static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4313 void *data, u16 len)
4314{
4315 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004316 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004317 struct hci_request req;
4318 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4319 u16 uuid_count, expected_len;
4320 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004321 int err;
4322
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004323 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004324
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004325 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004326
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004327 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004328 err = mgmt_cmd_complete(sk, hdev->id,
4329 MGMT_OP_START_SERVICE_DISCOVERY,
4330 MGMT_STATUS_NOT_POWERED,
4331 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004332 goto failed;
4333 }
4334
4335 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004336 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004337 err = mgmt_cmd_complete(sk, hdev->id,
4338 MGMT_OP_START_SERVICE_DISCOVERY,
4339 MGMT_STATUS_BUSY, &cp->type,
4340 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004341 goto failed;
4342 }
4343
4344 uuid_count = __le16_to_cpu(cp->uuid_count);
4345 if (uuid_count > max_uuid_count) {
4346 BT_ERR("service_discovery: too big uuid_count value %u",
4347 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004348 err = mgmt_cmd_complete(sk, hdev->id,
4349 MGMT_OP_START_SERVICE_DISCOVERY,
4350 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4351 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004352 goto failed;
4353 }
4354
4355 expected_len = sizeof(*cp) + uuid_count * 16;
4356 if (expected_len != len) {
4357 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4358 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004359 err = mgmt_cmd_complete(sk, hdev->id,
4360 MGMT_OP_START_SERVICE_DISCOVERY,
4361 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4362 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004363 goto failed;
4364 }
4365
4366 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004367 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004368 if (!cmd) {
4369 err = -ENOMEM;
4370 goto failed;
4371 }
4372
Johan Hedberg2922a942014-12-05 13:36:06 +02004373 cmd->cmd_complete = service_discovery_cmd_complete;
4374
Marcel Holtmann22078802014-12-05 11:45:22 +01004375 /* Clear the discovery filter first to free any previously
4376 * allocated memory for the UUID list.
4377 */
4378 hci_discovery_filter_clear(hdev);
4379
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004380 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004381 hdev->discovery.type = cp->type;
4382 hdev->discovery.rssi = cp->rssi;
4383 hdev->discovery.uuid_count = uuid_count;
4384
4385 if (uuid_count > 0) {
4386 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4387 GFP_KERNEL);
4388 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004389 err = mgmt_cmd_complete(sk, hdev->id,
4390 MGMT_OP_START_SERVICE_DISCOVERY,
4391 MGMT_STATUS_FAILED,
4392 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004393 mgmt_pending_remove(cmd);
4394 goto failed;
4395 }
4396 }
4397
4398 hci_req_init(&req, hdev);
4399
4400 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004401 err = mgmt_cmd_complete(sk, hdev->id,
4402 MGMT_OP_START_SERVICE_DISCOVERY,
4403 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004404 mgmt_pending_remove(cmd);
4405 goto failed;
4406 }
4407
4408 err = hci_req_run(&req, start_discovery_complete);
4409 if (err < 0) {
4410 mgmt_pending_remove(cmd);
4411 goto failed;
4412 }
4413
4414 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4415
4416failed:
4417 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004418 return err;
4419}
4420
Marcel Holtmann1904a852015-01-11 13:50:44 -08004421static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004422{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004423 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004424
Andre Guedes0e05bba2013-04-30 15:29:33 -03004425 BT_DBG("status %d", status);
4426
4427 hci_dev_lock(hdev);
4428
Johan Hedberg333ae952015-03-17 13:48:47 +02004429 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004430 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004431 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004432 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004433 }
4434
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004435 if (!status)
4436 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004437
Andre Guedes0e05bba2013-04-30 15:29:33 -03004438 hci_dev_unlock(hdev);
4439}
4440
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004441static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004442 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004443{
Johan Hedbergd9306502012-02-20 23:25:18 +02004444 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004445 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004446 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004447 int err;
4448
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004449 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004450
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004451 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004452
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004453 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004454 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4455 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4456 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004457 goto unlock;
4458 }
4459
4460 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004461 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4462 MGMT_STATUS_INVALID_PARAMS,
4463 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004464 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004465 }
4466
Johan Hedberg2922a942014-12-05 13:36:06 +02004467 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004468 if (!cmd) {
4469 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004470 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004471 }
4472
Johan Hedberg2922a942014-12-05 13:36:06 +02004473 cmd->cmd_complete = generic_cmd_complete;
4474
Andre Guedes0e05bba2013-04-30 15:29:33 -03004475 hci_req_init(&req, hdev);
4476
Johan Hedberg21a60d32014-06-10 14:05:58 +03004477 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004478
Johan Hedberg21a60d32014-06-10 14:05:58 +03004479 err = hci_req_run(&req, stop_discovery_complete);
4480 if (!err) {
4481 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004482 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004483 }
4484
Johan Hedberg21a60d32014-06-10 14:05:58 +03004485 mgmt_pending_remove(cmd);
4486
4487 /* If no HCI commands were sent we're done */
4488 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004489 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4490 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004491 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4492 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004493
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004494unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004495 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004496 return err;
4497}
4498
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004499static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004500 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004501{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004502 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004503 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004504 int err;
4505
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004506 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004507
Johan Hedberg561aafb2012-01-04 13:31:59 +02004508 hci_dev_lock(hdev);
4509
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004510 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004511 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4512 MGMT_STATUS_FAILED, &cp->addr,
4513 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004514 goto failed;
4515 }
4516
Johan Hedberga198e7b2012-02-17 14:27:06 +02004517 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004518 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004519 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4520 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4521 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004522 goto failed;
4523 }
4524
4525 if (cp->name_known) {
4526 e->name_state = NAME_KNOWN;
4527 list_del(&e->list);
4528 } else {
4529 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004530 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004531 }
4532
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004533 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4534 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004535
4536failed:
4537 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004538 return err;
4539}
4540
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004541static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004542 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004543{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004544 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004545 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004546 int err;
4547
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004548 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004549
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004550 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004551 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4552 MGMT_STATUS_INVALID_PARAMS,
4553 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004554
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004555 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004556
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004557 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4558 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004559 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004560 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004561 goto done;
4562 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004563
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004564 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4565 sk);
4566 status = MGMT_STATUS_SUCCESS;
4567
4568done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004569 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4570 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004571
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004572 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004573
4574 return err;
4575}
4576
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004577static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004578 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004579{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004580 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004581 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004582 int err;
4583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004584 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004585
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004586 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004587 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4588 MGMT_STATUS_INVALID_PARAMS,
4589 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004590
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004591 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004592
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004593 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4594 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004595 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004596 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004597 goto done;
4598 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004599
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004600 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4601 sk);
4602 status = MGMT_STATUS_SUCCESS;
4603
4604done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004605 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4606 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004607
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004608 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004609
4610 return err;
4611}
4612
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004613static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4614 u16 len)
4615{
4616 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004617 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004618 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004619 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004620
4621 BT_DBG("%s", hdev->name);
4622
Szymon Jancc72d4b82012-03-16 16:02:57 +01004623 source = __le16_to_cpu(cp->source);
4624
4625 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004626 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4627 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004628
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004629 hci_dev_lock(hdev);
4630
Szymon Jancc72d4b82012-03-16 16:02:57 +01004631 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004632 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4633 hdev->devid_product = __le16_to_cpu(cp->product);
4634 hdev->devid_version = __le16_to_cpu(cp->version);
4635
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004636 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4637 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004638
Johan Hedberg890ea892013-03-15 17:06:52 -05004639 hci_req_init(&req, hdev);
4640 update_eir(&req);
4641 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004642
4643 hci_dev_unlock(hdev);
4644
4645 return err;
4646}
4647
Arman Uguray24b4f382015-03-23 15:57:12 -07004648static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4649 u16 opcode)
4650{
4651 BT_DBG("status %d", status);
4652}
4653
Marcel Holtmann1904a852015-01-11 13:50:44 -08004654static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4655 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004656{
4657 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004658 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004659
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304660 hci_dev_lock(hdev);
4661
Johan Hedberg4375f102013-09-25 13:26:10 +03004662 if (status) {
4663 u8 mgmt_err = mgmt_status(status);
4664
4665 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4666 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304667 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004668 }
4669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004670 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004671 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004672 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004673 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004674
Johan Hedberg4375f102013-09-25 13:26:10 +03004675 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4676 &match);
4677
4678 new_settings(hdev, match.sk);
4679
4680 if (match.sk)
4681 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304682
Arman Uguray24b4f382015-03-23 15:57:12 -07004683 /* If "Set Advertising" was just disabled and instance advertising was
4684 * set up earlier, then enable the advertising instance.
4685 */
4686 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4687 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4688 goto unlock;
4689
4690 hci_req_init(&req, hdev);
4691
4692 update_adv_data(&req);
4693 enable_advertising(&req);
4694
4695 if (hci_req_run(&req, enable_advertising_instance) < 0)
4696 BT_ERR("Failed to re-configure advertising");
4697
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304698unlock:
4699 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004700}
4701
Marcel Holtmann21b51872013-10-10 09:47:53 -07004702static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4703 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004704{
4705 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004706 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004707 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004708 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004709 int err;
4710
4711 BT_DBG("request for %s", hdev->name);
4712
Johan Hedberge6fe7982013-10-02 15:45:22 +03004713 status = mgmt_le_support(hdev);
4714 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004715 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4716 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004717
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004718 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004719 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4720 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004721
4722 hci_dev_lock(hdev);
4723
4724 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004725
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004726 /* The following conditions are ones which mean that we should
4727 * not do any HCI communication but directly send a mgmt
4728 * response to user space (after toggling the flag if
4729 * necessary).
4730 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004731 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004732 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4733 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004734 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004735 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004736 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004737 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004738
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004739 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004740 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004741 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004742 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004743 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004744 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004745 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004746 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004747 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004748 }
4749
4750 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4751 if (err < 0)
4752 goto unlock;
4753
4754 if (changed)
4755 err = new_settings(hdev, sk);
4756
4757 goto unlock;
4758 }
4759
Johan Hedberg333ae952015-03-17 13:48:47 +02004760 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4761 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004762 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4763 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004764 goto unlock;
4765 }
4766
4767 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4768 if (!cmd) {
4769 err = -ENOMEM;
4770 goto unlock;
4771 }
4772
4773 hci_req_init(&req, hdev);
4774
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004775 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004776 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004777 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004778 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004779
Arman Uguray24b4f382015-03-23 15:57:12 -07004780 if (val) {
4781 /* Switch to instance "0" for the Set Advertising setting. */
Florian Grandelefae0022015-06-18 03:16:37 +02004782 update_inst_adv_data(&req, 0x00);
4783 update_inst_scan_rsp_data(&req, 0x00);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004784 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004785 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004786 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004787 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004788
4789 err = hci_req_run(&req, set_advertising_complete);
4790 if (err < 0)
4791 mgmt_pending_remove(cmd);
4792
4793unlock:
4794 hci_dev_unlock(hdev);
4795 return err;
4796}
4797
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004798static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4799 void *data, u16 len)
4800{
4801 struct mgmt_cp_set_static_address *cp = data;
4802 int err;
4803
4804 BT_DBG("%s", hdev->name);
4805
Marcel Holtmann62af4442013-10-02 22:10:32 -07004806 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004807 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4808 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004809
4810 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004811 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4812 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004813
4814 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4815 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004816 return mgmt_cmd_status(sk, hdev->id,
4817 MGMT_OP_SET_STATIC_ADDRESS,
4818 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004819
4820 /* Two most significant bits shall be set */
4821 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004822 return mgmt_cmd_status(sk, hdev->id,
4823 MGMT_OP_SET_STATIC_ADDRESS,
4824 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004825 }
4826
4827 hci_dev_lock(hdev);
4828
4829 bacpy(&hdev->static_addr, &cp->bdaddr);
4830
Marcel Holtmann93690c22015-03-06 10:11:21 -08004831 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4832 if (err < 0)
4833 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004834
Marcel Holtmann93690c22015-03-06 10:11:21 -08004835 err = new_settings(hdev, sk);
4836
4837unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004838 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004839 return err;
4840}
4841
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004842static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4843 void *data, u16 len)
4844{
4845 struct mgmt_cp_set_scan_params *cp = data;
4846 __u16 interval, window;
4847 int err;
4848
4849 BT_DBG("%s", hdev->name);
4850
4851 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004852 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4853 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004854
4855 interval = __le16_to_cpu(cp->interval);
4856
4857 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004858 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4859 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004860
4861 window = __le16_to_cpu(cp->window);
4862
4863 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004864 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4865 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004866
Marcel Holtmann899e1072013-10-14 09:55:32 -07004867 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004868 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4869 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004870
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004871 hci_dev_lock(hdev);
4872
4873 hdev->le_scan_interval = interval;
4874 hdev->le_scan_window = window;
4875
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004876 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4877 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004878
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004879 /* If background scan is running, restart it so new parameters are
4880 * loaded.
4881 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004882 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004883 hdev->discovery.state == DISCOVERY_STOPPED) {
4884 struct hci_request req;
4885
4886 hci_req_init(&req, hdev);
4887
4888 hci_req_add_le_scan_disable(&req);
4889 hci_req_add_le_passive_scan(&req);
4890
4891 hci_req_run(&req, NULL);
4892 }
4893
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004894 hci_dev_unlock(hdev);
4895
4896 return err;
4897}
4898
Marcel Holtmann1904a852015-01-11 13:50:44 -08004899static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4900 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004901{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004902 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004903
4904 BT_DBG("status 0x%02x", status);
4905
4906 hci_dev_lock(hdev);
4907
Johan Hedberg333ae952015-03-17 13:48:47 +02004908 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004909 if (!cmd)
4910 goto unlock;
4911
4912 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004913 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4914 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004915 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004916 struct mgmt_mode *cp = cmd->param;
4917
4918 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004919 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004920 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004921 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004922
Johan Hedberg33e38b32013-03-15 17:07:05 -05004923 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4924 new_settings(hdev, cmd->sk);
4925 }
4926
4927 mgmt_pending_remove(cmd);
4928
4929unlock:
4930 hci_dev_unlock(hdev);
4931}
4932
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004933static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004934 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004935{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004936 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004937 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004938 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004939 int err;
4940
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004941 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004942
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004943 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004944 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004945 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4946 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004947
Johan Hedberga7e80f22013-01-09 16:05:19 +02004948 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004949 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4950 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004951
Antti Julkuf6422ec2011-06-22 13:11:56 +03004952 hci_dev_lock(hdev);
4953
Johan Hedberg333ae952015-03-17 13:48:47 +02004954 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004955 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4956 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004957 goto unlock;
4958 }
4959
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004960 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004961 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4962 hdev);
4963 goto unlock;
4964 }
4965
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004966 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004967 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004968 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4969 hdev);
4970 new_settings(hdev, sk);
4971 goto unlock;
4972 }
4973
Johan Hedberg33e38b32013-03-15 17:07:05 -05004974 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4975 data, len);
4976 if (!cmd) {
4977 err = -ENOMEM;
4978 goto unlock;
4979 }
4980
4981 hci_req_init(&req, hdev);
4982
Johan Hedberg406d7802013-03-15 17:07:09 -05004983 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004984
4985 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004986 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004987 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4988 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004989 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004990 }
4991
Johan Hedberg33e38b32013-03-15 17:07:05 -05004992unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004993 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004994
Antti Julkuf6422ec2011-06-22 13:11:56 +03004995 return err;
4996}
4997
Marcel Holtmann1904a852015-01-11 13:50:44 -08004998static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004999{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005000 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005001
5002 BT_DBG("status 0x%02x", status);
5003
5004 hci_dev_lock(hdev);
5005
Johan Hedberg333ae952015-03-17 13:48:47 +02005006 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005007 if (!cmd)
5008 goto unlock;
5009
5010 if (status) {
5011 u8 mgmt_err = mgmt_status(status);
5012
5013 /* We need to restore the flag if related HCI commands
5014 * failed.
5015 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005016 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005017
Johan Hedberga69e8372015-03-06 21:08:53 +02005018 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005019 } else {
5020 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
5021 new_settings(hdev, cmd->sk);
5022 }
5023
5024 mgmt_pending_remove(cmd);
5025
5026unlock:
5027 hci_dev_unlock(hdev);
5028}
5029
5030static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
5031{
5032 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005033 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005034 struct hci_request req;
5035 int err;
5036
5037 BT_DBG("request for %s", hdev->name);
5038
5039 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005040 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5041 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005042
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005043 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005044 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5045 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005046
5047 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005048 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5049 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005050
5051 hci_dev_lock(hdev);
5052
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005053 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005054 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5055 goto unlock;
5056 }
5057
5058 if (!hdev_is_powered(hdev)) {
5059 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005060 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5061 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5062 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5063 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5064 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005065 }
5066
Marcel Holtmannce05d602015-03-13 02:11:03 -07005067 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005068
5069 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5070 if (err < 0)
5071 goto unlock;
5072
5073 err = new_settings(hdev, sk);
5074 goto unlock;
5075 }
5076
5077 /* Reject disabling when powered on */
5078 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005079 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5080 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005081 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005082 } else {
5083 /* When configuring a dual-mode controller to operate
5084 * with LE only and using a static address, then switching
5085 * BR/EDR back on is not allowed.
5086 *
5087 * Dual-mode controllers shall operate with the public
5088 * address as its identity address for BR/EDR and LE. So
5089 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005090 *
5091 * The same restrictions applies when secure connections
5092 * has been enabled. For BR/EDR this is a controller feature
5093 * while for LE it is a host stack feature. This means that
5094 * switching BR/EDR back on when secure connections has been
5095 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005096 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005097 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005098 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005099 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005100 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5101 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005102 goto unlock;
5103 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005104 }
5105
Johan Hedberg333ae952015-03-17 13:48:47 +02005106 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005107 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5108 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005109 goto unlock;
5110 }
5111
5112 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5113 if (!cmd) {
5114 err = -ENOMEM;
5115 goto unlock;
5116 }
5117
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005118 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005119 * generates the correct flags.
5120 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005121 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005122
5123 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005124
Johan Hedberg432df052014-08-01 11:13:31 +03005125 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005126 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005127
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005128 /* Since only the advertising data flags will change, there
5129 * is no need to update the scan response data.
5130 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005131 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005132
Johan Hedberg0663ca22013-10-02 13:43:14 +03005133 err = hci_req_run(&req, set_bredr_complete);
5134 if (err < 0)
5135 mgmt_pending_remove(cmd);
5136
5137unlock:
5138 hci_dev_unlock(hdev);
5139 return err;
5140}
5141
Johan Hedberga1443f52015-01-23 15:42:46 +02005142static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5143{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005144 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005145 struct mgmt_mode *cp;
5146
5147 BT_DBG("%s status %u", hdev->name, status);
5148
5149 hci_dev_lock(hdev);
5150
Johan Hedberg333ae952015-03-17 13:48:47 +02005151 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005152 if (!cmd)
5153 goto unlock;
5154
5155 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005156 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5157 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005158 goto remove;
5159 }
5160
5161 cp = cmd->param;
5162
5163 switch (cp->val) {
5164 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005165 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5166 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005167 break;
5168 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005169 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005170 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005171 break;
5172 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005173 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5174 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005175 break;
5176 }
5177
5178 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5179 new_settings(hdev, cmd->sk);
5180
5181remove:
5182 mgmt_pending_remove(cmd);
5183unlock:
5184 hci_dev_unlock(hdev);
5185}
5186
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005187static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5188 void *data, u16 len)
5189{
5190 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005191 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005192 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005193 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005194 int err;
5195
5196 BT_DBG("request for %s", hdev->name);
5197
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005198 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005199 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005200 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5201 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005202
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005203 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005204 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005205 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005206 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5207 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005208
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005209 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005210 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005211 MGMT_STATUS_INVALID_PARAMS);
5212
5213 hci_dev_lock(hdev);
5214
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005215 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005216 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005217 bool changed;
5218
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005219 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005220 changed = !hci_dev_test_and_set_flag(hdev,
5221 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005222 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005223 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005224 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005225 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005226 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005227 changed = hci_dev_test_and_clear_flag(hdev,
5228 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005229 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005230 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005231
5232 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5233 if (err < 0)
5234 goto failed;
5235
5236 if (changed)
5237 err = new_settings(hdev, sk);
5238
5239 goto failed;
5240 }
5241
Johan Hedberg333ae952015-03-17 13:48:47 +02005242 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005243 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5244 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005245 goto failed;
5246 }
5247
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005248 val = !!cp->val;
5249
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005250 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5251 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005252 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5253 goto failed;
5254 }
5255
5256 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5257 if (!cmd) {
5258 err = -ENOMEM;
5259 goto failed;
5260 }
5261
Johan Hedberga1443f52015-01-23 15:42:46 +02005262 hci_req_init(&req, hdev);
5263 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5264 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005265 if (err < 0) {
5266 mgmt_pending_remove(cmd);
5267 goto failed;
5268 }
5269
5270failed:
5271 hci_dev_unlock(hdev);
5272 return err;
5273}
5274
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005275static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5276 void *data, u16 len)
5277{
5278 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005279 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005280 int err;
5281
5282 BT_DBG("request for %s", hdev->name);
5283
Johan Hedbergb97109792014-06-24 14:00:28 +03005284 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005285 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5286 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005287
5288 hci_dev_lock(hdev);
5289
5290 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005291 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005292 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005293 changed = hci_dev_test_and_clear_flag(hdev,
5294 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005295
Johan Hedbergb97109792014-06-24 14:00:28 +03005296 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005297 use_changed = !hci_dev_test_and_set_flag(hdev,
5298 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005299 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005300 use_changed = hci_dev_test_and_clear_flag(hdev,
5301 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005302
5303 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005304 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005305 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5306 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5307 sizeof(mode), &mode);
5308 }
5309
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005310 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5311 if (err < 0)
5312 goto unlock;
5313
5314 if (changed)
5315 err = new_settings(hdev, sk);
5316
5317unlock:
5318 hci_dev_unlock(hdev);
5319 return err;
5320}
5321
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005322static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5323 u16 len)
5324{
5325 struct mgmt_cp_set_privacy *cp = cp_data;
5326 bool changed;
5327 int err;
5328
5329 BT_DBG("request for %s", hdev->name);
5330
5331 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005332 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5333 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005334
5335 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005336 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5337 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005338
5339 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005340 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5341 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005342
5343 hci_dev_lock(hdev);
5344
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005345 /* If user space supports this command it is also expected to
5346 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5347 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005348 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005349
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005350 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005351 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005352 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005353 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005354 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005355 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005356 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005357 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005358 }
5359
5360 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5361 if (err < 0)
5362 goto unlock;
5363
5364 if (changed)
5365 err = new_settings(hdev, sk);
5366
5367unlock:
5368 hci_dev_unlock(hdev);
5369 return err;
5370}
5371
Johan Hedberg41edf162014-02-18 10:19:35 +02005372static bool irk_is_valid(struct mgmt_irk_info *irk)
5373{
5374 switch (irk->addr.type) {
5375 case BDADDR_LE_PUBLIC:
5376 return true;
5377
5378 case BDADDR_LE_RANDOM:
5379 /* Two most significant bits shall be set */
5380 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5381 return false;
5382 return true;
5383 }
5384
5385 return false;
5386}
5387
5388static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5389 u16 len)
5390{
5391 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005392 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5393 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005394 u16 irk_count, expected_len;
5395 int i, err;
5396
5397 BT_DBG("request for %s", hdev->name);
5398
5399 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005400 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5401 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005402
5403 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005404 if (irk_count > max_irk_count) {
5405 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005406 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5407 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005408 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005409
5410 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5411 if (expected_len != len) {
5412 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005413 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005414 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5415 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005416 }
5417
5418 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5419
5420 for (i = 0; i < irk_count; i++) {
5421 struct mgmt_irk_info *key = &cp->irks[i];
5422
5423 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005424 return mgmt_cmd_status(sk, hdev->id,
5425 MGMT_OP_LOAD_IRKS,
5426 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005427 }
5428
5429 hci_dev_lock(hdev);
5430
5431 hci_smp_irks_clear(hdev);
5432
5433 for (i = 0; i < irk_count; i++) {
5434 struct mgmt_irk_info *irk = &cp->irks[i];
5435 u8 addr_type;
5436
5437 if (irk->addr.type == BDADDR_LE_PUBLIC)
5438 addr_type = ADDR_LE_DEV_PUBLIC;
5439 else
5440 addr_type = ADDR_LE_DEV_RANDOM;
5441
5442 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5443 BDADDR_ANY);
5444 }
5445
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005446 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005447
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005448 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005449
5450 hci_dev_unlock(hdev);
5451
5452 return err;
5453}
5454
Johan Hedberg3f706b72013-01-20 14:27:16 +02005455static bool ltk_is_valid(struct mgmt_ltk_info *key)
5456{
5457 if (key->master != 0x00 && key->master != 0x01)
5458 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005459
5460 switch (key->addr.type) {
5461 case BDADDR_LE_PUBLIC:
5462 return true;
5463
5464 case BDADDR_LE_RANDOM:
5465 /* Two most significant bits shall be set */
5466 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5467 return false;
5468 return true;
5469 }
5470
5471 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005472}
5473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005474static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005475 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005476{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005477 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005478 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5479 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005480 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005481 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005482
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005483 BT_DBG("request for %s", hdev->name);
5484
5485 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005486 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5487 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005488
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005489 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005490 if (key_count > max_key_count) {
5491 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005492 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5493 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005494 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005495
5496 expected_len = sizeof(*cp) + key_count *
5497 sizeof(struct mgmt_ltk_info);
5498 if (expected_len != len) {
5499 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005500 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005501 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5502 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005503 }
5504
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005505 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005506
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005507 for (i = 0; i < key_count; i++) {
5508 struct mgmt_ltk_info *key = &cp->keys[i];
5509
Johan Hedberg3f706b72013-01-20 14:27:16 +02005510 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005511 return mgmt_cmd_status(sk, hdev->id,
5512 MGMT_OP_LOAD_LONG_TERM_KEYS,
5513 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005514 }
5515
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005516 hci_dev_lock(hdev);
5517
5518 hci_smp_ltks_clear(hdev);
5519
5520 for (i = 0; i < key_count; i++) {
5521 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005522 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005523
5524 if (key->addr.type == BDADDR_LE_PUBLIC)
5525 addr_type = ADDR_LE_DEV_PUBLIC;
5526 else
5527 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005528
Johan Hedberg61b43352014-05-29 19:36:53 +03005529 switch (key->type) {
5530 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005531 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005532 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005533 break;
5534 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005535 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005536 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005537 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005538 case MGMT_LTK_P256_UNAUTH:
5539 authenticated = 0x00;
5540 type = SMP_LTK_P256;
5541 break;
5542 case MGMT_LTK_P256_AUTH:
5543 authenticated = 0x01;
5544 type = SMP_LTK_P256;
5545 break;
5546 case MGMT_LTK_P256_DEBUG:
5547 authenticated = 0x00;
5548 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005549 default:
5550 continue;
5551 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005552
Johan Hedberg35d70272014-02-19 14:57:47 +02005553 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005554 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005555 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005556 }
5557
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005558 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005559 NULL, 0);
5560
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005561 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005562
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005563 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005564}
5565
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005566static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005567{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005568 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005569 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005570 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005571
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005572 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005573
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005574 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005575 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005576 rp.tx_power = conn->tx_power;
5577 rp.max_tx_power = conn->max_tx_power;
5578 } else {
5579 rp.rssi = HCI_RSSI_INVALID;
5580 rp.tx_power = HCI_TX_POWER_INVALID;
5581 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005582 }
5583
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005584 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5585 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005586
5587 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005588 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005589
5590 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005591}
5592
Marcel Holtmann1904a852015-01-11 13:50:44 -08005593static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5594 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005595{
5596 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005597 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005598 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005599 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005600 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005601
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005602 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005603
5604 hci_dev_lock(hdev);
5605
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005606 /* Commands sent in request are either Read RSSI or Read Transmit Power
5607 * Level so we check which one was last sent to retrieve connection
5608 * handle. Both commands have handle as first parameter so it's safe to
5609 * cast data on the same command struct.
5610 *
5611 * First command sent is always Read RSSI and we fail only if it fails.
5612 * In other case we simply override error to indicate success as we
5613 * already remembered if TX power value is actually valid.
5614 */
5615 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5616 if (!cp) {
5617 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005618 status = MGMT_STATUS_SUCCESS;
5619 } else {
5620 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005621 }
5622
5623 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005624 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005625 goto unlock;
5626 }
5627
5628 handle = __le16_to_cpu(cp->handle);
5629 conn = hci_conn_hash_lookup_handle(hdev, handle);
5630 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005631 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005632 goto unlock;
5633 }
5634
Johan Hedberg333ae952015-03-17 13:48:47 +02005635 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005636 if (!cmd)
5637 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005638
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005639 cmd->cmd_complete(cmd, status);
5640 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005641
5642unlock:
5643 hci_dev_unlock(hdev);
5644}
5645
5646static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5647 u16 len)
5648{
5649 struct mgmt_cp_get_conn_info *cp = data;
5650 struct mgmt_rp_get_conn_info rp;
5651 struct hci_conn *conn;
5652 unsigned long conn_info_age;
5653 int err = 0;
5654
5655 BT_DBG("%s", hdev->name);
5656
5657 memset(&rp, 0, sizeof(rp));
5658 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5659 rp.addr.type = cp->addr.type;
5660
5661 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005662 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5663 MGMT_STATUS_INVALID_PARAMS,
5664 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005665
5666 hci_dev_lock(hdev);
5667
5668 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005669 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5670 MGMT_STATUS_NOT_POWERED, &rp,
5671 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005672 goto unlock;
5673 }
5674
5675 if (cp->addr.type == BDADDR_BREDR)
5676 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5677 &cp->addr.bdaddr);
5678 else
5679 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5680
5681 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005682 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5683 MGMT_STATUS_NOT_CONNECTED, &rp,
5684 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005685 goto unlock;
5686 }
5687
Johan Hedberg333ae952015-03-17 13:48:47 +02005688 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005689 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5690 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005691 goto unlock;
5692 }
5693
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005694 /* To avoid client trying to guess when to poll again for information we
5695 * calculate conn info age as random value between min/max set in hdev.
5696 */
5697 conn_info_age = hdev->conn_info_min_age +
5698 prandom_u32_max(hdev->conn_info_max_age -
5699 hdev->conn_info_min_age);
5700
5701 /* Query controller to refresh cached values if they are too old or were
5702 * never read.
5703 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005704 if (time_after(jiffies, conn->conn_info_timestamp +
5705 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005706 !conn->conn_info_timestamp) {
5707 struct hci_request req;
5708 struct hci_cp_read_tx_power req_txp_cp;
5709 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005710 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005711
5712 hci_req_init(&req, hdev);
5713 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5714 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5715 &req_rssi_cp);
5716
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005717 /* For LE links TX power does not change thus we don't need to
5718 * query for it once value is known.
5719 */
5720 if (!bdaddr_type_is_le(cp->addr.type) ||
5721 conn->tx_power == HCI_TX_POWER_INVALID) {
5722 req_txp_cp.handle = cpu_to_le16(conn->handle);
5723 req_txp_cp.type = 0x00;
5724 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5725 sizeof(req_txp_cp), &req_txp_cp);
5726 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005727
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005728 /* Max TX power needs to be read only once per connection */
5729 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5730 req_txp_cp.handle = cpu_to_le16(conn->handle);
5731 req_txp_cp.type = 0x01;
5732 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5733 sizeof(req_txp_cp), &req_txp_cp);
5734 }
5735
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005736 err = hci_req_run(&req, conn_info_refresh_complete);
5737 if (err < 0)
5738 goto unlock;
5739
5740 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5741 data, len);
5742 if (!cmd) {
5743 err = -ENOMEM;
5744 goto unlock;
5745 }
5746
5747 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005748 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005749 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005750
5751 conn->conn_info_timestamp = jiffies;
5752 } else {
5753 /* Cache is valid, just reply with values cached in hci_conn */
5754 rp.rssi = conn->rssi;
5755 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005756 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005757
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005758 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5759 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005760 }
5761
5762unlock:
5763 hci_dev_unlock(hdev);
5764 return err;
5765}
5766
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005767static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005768{
5769 struct hci_conn *conn = cmd->user_data;
5770 struct mgmt_rp_get_clock_info rp;
5771 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005772 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005773
5774 memset(&rp, 0, sizeof(rp));
5775 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5776
5777 if (status)
5778 goto complete;
5779
5780 hdev = hci_dev_get(cmd->index);
5781 if (hdev) {
5782 rp.local_clock = cpu_to_le32(hdev->clock);
5783 hci_dev_put(hdev);
5784 }
5785
5786 if (conn) {
5787 rp.piconet_clock = cpu_to_le32(conn->clock);
5788 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5789 }
5790
5791complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005792 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5793 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005794
5795 if (conn) {
5796 hci_conn_drop(conn);
5797 hci_conn_put(conn);
5798 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005799
5800 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005801}
5802
Marcel Holtmann1904a852015-01-11 13:50:44 -08005803static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005804{
Johan Hedberg95868422014-06-28 17:54:07 +03005805 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005806 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005807 struct hci_conn *conn;
5808
5809 BT_DBG("%s status %u", hdev->name, status);
5810
5811 hci_dev_lock(hdev);
5812
5813 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5814 if (!hci_cp)
5815 goto unlock;
5816
5817 if (hci_cp->which) {
5818 u16 handle = __le16_to_cpu(hci_cp->handle);
5819 conn = hci_conn_hash_lookup_handle(hdev, handle);
5820 } else {
5821 conn = NULL;
5822 }
5823
Johan Hedberg333ae952015-03-17 13:48:47 +02005824 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005825 if (!cmd)
5826 goto unlock;
5827
Johan Hedberg69487372014-12-05 13:36:07 +02005828 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005829 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005830
5831unlock:
5832 hci_dev_unlock(hdev);
5833}
5834
5835static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5836 u16 len)
5837{
5838 struct mgmt_cp_get_clock_info *cp = data;
5839 struct mgmt_rp_get_clock_info rp;
5840 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005841 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005842 struct hci_request req;
5843 struct hci_conn *conn;
5844 int err;
5845
5846 BT_DBG("%s", hdev->name);
5847
5848 memset(&rp, 0, sizeof(rp));
5849 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5850 rp.addr.type = cp->addr.type;
5851
5852 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005853 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5854 MGMT_STATUS_INVALID_PARAMS,
5855 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005856
5857 hci_dev_lock(hdev);
5858
5859 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005860 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5861 MGMT_STATUS_NOT_POWERED, &rp,
5862 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005863 goto unlock;
5864 }
5865
5866 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5867 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5868 &cp->addr.bdaddr);
5869 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005870 err = mgmt_cmd_complete(sk, hdev->id,
5871 MGMT_OP_GET_CLOCK_INFO,
5872 MGMT_STATUS_NOT_CONNECTED,
5873 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005874 goto unlock;
5875 }
5876 } else {
5877 conn = NULL;
5878 }
5879
5880 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5881 if (!cmd) {
5882 err = -ENOMEM;
5883 goto unlock;
5884 }
5885
Johan Hedberg69487372014-12-05 13:36:07 +02005886 cmd->cmd_complete = clock_info_cmd_complete;
5887
Johan Hedberg95868422014-06-28 17:54:07 +03005888 hci_req_init(&req, hdev);
5889
5890 memset(&hci_cp, 0, sizeof(hci_cp));
5891 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5892
5893 if (conn) {
5894 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005895 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005896
5897 hci_cp.handle = cpu_to_le16(conn->handle);
5898 hci_cp.which = 0x01; /* Piconet clock */
5899 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5900 }
5901
5902 err = hci_req_run(&req, get_clock_info_complete);
5903 if (err < 0)
5904 mgmt_pending_remove(cmd);
5905
5906unlock:
5907 hci_dev_unlock(hdev);
5908 return err;
5909}
5910
Johan Hedberg5a154e62014-12-19 22:26:02 +02005911static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5912{
5913 struct hci_conn *conn;
5914
5915 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5916 if (!conn)
5917 return false;
5918
5919 if (conn->dst_type != type)
5920 return false;
5921
5922 if (conn->state != BT_CONNECTED)
5923 return false;
5924
5925 return true;
5926}
5927
5928/* This function requires the caller holds hdev->lock */
5929static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5930 u8 addr_type, u8 auto_connect)
5931{
5932 struct hci_dev *hdev = req->hdev;
5933 struct hci_conn_params *params;
5934
5935 params = hci_conn_params_add(hdev, addr, addr_type);
5936 if (!params)
5937 return -EIO;
5938
5939 if (params->auto_connect == auto_connect)
5940 return 0;
5941
5942 list_del_init(&params->action);
5943
5944 switch (auto_connect) {
5945 case HCI_AUTO_CONN_DISABLED:
5946 case HCI_AUTO_CONN_LINK_LOSS:
5947 __hci_update_background_scan(req);
5948 break;
5949 case HCI_AUTO_CONN_REPORT:
5950 list_add(&params->action, &hdev->pend_le_reports);
5951 __hci_update_background_scan(req);
5952 break;
5953 case HCI_AUTO_CONN_DIRECT:
5954 case HCI_AUTO_CONN_ALWAYS:
5955 if (!is_connected(hdev, addr, addr_type)) {
5956 list_add(&params->action, &hdev->pend_le_conns);
5957 __hci_update_background_scan(req);
5958 }
5959 break;
5960 }
5961
5962 params->auto_connect = auto_connect;
5963
5964 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5965 auto_connect);
5966
5967 return 0;
5968}
5969
Marcel Holtmann8afef092014-06-29 22:28:34 +02005970static void device_added(struct sock *sk, struct hci_dev *hdev,
5971 bdaddr_t *bdaddr, u8 type, u8 action)
5972{
5973 struct mgmt_ev_device_added ev;
5974
5975 bacpy(&ev.addr.bdaddr, bdaddr);
5976 ev.addr.type = type;
5977 ev.action = action;
5978
5979 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5980}
5981
Marcel Holtmann1904a852015-01-11 13:50:44 -08005982static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005983{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005984 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005985
5986 BT_DBG("status 0x%02x", status);
5987
5988 hci_dev_lock(hdev);
5989
Johan Hedberg333ae952015-03-17 13:48:47 +02005990 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005991 if (!cmd)
5992 goto unlock;
5993
5994 cmd->cmd_complete(cmd, mgmt_status(status));
5995 mgmt_pending_remove(cmd);
5996
5997unlock:
5998 hci_dev_unlock(hdev);
5999}
6000
Marcel Holtmann2faade52014-06-29 19:44:03 +02006001static int add_device(struct sock *sk, struct hci_dev *hdev,
6002 void *data, u16 len)
6003{
6004 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006005 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006006 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006007 u8 auto_conn, addr_type;
6008 int err;
6009
6010 BT_DBG("%s", hdev->name);
6011
Johan Hedberg66593582014-07-09 12:59:14 +03006012 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02006013 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006014 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6015 MGMT_STATUS_INVALID_PARAMS,
6016 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006017
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006018 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006019 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6020 MGMT_STATUS_INVALID_PARAMS,
6021 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006022
Johan Hedberg5a154e62014-12-19 22:26:02 +02006023 hci_req_init(&req, hdev);
6024
Marcel Holtmann2faade52014-06-29 19:44:03 +02006025 hci_dev_lock(hdev);
6026
Johan Hedberg5a154e62014-12-19 22:26:02 +02006027 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
6028 if (!cmd) {
6029 err = -ENOMEM;
6030 goto unlock;
6031 }
6032
6033 cmd->cmd_complete = addr_cmd_complete;
6034
Johan Hedberg66593582014-07-09 12:59:14 +03006035 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006036 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03006037 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006038 err = cmd->cmd_complete(cmd,
6039 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006040 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006041 goto unlock;
6042 }
6043
6044 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
6045 cp->addr.type);
6046 if (err)
6047 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03006048
Johan Hedberg5a154e62014-12-19 22:26:02 +02006049 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006050
Johan Hedberg66593582014-07-09 12:59:14 +03006051 goto added;
6052 }
6053
Marcel Holtmann2faade52014-06-29 19:44:03 +02006054 if (cp->addr.type == BDADDR_LE_PUBLIC)
6055 addr_type = ADDR_LE_DEV_PUBLIC;
6056 else
6057 addr_type = ADDR_LE_DEV_RANDOM;
6058
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006059 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006060 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006061 else if (cp->action == 0x01)
6062 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006063 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006064 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006065
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006066 /* If the connection parameters don't exist for this device,
6067 * they will be created and configured with defaults.
6068 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006069 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006070 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006071 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006072 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006073 goto unlock;
6074 }
6075
Johan Hedberg66593582014-07-09 12:59:14 +03006076added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006077 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6078
Johan Hedberg5a154e62014-12-19 22:26:02 +02006079 err = hci_req_run(&req, add_device_complete);
6080 if (err < 0) {
6081 /* ENODATA means no HCI commands were needed (e.g. if
6082 * the adapter is powered off).
6083 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006084 if (err == -ENODATA)
6085 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006086 mgmt_pending_remove(cmd);
6087 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006088
6089unlock:
6090 hci_dev_unlock(hdev);
6091 return err;
6092}
6093
Marcel Holtmann8afef092014-06-29 22:28:34 +02006094static void device_removed(struct sock *sk, struct hci_dev *hdev,
6095 bdaddr_t *bdaddr, u8 type)
6096{
6097 struct mgmt_ev_device_removed ev;
6098
6099 bacpy(&ev.addr.bdaddr, bdaddr);
6100 ev.addr.type = type;
6101
6102 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6103}
6104
Marcel Holtmann1904a852015-01-11 13:50:44 -08006105static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006106{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006107 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006108
6109 BT_DBG("status 0x%02x", status);
6110
6111 hci_dev_lock(hdev);
6112
Johan Hedberg333ae952015-03-17 13:48:47 +02006113 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006114 if (!cmd)
6115 goto unlock;
6116
6117 cmd->cmd_complete(cmd, mgmt_status(status));
6118 mgmt_pending_remove(cmd);
6119
6120unlock:
6121 hci_dev_unlock(hdev);
6122}
6123
Marcel Holtmann2faade52014-06-29 19:44:03 +02006124static int remove_device(struct sock *sk, struct hci_dev *hdev,
6125 void *data, u16 len)
6126{
6127 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006128 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006129 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006130 int err;
6131
6132 BT_DBG("%s", hdev->name);
6133
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006134 hci_req_init(&req, hdev);
6135
Marcel Holtmann2faade52014-06-29 19:44:03 +02006136 hci_dev_lock(hdev);
6137
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006138 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6139 if (!cmd) {
6140 err = -ENOMEM;
6141 goto unlock;
6142 }
6143
6144 cmd->cmd_complete = addr_cmd_complete;
6145
Marcel Holtmann2faade52014-06-29 19:44:03 +02006146 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006147 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006148 u8 addr_type;
6149
Johan Hedberg66593582014-07-09 12:59:14 +03006150 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006151 err = cmd->cmd_complete(cmd,
6152 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006153 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006154 goto unlock;
6155 }
6156
Johan Hedberg66593582014-07-09 12:59:14 +03006157 if (cp->addr.type == BDADDR_BREDR) {
6158 err = hci_bdaddr_list_del(&hdev->whitelist,
6159 &cp->addr.bdaddr,
6160 cp->addr.type);
6161 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006162 err = cmd->cmd_complete(cmd,
6163 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006164 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006165 goto unlock;
6166 }
6167
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006168 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006169
Johan Hedberg66593582014-07-09 12:59:14 +03006170 device_removed(sk, hdev, &cp->addr.bdaddr,
6171 cp->addr.type);
6172 goto complete;
6173 }
6174
Marcel Holtmann2faade52014-06-29 19:44:03 +02006175 if (cp->addr.type == BDADDR_LE_PUBLIC)
6176 addr_type = ADDR_LE_DEV_PUBLIC;
6177 else
6178 addr_type = ADDR_LE_DEV_RANDOM;
6179
Johan Hedbergc71593d2014-07-02 17:37:28 +03006180 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6181 addr_type);
6182 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006183 err = cmd->cmd_complete(cmd,
6184 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006185 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006186 goto unlock;
6187 }
6188
6189 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006190 err = cmd->cmd_complete(cmd,
6191 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006192 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006193 goto unlock;
6194 }
6195
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006196 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006197 list_del(&params->list);
6198 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006199 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006200
6201 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006202 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006203 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006204 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006205
Marcel Holtmann2faade52014-06-29 19:44:03 +02006206 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006207 err = cmd->cmd_complete(cmd,
6208 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006209 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006210 goto unlock;
6211 }
6212
Johan Hedberg66593582014-07-09 12:59:14 +03006213 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6214 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6215 list_del(&b->list);
6216 kfree(b);
6217 }
6218
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006219 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006220
Johan Hedberg19de0822014-07-06 13:06:51 +03006221 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6222 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6223 continue;
6224 device_removed(sk, hdev, &p->addr, p->addr_type);
6225 list_del(&p->action);
6226 list_del(&p->list);
6227 kfree(p);
6228 }
6229
6230 BT_DBG("All LE connection parameters were removed");
6231
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006232 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006233 }
6234
Johan Hedberg66593582014-07-09 12:59:14 +03006235complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006236 err = hci_req_run(&req, remove_device_complete);
6237 if (err < 0) {
6238 /* ENODATA means no HCI commands were needed (e.g. if
6239 * the adapter is powered off).
6240 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006241 if (err == -ENODATA)
6242 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006243 mgmt_pending_remove(cmd);
6244 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006245
6246unlock:
6247 hci_dev_unlock(hdev);
6248 return err;
6249}
6250
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006251static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6252 u16 len)
6253{
6254 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006255 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6256 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006257 u16 param_count, expected_len;
6258 int i;
6259
6260 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006261 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6262 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006263
6264 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006265 if (param_count > max_param_count) {
6266 BT_ERR("load_conn_param: too big param_count value %u",
6267 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006268 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6269 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006270 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006271
6272 expected_len = sizeof(*cp) + param_count *
6273 sizeof(struct mgmt_conn_param);
6274 if (expected_len != len) {
6275 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6276 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006277 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6278 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006279 }
6280
6281 BT_DBG("%s param_count %u", hdev->name, param_count);
6282
6283 hci_dev_lock(hdev);
6284
6285 hci_conn_params_clear_disabled(hdev);
6286
6287 for (i = 0; i < param_count; i++) {
6288 struct mgmt_conn_param *param = &cp->params[i];
6289 struct hci_conn_params *hci_param;
6290 u16 min, max, latency, timeout;
6291 u8 addr_type;
6292
6293 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6294 param->addr.type);
6295
6296 if (param->addr.type == BDADDR_LE_PUBLIC) {
6297 addr_type = ADDR_LE_DEV_PUBLIC;
6298 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6299 addr_type = ADDR_LE_DEV_RANDOM;
6300 } else {
6301 BT_ERR("Ignoring invalid connection parameters");
6302 continue;
6303 }
6304
6305 min = le16_to_cpu(param->min_interval);
6306 max = le16_to_cpu(param->max_interval);
6307 latency = le16_to_cpu(param->latency);
6308 timeout = le16_to_cpu(param->timeout);
6309
6310 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6311 min, max, latency, timeout);
6312
6313 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6314 BT_ERR("Ignoring invalid connection parameters");
6315 continue;
6316 }
6317
6318 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6319 addr_type);
6320 if (!hci_param) {
6321 BT_ERR("Failed to add connection parameters");
6322 continue;
6323 }
6324
6325 hci_param->conn_min_interval = min;
6326 hci_param->conn_max_interval = max;
6327 hci_param->conn_latency = latency;
6328 hci_param->supervision_timeout = timeout;
6329 }
6330
6331 hci_dev_unlock(hdev);
6332
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006333 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6334 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006335}
6336
Marcel Holtmanndbece372014-07-04 18:11:55 +02006337static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6338 void *data, u16 len)
6339{
6340 struct mgmt_cp_set_external_config *cp = data;
6341 bool changed;
6342 int err;
6343
6344 BT_DBG("%s", hdev->name);
6345
6346 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006347 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6348 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006349
6350 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006351 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6352 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006353
6354 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006355 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6356 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006357
6358 hci_dev_lock(hdev);
6359
6360 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006361 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006362 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006363 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006364
6365 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6366 if (err < 0)
6367 goto unlock;
6368
6369 if (!changed)
6370 goto unlock;
6371
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006372 err = new_options(hdev, sk);
6373
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006374 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006375 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006376
Marcel Holtmann516018a2015-03-13 02:11:04 -07006377 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006378 hci_dev_set_flag(hdev, HCI_CONFIG);
6379 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006380
6381 queue_work(hdev->req_workqueue, &hdev->power_on);
6382 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006383 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006384 mgmt_index_added(hdev);
6385 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006386 }
6387
6388unlock:
6389 hci_dev_unlock(hdev);
6390 return err;
6391}
6392
Marcel Holtmann9713c172014-07-06 12:11:15 +02006393static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6394 void *data, u16 len)
6395{
6396 struct mgmt_cp_set_public_address *cp = data;
6397 bool changed;
6398 int err;
6399
6400 BT_DBG("%s", hdev->name);
6401
6402 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006403 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6404 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006405
6406 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006407 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6408 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006409
6410 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006411 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6412 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006413
6414 hci_dev_lock(hdev);
6415
6416 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6417 bacpy(&hdev->public_addr, &cp->bdaddr);
6418
6419 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6420 if (err < 0)
6421 goto unlock;
6422
6423 if (!changed)
6424 goto unlock;
6425
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006426 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006427 err = new_options(hdev, sk);
6428
6429 if (is_configured(hdev)) {
6430 mgmt_index_removed(hdev);
6431
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006432 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006433
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006434 hci_dev_set_flag(hdev, HCI_CONFIG);
6435 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006436
6437 queue_work(hdev->req_workqueue, &hdev->power_on);
6438 }
6439
6440unlock:
6441 hci_dev_unlock(hdev);
6442 return err;
6443}
6444
Marcel Holtmannbea41602015-03-14 22:43:17 -07006445static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6446 u8 data_len)
6447{
6448 eir[eir_len++] = sizeof(type) + data_len;
6449 eir[eir_len++] = type;
6450 memcpy(&eir[eir_len], data, data_len);
6451 eir_len += data_len;
6452
6453 return eir_len;
6454}
6455
Johan Hedberg40f66c02015-04-07 21:52:22 +03006456static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
6457 u16 opcode, struct sk_buff *skb)
6458{
6459 const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
6460 struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
6461 u8 *h192, *r192, *h256, *r256;
6462 struct mgmt_pending_cmd *cmd;
6463 u16 eir_len;
6464 int err;
6465
6466 BT_DBG("%s status %u", hdev->name, status);
6467
6468 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
6469 if (!cmd)
6470 return;
6471
6472 mgmt_cp = cmd->param;
6473
6474 if (status) {
6475 status = mgmt_status(status);
6476 eir_len = 0;
6477
6478 h192 = NULL;
6479 r192 = NULL;
6480 h256 = NULL;
6481 r256 = NULL;
6482 } else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
6483 struct hci_rp_read_local_oob_data *rp;
6484
6485 if (skb->len != sizeof(*rp)) {
6486 status = MGMT_STATUS_FAILED;
6487 eir_len = 0;
6488 } else {
6489 status = MGMT_STATUS_SUCCESS;
6490 rp = (void *)skb->data;
6491
6492 eir_len = 5 + 18 + 18;
6493 h192 = rp->hash;
6494 r192 = rp->rand;
6495 h256 = NULL;
6496 r256 = NULL;
6497 }
6498 } else {
6499 struct hci_rp_read_local_oob_ext_data *rp;
6500
6501 if (skb->len != sizeof(*rp)) {
6502 status = MGMT_STATUS_FAILED;
6503 eir_len = 0;
6504 } else {
6505 status = MGMT_STATUS_SUCCESS;
6506 rp = (void *)skb->data;
6507
6508 if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
6509 eir_len = 5 + 18 + 18;
6510 h192 = NULL;
6511 r192 = NULL;
6512 } else {
6513 eir_len = 5 + 18 + 18 + 18 + 18;
6514 h192 = rp->hash192;
6515 r192 = rp->rand192;
6516 }
6517
6518 h256 = rp->hash256;
6519 r256 = rp->rand256;
6520 }
6521 }
6522
6523 mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
6524 if (!mgmt_rp)
6525 goto done;
6526
6527 if (status)
6528 goto send_rsp;
6529
6530 eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
6531 hdev->dev_class, 3);
6532
6533 if (h192 && r192) {
6534 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6535 EIR_SSP_HASH_C192, h192, 16);
6536 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6537 EIR_SSP_RAND_R192, r192, 16);
6538 }
6539
6540 if (h256 && r256) {
6541 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6542 EIR_SSP_HASH_C256, h256, 16);
6543 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6544 EIR_SSP_RAND_R256, r256, 16);
6545 }
6546
6547send_rsp:
6548 mgmt_rp->type = mgmt_cp->type;
6549 mgmt_rp->eir_len = cpu_to_le16(eir_len);
6550
6551 err = mgmt_cmd_complete(cmd->sk, hdev->id,
6552 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
6553 mgmt_rp, sizeof(*mgmt_rp) + eir_len);
6554 if (err < 0 || status)
6555 goto done;
6556
6557 hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
6558
6559 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6560 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
6561 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
6562done:
6563 kfree(mgmt_rp);
6564 mgmt_pending_remove(cmd);
6565}
6566
6567static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
6568 struct mgmt_cp_read_local_oob_ext_data *cp)
6569{
6570 struct mgmt_pending_cmd *cmd;
6571 struct hci_request req;
6572 int err;
6573
6574 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
6575 cp, sizeof(*cp));
6576 if (!cmd)
6577 return -ENOMEM;
6578
6579 hci_req_init(&req, hdev);
6580
6581 if (bredr_sc_enabled(hdev))
6582 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
6583 else
6584 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
6585
6586 err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
6587 if (err < 0) {
6588 mgmt_pending_remove(cmd);
6589 return err;
6590 }
6591
6592 return 0;
6593}
6594
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006595static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6596 void *data, u16 data_len)
6597{
6598 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6599 struct mgmt_rp_read_local_oob_ext_data *rp;
6600 size_t rp_len;
6601 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006602 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006603 int err;
6604
6605 BT_DBG("%s", hdev->name);
6606
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006607 if (hdev_is_powered(hdev)) {
6608 switch (cp->type) {
6609 case BIT(BDADDR_BREDR):
6610 status = mgmt_bredr_support(hdev);
6611 if (status)
6612 eir_len = 0;
6613 else
6614 eir_len = 5;
6615 break;
6616 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6617 status = mgmt_le_support(hdev);
6618 if (status)
6619 eir_len = 0;
6620 else
6621 eir_len = 9 + 3 + 18 + 18 + 3;
6622 break;
6623 default:
6624 status = MGMT_STATUS_INVALID_PARAMS;
6625 eir_len = 0;
6626 break;
6627 }
6628 } else {
6629 status = MGMT_STATUS_NOT_POWERED;
6630 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006631 }
6632
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006633 rp_len = sizeof(*rp) + eir_len;
6634 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006635 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006636 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006637
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006638 if (status)
6639 goto complete;
6640
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006641 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006642
6643 eir_len = 0;
6644 switch (cp->type) {
6645 case BIT(BDADDR_BREDR):
Johan Hedberg40f66c02015-04-07 21:52:22 +03006646 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
6647 err = read_local_ssp_oob_req(hdev, sk, cp);
6648 hci_dev_unlock(hdev);
6649 if (!err)
6650 goto done;
6651
6652 status = MGMT_STATUS_FAILED;
6653 goto complete;
6654 } else {
6655 eir_len = eir_append_data(rp->eir, eir_len,
6656 EIR_CLASS_OF_DEV,
6657 hdev->dev_class, 3);
6658 }
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006659 break;
6660 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006661 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6662 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006663 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006664 status = MGMT_STATUS_FAILED;
6665 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006666 }
6667
Marcel Holtmanne2135682015-04-02 12:00:58 -07006668 /* This should return the active RPA, but since the RPA
6669 * is only programmed on demand, it is really hard to fill
6670 * this in at the moment. For now disallow retrieving
6671 * local out-of-band data when privacy is in use.
6672 *
6673 * Returning the identity address will not help here since
6674 * pairing happens before the identity resolving key is
6675 * known and thus the connection establishment happens
6676 * based on the RPA and not the identity address.
6677 */
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006678 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
Marcel Holtmanne2135682015-04-02 12:00:58 -07006679 hci_dev_unlock(hdev);
6680 status = MGMT_STATUS_REJECTED;
6681 goto complete;
6682 }
6683
6684 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6685 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6686 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6687 bacmp(&hdev->static_addr, BDADDR_ANY))) {
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006688 memcpy(addr, &hdev->static_addr, 6);
6689 addr[6] = 0x01;
6690 } else {
6691 memcpy(addr, &hdev->bdaddr, 6);
6692 addr[6] = 0x00;
6693 }
6694
6695 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6696 addr, sizeof(addr));
6697
6698 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6699 role = 0x02;
6700 else
6701 role = 0x01;
6702
6703 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6704 &role, sizeof(role));
6705
Marcel Holtmann5082a592015-03-16 12:39:00 -07006706 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6707 eir_len = eir_append_data(rp->eir, eir_len,
6708 EIR_LE_SC_CONFIRM,
6709 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006710
Marcel Holtmann5082a592015-03-16 12:39:00 -07006711 eir_len = eir_append_data(rp->eir, eir_len,
6712 EIR_LE_SC_RANDOM,
6713 rand, sizeof(rand));
6714 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006715
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006716 flags = get_adv_discov_flags(hdev);
6717
6718 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6719 flags |= LE_AD_NO_BREDR;
6720
6721 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6722 &flags, sizeof(flags));
6723 break;
6724 }
6725
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006726 hci_dev_unlock(hdev);
6727
Marcel Holtmann72000df2015-03-16 16:11:21 -07006728 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6729
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006730 status = MGMT_STATUS_SUCCESS;
6731
6732complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006733 rp->type = cp->type;
6734 rp->eir_len = cpu_to_le16(eir_len);
6735
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006736 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006737 status, rp, sizeof(*rp) + eir_len);
6738 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006739 goto done;
6740
6741 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6742 rp, sizeof(*rp) + eir_len,
6743 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006744
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006745done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006746 kfree(rp);
6747
6748 return err;
6749}
6750
Arman Uguray089fa8c2015-03-25 18:53:45 -07006751static u32 get_supported_adv_flags(struct hci_dev *hdev)
6752{
6753 u32 flags = 0;
6754
6755 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6756 flags |= MGMT_ADV_FLAG_DISCOV;
6757 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6758 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6759
6760 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6761 flags |= MGMT_ADV_FLAG_TX_POWER;
6762
6763 return flags;
6764}
6765
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006766static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6767 void *data, u16 data_len)
6768{
6769 struct mgmt_rp_read_adv_features *rp;
6770 size_t rp_len;
Florian Grandel286e0c82015-06-18 03:16:38 +02006771 int err, i;
Arman Uguray24b4f382015-03-23 15:57:12 -07006772 bool instance;
Florian Grandel286e0c82015-06-18 03:16:38 +02006773 struct adv_info *adv_instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006774 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006775
6776 BT_DBG("%s", hdev->name);
6777
Arman Uguray089fa8c2015-03-25 18:53:45 -07006778 if (!lmp_le_capable(hdev))
6779 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6780 MGMT_STATUS_REJECTED);
6781
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006782 hci_dev_lock(hdev);
6783
6784 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006785
Arman Uguray24b4f382015-03-23 15:57:12 -07006786 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6787 if (instance)
Florian Grandel286e0c82015-06-18 03:16:38 +02006788 rp_len += hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006789
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006790 rp = kmalloc(rp_len, GFP_ATOMIC);
6791 if (!rp) {
6792 hci_dev_unlock(hdev);
6793 return -ENOMEM;
6794 }
6795
Arman Uguray089fa8c2015-03-25 18:53:45 -07006796 supported_flags = get_supported_adv_flags(hdev);
6797
6798 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006799 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6800 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Florian Grandeld2609b32015-06-18 03:16:34 +02006801 rp->max_instances = HCI_MAX_ADV_INSTANCES;
Arman Uguray24b4f382015-03-23 15:57:12 -07006802
Arman Uguray24b4f382015-03-23 15:57:12 -07006803 if (instance) {
Florian Grandel286e0c82015-06-18 03:16:38 +02006804 i = 0;
6805 list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
6806 if (i >= hdev->adv_instance_cnt)
6807 break;
6808
6809 rp->instance[i] = adv_instance->instance;
6810 i++;
6811 }
6812 rp->num_instances = hdev->adv_instance_cnt;
Arman Uguray24b4f382015-03-23 15:57:12 -07006813 } else {
6814 rp->num_instances = 0;
6815 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006816
6817 hci_dev_unlock(hdev);
6818
6819 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6820 MGMT_STATUS_SUCCESS, rp, rp_len);
6821
6822 kfree(rp);
6823
6824 return err;
6825}
6826
Arman Uguray4117ed72015-03-23 15:57:14 -07006827static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006828 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006829{
Arman Uguray4117ed72015-03-23 15:57:14 -07006830 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006831 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006832 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006833 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006834 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6835 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006836
Arman Uguray807ec772015-03-25 18:53:42 -07006837 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006838 flags_managed = true;
6839 max_len -= 3;
6840 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006841
Arman Uguray5507e352015-03-25 18:53:44 -07006842 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6843 tx_power_managed = true;
6844 max_len -= 3;
6845 }
6846
Arman Uguray4117ed72015-03-23 15:57:14 -07006847 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006848 return false;
6849
Arman Uguray4117ed72015-03-23 15:57:14 -07006850 /* Make sure that the data is correctly formatted. */
6851 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6852 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006853
Arman Ugurayb44133f2015-03-25 18:53:41 -07006854 if (flags_managed && data[i + 1] == EIR_FLAGS)
6855 return false;
6856
Arman Uguray5507e352015-03-25 18:53:44 -07006857 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6858 return false;
6859
Arman Uguray24b4f382015-03-23 15:57:12 -07006860 /* If the current field length would exceed the total data
6861 * length, then it's invalid.
6862 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006863 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006864 return false;
6865 }
6866
6867 return true;
6868}
6869
Arman Uguray24b4f382015-03-23 15:57:12 -07006870static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6871 u16 opcode)
6872{
6873 struct mgmt_pending_cmd *cmd;
6874 struct mgmt_rp_add_advertising rp;
6875
6876 BT_DBG("status %d", status);
6877
6878 hci_dev_lock(hdev);
6879
6880 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6881
6882 if (status) {
6883 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6884 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6885 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6886 }
6887
6888 if (!cmd)
6889 goto unlock;
6890
6891 rp.instance = 0x01;
6892
6893 if (status)
6894 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6895 mgmt_status(status));
6896 else
6897 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6898 mgmt_status(status), &rp, sizeof(rp));
6899
6900 mgmt_pending_remove(cmd);
6901
6902unlock:
6903 hci_dev_unlock(hdev);
6904}
6905
Florian Grandel5d900e42015-06-18 03:16:35 +02006906void mgmt_adv_timeout_expired(struct hci_dev *hdev)
Arman Uguray912098a2015-03-23 15:57:15 -07006907{
Florian Grandel5d900e42015-06-18 03:16:35 +02006908 hdev->adv_instance_timeout = 0;
Arman Uguray912098a2015-03-23 15:57:15 -07006909
6910 hci_dev_lock(hdev);
6911 clear_adv_instance(hdev);
6912 hci_dev_unlock(hdev);
6913}
6914
Arman Uguray24b4f382015-03-23 15:57:12 -07006915static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6916 void *data, u16 data_len)
6917{
6918 struct mgmt_cp_add_advertising *cp = data;
6919 struct mgmt_rp_add_advertising rp;
6920 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006921 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006922 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006923 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006924 int err;
6925 struct mgmt_pending_cmd *cmd;
6926 struct hci_request req;
6927
6928 BT_DBG("%s", hdev->name);
6929
6930 status = mgmt_le_support(hdev);
6931 if (status)
6932 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6933 status);
6934
6935 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006936 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006937
Arman Uguray089fa8c2015-03-25 18:53:45 -07006938 /* The current implementation only supports adding one instance and only
6939 * a subset of the specified flags.
6940 */
6941 supported_flags = get_supported_adv_flags(hdev);
6942 if (cp->instance != 0x01 || (flags & ~supported_flags))
Arman Uguray24b4f382015-03-23 15:57:12 -07006943 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6944 MGMT_STATUS_INVALID_PARAMS);
6945
6946 hci_dev_lock(hdev);
6947
Arman Uguray912098a2015-03-23 15:57:15 -07006948 if (timeout && !hdev_is_powered(hdev)) {
6949 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6950 MGMT_STATUS_REJECTED);
6951 goto unlock;
6952 }
6953
Arman Uguray24b4f382015-03-23 15:57:12 -07006954 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006955 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006956 pending_find(MGMT_OP_SET_LE, hdev)) {
6957 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6958 MGMT_STATUS_BUSY);
6959 goto unlock;
6960 }
6961
Arman Ugurayb44133f2015-03-25 18:53:41 -07006962 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006963 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006964 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006965 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6966 MGMT_STATUS_INVALID_PARAMS);
6967 goto unlock;
6968 }
6969
6970 hdev->adv_instance.flags = flags;
6971 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6972 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6973
6974 if (cp->adv_data_len)
6975 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6976
6977 if (cp->scan_rsp_len)
6978 memcpy(hdev->adv_instance.scan_rsp_data,
6979 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6980
Florian Grandel5d900e42015-06-18 03:16:35 +02006981 if (hdev->adv_instance_timeout)
6982 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07006983
Florian Grandel5d900e42015-06-18 03:16:35 +02006984 hdev->adv_instance_timeout = timeout;
Arman Uguray912098a2015-03-23 15:57:15 -07006985
6986 if (timeout)
6987 queue_delayed_work(hdev->workqueue,
Florian Grandel5d900e42015-06-18 03:16:35 +02006988 &hdev->adv_instance_expire,
Arman Uguray912098a2015-03-23 15:57:15 -07006989 msecs_to_jiffies(timeout * 1000));
6990
Arman Uguray24b4f382015-03-23 15:57:12 -07006991 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6992 advertising_added(sk, hdev, 1);
6993
6994 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6995 * we have no HCI communication to make. Simply return.
6996 */
6997 if (!hdev_is_powered(hdev) ||
6998 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6999 rp.instance = 0x01;
7000 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7001 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7002 goto unlock;
7003 }
7004
7005 /* We're good to go, update advertising data, parameters, and start
7006 * advertising.
7007 */
7008 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
7009 data_len);
7010 if (!cmd) {
7011 err = -ENOMEM;
7012 goto unlock;
7013 }
7014
7015 hci_req_init(&req, hdev);
7016
7017 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07007018 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007019 enable_advertising(&req);
7020
7021 err = hci_req_run(&req, add_advertising_complete);
7022 if (err < 0)
7023 mgmt_pending_remove(cmd);
7024
7025unlock:
7026 hci_dev_unlock(hdev);
7027
7028 return err;
7029}
7030
Arman Ugurayda9293352015-03-23 15:57:13 -07007031static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
7032 u16 opcode)
7033{
7034 struct mgmt_pending_cmd *cmd;
7035 struct mgmt_rp_remove_advertising rp;
7036
7037 BT_DBG("status %d", status);
7038
7039 hci_dev_lock(hdev);
7040
7041 /* A failure status here only means that we failed to disable
7042 * advertising. Otherwise, the advertising instance has been removed,
7043 * so report success.
7044 */
7045 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
7046 if (!cmd)
7047 goto unlock;
7048
7049 rp.instance = 1;
7050
7051 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
7052 &rp, sizeof(rp));
7053 mgmt_pending_remove(cmd);
7054
7055unlock:
7056 hci_dev_unlock(hdev);
7057}
7058
7059static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
7060 void *data, u16 data_len)
7061{
7062 struct mgmt_cp_remove_advertising *cp = data;
7063 struct mgmt_rp_remove_advertising rp;
7064 int err;
7065 struct mgmt_pending_cmd *cmd;
7066 struct hci_request req;
7067
7068 BT_DBG("%s", hdev->name);
7069
7070 /* The current implementation only allows modifying instance no 1. A
7071 * value of 0 indicates that all instances should be cleared.
7072 */
7073 if (cp->instance > 1)
7074 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7075 MGMT_STATUS_INVALID_PARAMS);
7076
7077 hci_dev_lock(hdev);
7078
7079 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
7080 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
7081 pending_find(MGMT_OP_SET_LE, hdev)) {
7082 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7083 MGMT_STATUS_BUSY);
7084 goto unlock;
7085 }
7086
7087 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
7088 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7089 MGMT_STATUS_INVALID_PARAMS);
7090 goto unlock;
7091 }
7092
Florian Grandel5d900e42015-06-18 03:16:35 +02007093 if (hdev->adv_instance_timeout)
7094 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07007095
Arman Ugurayda9293352015-03-23 15:57:13 -07007096 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
7097
7098 advertising_removed(sk, hdev, 1);
7099
7100 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
7101
7102 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7103 * we have no HCI communication to make. Simply return.
7104 */
7105 if (!hdev_is_powered(hdev) ||
7106 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7107 rp.instance = 1;
7108 err = mgmt_cmd_complete(sk, hdev->id,
7109 MGMT_OP_REMOVE_ADVERTISING,
7110 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7111 goto unlock;
7112 }
7113
7114 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
7115 data_len);
7116 if (!cmd) {
7117 err = -ENOMEM;
7118 goto unlock;
7119 }
7120
7121 hci_req_init(&req, hdev);
7122 disable_advertising(&req);
7123
7124 err = hci_req_run(&req, remove_advertising_complete);
7125 if (err < 0)
7126 mgmt_pending_remove(cmd);
7127
7128unlock:
7129 hci_dev_unlock(hdev);
7130
7131 return err;
7132}
7133
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007134static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007135 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007136 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007137 HCI_MGMT_NO_HDEV |
7138 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007139 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007140 HCI_MGMT_NO_HDEV |
7141 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007142 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007143 HCI_MGMT_NO_HDEV |
7144 HCI_MGMT_UNTRUSTED },
7145 { read_controller_info, MGMT_READ_INFO_SIZE,
7146 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007147 { set_powered, MGMT_SETTING_SIZE },
7148 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7149 { set_connectable, MGMT_SETTING_SIZE },
7150 { set_fast_connectable, MGMT_SETTING_SIZE },
7151 { set_bondable, MGMT_SETTING_SIZE },
7152 { set_link_security, MGMT_SETTING_SIZE },
7153 { set_ssp, MGMT_SETTING_SIZE },
7154 { set_hs, MGMT_SETTING_SIZE },
7155 { set_le, MGMT_SETTING_SIZE },
7156 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7157 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7158 { add_uuid, MGMT_ADD_UUID_SIZE },
7159 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007160 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7161 HCI_MGMT_VAR_LEN },
7162 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7163 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007164 { disconnect, MGMT_DISCONNECT_SIZE },
7165 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7166 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7167 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7168 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7169 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7170 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7171 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7172 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7173 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7174 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7175 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007176 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7177 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7178 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007179 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7180 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7181 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7182 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7183 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7184 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7185 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7186 { set_advertising, MGMT_SETTING_SIZE },
7187 { set_bredr, MGMT_SETTING_SIZE },
7188 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7189 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7190 { set_secure_conn, MGMT_SETTING_SIZE },
7191 { set_debug_keys, MGMT_SETTING_SIZE },
7192 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007193 { load_irks, MGMT_LOAD_IRKS_SIZE,
7194 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007195 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7196 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7197 { add_device, MGMT_ADD_DEVICE_SIZE },
7198 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007199 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7200 HCI_MGMT_VAR_LEN },
7201 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007202 HCI_MGMT_NO_HDEV |
7203 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007204 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007205 HCI_MGMT_UNCONFIGURED |
7206 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007207 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7208 HCI_MGMT_UNCONFIGURED },
7209 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7210 HCI_MGMT_UNCONFIGURED },
7211 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7212 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007213 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007214 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007215 HCI_MGMT_NO_HDEV |
7216 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007217 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007218 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7219 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007220 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007221};
7222
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007223void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007224{
Marcel Holtmannced85542015-03-14 19:27:56 -07007225 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007226
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007227 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7228 return;
7229
Marcel Holtmannf9207332015-03-14 19:27:55 -07007230 switch (hdev->dev_type) {
7231 case HCI_BREDR:
7232 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7233 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7234 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007235 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007236 } else {
7237 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7238 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007239 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007240 }
7241 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007242 case HCI_AMP:
7243 ev.type = 0x02;
7244 break;
7245 default:
7246 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007247 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007248
7249 ev.bus = hdev->bus;
7250
7251 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7252 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007253}
7254
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007255void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007256{
Marcel Holtmannced85542015-03-14 19:27:56 -07007257 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007258 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007259
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007260 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7261 return;
7262
Marcel Holtmannf9207332015-03-14 19:27:55 -07007263 switch (hdev->dev_type) {
7264 case HCI_BREDR:
7265 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007266
Marcel Holtmannf9207332015-03-14 19:27:55 -07007267 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7268 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7269 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007270 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007271 } else {
7272 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7273 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007274 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007275 }
7276 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007277 case HCI_AMP:
7278 ev.type = 0x02;
7279 break;
7280 default:
7281 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007282 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007283
7284 ev.bus = hdev->bus;
7285
7286 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7287 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007288}
7289
Andre Guedes6046dc32014-02-26 20:21:51 -03007290/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007291static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007292{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007293 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007294 struct hci_conn_params *p;
7295
7296 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007297 /* Needed for AUTO_OFF case where might not "really"
7298 * have been powered off.
7299 */
7300 list_del_init(&p->action);
7301
7302 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007303 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007304 case HCI_AUTO_CONN_ALWAYS:
7305 list_add(&p->action, &hdev->pend_le_conns);
7306 break;
7307 case HCI_AUTO_CONN_REPORT:
7308 list_add(&p->action, &hdev->pend_le_reports);
7309 break;
7310 default:
7311 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007312 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007313 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007314
Johan Hedberg2cf22212014-12-19 22:26:00 +02007315 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007316}
7317
Marcel Holtmann1904a852015-01-11 13:50:44 -08007318static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007319{
7320 struct cmd_lookup match = { NULL, hdev };
7321
7322 BT_DBG("status 0x%02x", status);
7323
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007324 if (!status) {
7325 /* Register the available SMP channels (BR/EDR and LE) only
7326 * when successfully powering on the controller. This late
7327 * registration is required so that LE SMP can clearly
7328 * decide if the public address or static address is used.
7329 */
7330 smp_register(hdev);
7331 }
7332
Johan Hedberg229ab392013-03-15 17:06:53 -05007333 hci_dev_lock(hdev);
7334
7335 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7336
7337 new_settings(hdev, match.sk);
7338
7339 hci_dev_unlock(hdev);
7340
7341 if (match.sk)
7342 sock_put(match.sk);
7343}
7344
Johan Hedberg70da6242013-03-15 17:06:51 -05007345static int powered_update_hci(struct hci_dev *hdev)
7346{
Johan Hedberg890ea892013-03-15 17:06:52 -05007347 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007348 u8 link_sec;
7349
Johan Hedberg890ea892013-03-15 17:06:52 -05007350 hci_req_init(&req, hdev);
7351
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007352 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007353 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007354 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007355
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007356 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007357
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007358 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7359 u8 support = 0x01;
7360
7361 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7362 sizeof(support), &support);
7363 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007364 }
7365
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007366 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007367 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007368 struct hci_cp_write_le_host_supported cp;
7369
Marcel Holtmann32226e42014-07-24 20:04:16 +02007370 cp.le = 0x01;
7371 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007372
7373 /* Check first if we already have the right
7374 * host state (host features set)
7375 */
7376 if (cp.le != lmp_host_le_capable(hdev) ||
7377 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007378 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7379 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007380 }
7381
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007382 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007383 /* Make sure the controller has a good default for
7384 * advertising data. This also applies to the case
7385 * where BR/EDR was toggled during the AUTO_OFF phase.
7386 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007387 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007388 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007389 update_scan_rsp_data(&req);
7390 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007391
Arman Uguray24b4f382015-03-23 15:57:12 -07007392 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7393 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007394 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007395
7396 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007397 }
7398
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007399 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007400 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007401 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7402 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007403
7404 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007405 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007406 write_fast_connectable(&req, true);
7407 else
7408 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007409 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007410 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007411 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007412 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007413 }
7414
Johan Hedberg229ab392013-03-15 17:06:53 -05007415 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007416}
7417
Johan Hedberg744cf192011-11-08 20:40:14 +02007418int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007419{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007420 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007421 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007422 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007423
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007424 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007425 return 0;
7426
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007427 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007428 if (powered_update_hci(hdev) == 0)
7429 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007430
Johan Hedberg229ab392013-03-15 17:06:53 -05007431 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7432 &match);
7433 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007434 }
7435
Johan Hedberg229ab392013-03-15 17:06:53 -05007436 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007437
7438 /* If the power off is because of hdev unregistration let
7439 * use the appropriate INVALID_INDEX status. Otherwise use
7440 * NOT_POWERED. We cover both scenarios here since later in
7441 * mgmt_index_removed() any hci_conn callbacks will have already
7442 * been triggered, potentially causing misleading DISCONNECTED
7443 * status responses.
7444 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007445 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007446 status = MGMT_STATUS_INVALID_INDEX;
7447 else
7448 status = MGMT_STATUS_NOT_POWERED;
7449
7450 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007451
7452 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007453 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7454 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007455
7456new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007457 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007458
7459 if (match.sk)
7460 sock_put(match.sk);
7461
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007462 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007463}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007464
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007465void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007466{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007467 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007468 u8 status;
7469
Johan Hedberg333ae952015-03-17 13:48:47 +02007470 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007471 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007472 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007473
7474 if (err == -ERFKILL)
7475 status = MGMT_STATUS_RFKILLED;
7476 else
7477 status = MGMT_STATUS_FAILED;
7478
Johan Hedberga69e8372015-03-06 21:08:53 +02007479 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007480
7481 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007482}
7483
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007484void mgmt_discoverable_timeout(struct hci_dev *hdev)
7485{
7486 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007487
7488 hci_dev_lock(hdev);
7489
7490 /* When discoverable timeout triggers, then just make sure
7491 * the limited discoverable flag is cleared. Even in the case
7492 * of a timeout triggered from general discoverable, it is
7493 * safe to unconditionally clear the flag.
7494 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007495 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7496 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007497
7498 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007499 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007500 u8 scan = SCAN_PAGE;
7501 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7502 sizeof(scan), &scan);
7503 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007504 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007505
7506 /* Advertising instances don't use the global discoverable setting, so
7507 * only update AD if advertising was enabled using Set Advertising.
7508 */
7509 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7510 update_adv_data(&req);
7511
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007512 hci_req_run(&req, NULL);
7513
7514 hdev->discov_timeout = 0;
7515
Johan Hedberg9a43e252013-10-20 19:00:07 +03007516 new_settings(hdev, NULL);
7517
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007518 hci_dev_unlock(hdev);
7519}
7520
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007521void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7522 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007523{
Johan Hedberg86742e12011-11-07 23:13:38 +02007524 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007525
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007526 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007527
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007528 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007529 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007530 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007531 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007532 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007533 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007534
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007535 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007536}
Johan Hedbergf7520542011-01-20 12:34:39 +02007537
Johan Hedbergd7b25452014-05-23 13:19:53 +03007538static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7539{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007540 switch (ltk->type) {
7541 case SMP_LTK:
7542 case SMP_LTK_SLAVE:
7543 if (ltk->authenticated)
7544 return MGMT_LTK_AUTHENTICATED;
7545 return MGMT_LTK_UNAUTHENTICATED;
7546 case SMP_LTK_P256:
7547 if (ltk->authenticated)
7548 return MGMT_LTK_P256_AUTH;
7549 return MGMT_LTK_P256_UNAUTH;
7550 case SMP_LTK_P256_DEBUG:
7551 return MGMT_LTK_P256_DEBUG;
7552 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007553
7554 return MGMT_LTK_UNAUTHENTICATED;
7555}
7556
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007557void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007558{
7559 struct mgmt_ev_new_long_term_key ev;
7560
7561 memset(&ev, 0, sizeof(ev));
7562
Marcel Holtmann5192d302014-02-19 17:11:58 -08007563 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007564 * without providing an identity resolving key don't require
Marcel Holtmann5192d302014-02-19 17:11:58 -08007565 * to store long term keys. Their addresses will change the
7566 * next time around.
7567 *
7568 * Only when a remote device provides an identity address
7569 * make sure the long term key is stored. If the remote
7570 * identity is known, the long term keys are internally
7571 * mapped to the identity address. So allow static random
7572 * and public addresses here.
7573 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007574 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7575 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7576 ev.store_hint = 0x00;
7577 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007578 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007579
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007580 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007581 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007582 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007583 ev.key.enc_size = key->enc_size;
7584 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007585 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007586
Johan Hedberg2ceba532014-06-16 19:25:16 +03007587 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007588 ev.key.master = 1;
7589
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007590 /* Make sure we copy only the significant bytes based on the
7591 * encryption key size, and set the rest of the value to zeroes.
7592 */
7593 memcpy(ev.key.val, key->val, sizeof(key->enc_size));
7594 memset(ev.key.val + key->enc_size, 0,
7595 sizeof(ev.key.val) - key->enc_size);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007596
Marcel Holtmann083368f2013-10-15 14:26:29 -07007597 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007598}
7599
Johan Hedberg95fbac82014-02-19 15:18:31 +02007600void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7601{
7602 struct mgmt_ev_new_irk ev;
7603
7604 memset(&ev, 0, sizeof(ev));
7605
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007606 /* For identity resolving keys from devices that are already
7607 * using a public address or static random address, do not
7608 * ask for storing this key. The identity resolving key really
Florian Grandelf72186d2015-05-26 03:31:09 +02007609 * is only mandatory for devices using resolvable random
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007610 * addresses.
7611 *
7612 * Storing all identity resolving keys has the downside that
7613 * they will be also loaded on next boot of they system. More
7614 * identity resolving keys, means more time during scanning is
7615 * needed to actually resolve these addresses.
7616 */
7617 if (bacmp(&irk->rpa, BDADDR_ANY))
7618 ev.store_hint = 0x01;
7619 else
7620 ev.store_hint = 0x00;
7621
Johan Hedberg95fbac82014-02-19 15:18:31 +02007622 bacpy(&ev.rpa, &irk->rpa);
7623 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7624 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7625 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7626
7627 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7628}
7629
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007630void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7631 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007632{
7633 struct mgmt_ev_new_csrk ev;
7634
7635 memset(&ev, 0, sizeof(ev));
7636
7637 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007638 * without providing an identity resolving key don't require
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007639 * to store signature resolving keys. Their addresses will change
7640 * the next time around.
7641 *
7642 * Only when a remote device provides an identity address
7643 * make sure the signature resolving key is stored. So allow
7644 * static random and public addresses here.
7645 */
7646 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7647 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7648 ev.store_hint = 0x00;
7649 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007650 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007651
7652 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7653 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007654 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007655 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7656
7657 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7658}
7659
Andre Guedesffb5a8272014-07-01 18:10:11 -03007660void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007661 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7662 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007663{
7664 struct mgmt_ev_new_conn_param ev;
7665
Johan Hedbergc103aea2014-07-02 17:37:34 +03007666 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7667 return;
7668
Andre Guedesffb5a8272014-07-01 18:10:11 -03007669 memset(&ev, 0, sizeof(ev));
7670 bacpy(&ev.addr.bdaddr, bdaddr);
7671 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007672 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007673 ev.min_interval = cpu_to_le16(min_interval);
7674 ev.max_interval = cpu_to_le16(max_interval);
7675 ev.latency = cpu_to_le16(latency);
7676 ev.timeout = cpu_to_le16(timeout);
7677
7678 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7679}
7680
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007681void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7682 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007683{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007684 char buf[512];
7685 struct mgmt_ev_device_connected *ev = (void *) buf;
7686 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007687
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007688 bacpy(&ev->addr.bdaddr, &conn->dst);
7689 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007690
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007691 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007692
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007693 /* We must ensure that the EIR Data fields are ordered and
7694 * unique. Keep it simple for now and avoid the problem by not
7695 * adding any BR/EDR data to the LE adv.
7696 */
7697 if (conn->le_adv_data_len > 0) {
7698 memcpy(&ev->eir[eir_len],
7699 conn->le_adv_data, conn->le_adv_data_len);
7700 eir_len = conn->le_adv_data_len;
7701 } else {
7702 if (name_len > 0)
7703 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7704 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007705
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007706 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007707 eir_len = eir_append_data(ev->eir, eir_len,
7708 EIR_CLASS_OF_DEV,
7709 conn->dev_class, 3);
7710 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007711
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007712 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007713
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007714 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7715 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007716}
7717
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007718static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007719{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007720 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007721
Johan Hedbergf5818c22014-12-05 13:36:02 +02007722 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007723
7724 *sk = cmd->sk;
7725 sock_hold(*sk);
7726
Johan Hedberga664b5b2011-02-19 12:06:02 -03007727 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007728}
7729
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007730static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007731{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007732 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007733 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007734
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007735 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7736
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007737 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007738 mgmt_pending_remove(cmd);
7739}
7740
Johan Hedberg84c61d92014-08-01 11:13:30 +03007741bool mgmt_powering_down(struct hci_dev *hdev)
7742{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007743 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007744 struct mgmt_mode *cp;
7745
Johan Hedberg333ae952015-03-17 13:48:47 +02007746 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007747 if (!cmd)
7748 return false;
7749
7750 cp = cmd->param;
7751 if (!cp->val)
7752 return true;
7753
7754 return false;
7755}
7756
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007757void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007758 u8 link_type, u8 addr_type, u8 reason,
7759 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007760{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007761 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007762 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007763
Johan Hedberg84c61d92014-08-01 11:13:30 +03007764 /* The connection is still in hci_conn_hash so test for 1
7765 * instead of 0 to know if this is the last one.
7766 */
7767 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7768 cancel_delayed_work(&hdev->power_off);
7769 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007770 }
7771
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007772 if (!mgmt_connected)
7773 return;
7774
Andre Guedes57eb7762013-10-30 19:01:41 -03007775 if (link_type != ACL_LINK && link_type != LE_LINK)
7776 return;
7777
Johan Hedberg744cf192011-11-08 20:40:14 +02007778 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007779
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007780 bacpy(&ev.addr.bdaddr, bdaddr);
7781 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7782 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007783
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007784 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007785
7786 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007787 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007788
Johan Hedberg124f6e32012-02-09 13:50:12 +02007789 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007790 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007791}
7792
Marcel Holtmann78929242013-10-06 23:55:47 -07007793void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7794 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007795{
Andre Guedes3655bba2013-10-30 19:01:40 -03007796 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7797 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007798 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007799
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007800 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7801 hdev);
7802
Johan Hedberg333ae952015-03-17 13:48:47 +02007803 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007804 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007805 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007806
Andre Guedes3655bba2013-10-30 19:01:40 -03007807 cp = cmd->param;
7808
7809 if (bacmp(bdaddr, &cp->addr.bdaddr))
7810 return;
7811
7812 if (cp->addr.type != bdaddr_type)
7813 return;
7814
Johan Hedbergf5818c22014-12-05 13:36:02 +02007815 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007816 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007817}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007818
Marcel Holtmann445608d2013-10-06 23:55:48 -07007819void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7820 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007821{
7822 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007823
Johan Hedberg84c61d92014-08-01 11:13:30 +03007824 /* The connection is still in hci_conn_hash so test for 1
7825 * instead of 0 to know if this is the last one.
7826 */
7827 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7828 cancel_delayed_work(&hdev->power_off);
7829 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007830 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007831
Johan Hedberg4c659c32011-11-07 23:13:39 +02007832 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007833 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007834 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007835
Marcel Holtmann445608d2013-10-06 23:55:48 -07007836 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007837}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007838
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007839void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007840{
7841 struct mgmt_ev_pin_code_request ev;
7842
Johan Hedbergd8457692012-02-17 14:24:57 +02007843 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007844 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007845 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007846
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007847 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007848}
7849
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007850void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7851 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007852{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007853 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007854
Johan Hedberg333ae952015-03-17 13:48:47 +02007855 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007856 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007857 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007858
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007859 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007860 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007861}
7862
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007863void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7864 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007865{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007866 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007867
Johan Hedberg333ae952015-03-17 13:48:47 +02007868 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007869 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007870 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007871
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007872 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007873 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007874}
Johan Hedberga5c29682011-02-19 12:05:57 -03007875
Johan Hedberg744cf192011-11-08 20:40:14 +02007876int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007877 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007878 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007879{
7880 struct mgmt_ev_user_confirm_request ev;
7881
Johan Hedberg744cf192011-11-08 20:40:14 +02007882 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007883
Johan Hedberg272d90d2012-02-09 15:26:12 +02007884 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007885 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007886 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007887 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007888
Johan Hedberg744cf192011-11-08 20:40:14 +02007889 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007890 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007891}
7892
Johan Hedberg272d90d2012-02-09 15:26:12 +02007893int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007894 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007895{
7896 struct mgmt_ev_user_passkey_request ev;
7897
7898 BT_DBG("%s", hdev->name);
7899
Johan Hedberg272d90d2012-02-09 15:26:12 +02007900 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007901 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007902
7903 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007904 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007905}
7906
Brian Gix0df4c182011-11-16 13:53:13 -08007907static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007908 u8 link_type, u8 addr_type, u8 status,
7909 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007910{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007911 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007912
Johan Hedberg333ae952015-03-17 13:48:47 +02007913 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007914 if (!cmd)
7915 return -ENOENT;
7916
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007917 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007918 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007919
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007920 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007921}
7922
Johan Hedberg744cf192011-11-08 20:40:14 +02007923int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007924 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007925{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007926 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007927 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007928}
7929
Johan Hedberg272d90d2012-02-09 15:26:12 +02007930int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007931 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007932{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007933 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007934 status,
7935 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007936}
Johan Hedberg2a611692011-02-19 12:06:00 -03007937
Brian Gix604086b2011-11-23 08:28:33 -08007938int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007939 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007940{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007941 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007942 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007943}
7944
Johan Hedberg272d90d2012-02-09 15:26:12 +02007945int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007946 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007947{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007948 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007949 status,
7950 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007951}
7952
Johan Hedberg92a25252012-09-06 18:39:26 +03007953int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7954 u8 link_type, u8 addr_type, u32 passkey,
7955 u8 entered)
7956{
7957 struct mgmt_ev_passkey_notify ev;
7958
7959 BT_DBG("%s", hdev->name);
7960
7961 bacpy(&ev.addr.bdaddr, bdaddr);
7962 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7963 ev.passkey = __cpu_to_le32(passkey);
7964 ev.entered = entered;
7965
7966 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7967}
7968
Johan Hedberge1e930f2014-09-08 17:09:49 -07007969void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007970{
7971 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007972 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007973 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007974
Johan Hedberge1e930f2014-09-08 17:09:49 -07007975 bacpy(&ev.addr.bdaddr, &conn->dst);
7976 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7977 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007978
Johan Hedberge1e930f2014-09-08 17:09:49 -07007979 cmd = find_pairing(conn);
7980
7981 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7982 cmd ? cmd->sk : NULL);
7983
Johan Hedberga511b352014-12-11 21:45:45 +02007984 if (cmd) {
7985 cmd->cmd_complete(cmd, status);
7986 mgmt_pending_remove(cmd);
7987 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007988}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007989
Marcel Holtmann464996a2013-10-15 14:26:24 -07007990void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007991{
7992 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007993 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007994
7995 if (status) {
7996 u8 mgmt_err = mgmt_status(status);
7997 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007998 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007999 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008000 }
8001
Marcel Holtmann464996a2013-10-15 14:26:24 -07008002 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07008003 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07008004 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008005 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02008006
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008007 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008008 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008009
Johan Hedberg47990ea2012-02-22 11:58:37 +02008010 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07008011 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008012
8013 if (match.sk)
8014 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008015}
8016
Johan Hedberg890ea892013-03-15 17:06:52 -05008017static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02008018{
Johan Hedberg890ea892013-03-15 17:06:52 -05008019 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008020 struct hci_cp_write_eir cp;
8021
Johan Hedberg976eb202012-10-24 21:12:01 +03008022 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05008023 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008024
Johan Hedbergc80da272012-02-22 15:38:48 +02008025 memset(hdev->eir, 0, sizeof(hdev->eir));
8026
Johan Hedbergcacaf522012-02-21 00:52:42 +02008027 memset(&cp, 0, sizeof(cp));
8028
Johan Hedberg890ea892013-03-15 17:06:52 -05008029 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02008030}
8031
Marcel Holtmann3e248562013-10-15 14:26:25 -07008032void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008033{
8034 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05008035 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008036 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008037
8038 if (status) {
8039 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008040
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008041 if (enable && hci_dev_test_and_clear_flag(hdev,
8042 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008043 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008044 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008045 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008046
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008047 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
8048 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008049 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008050 }
8051
8052 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07008053 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008054 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008055 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008056 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008057 changed = hci_dev_test_and_clear_flag(hdev,
8058 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008059 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008060 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008061 }
8062
8063 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
8064
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008065 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07008066 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008067
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02008068 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008069 sock_put(match.sk);
8070
Johan Hedberg890ea892013-03-15 17:06:52 -05008071 hci_req_init(&req, hdev);
8072
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008073 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
8074 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03008075 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
8076 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05008077 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008078 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05008079 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008080 }
Johan Hedberg890ea892013-03-15 17:06:52 -05008081
8082 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008083}
8084
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008085static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02008086{
8087 struct cmd_lookup *match = data;
8088
Johan Hedberg90e70452012-02-23 23:09:40 +02008089 if (match->sk == NULL) {
8090 match->sk = cmd->sk;
8091 sock_hold(match->sk);
8092 }
Johan Hedberg90e70452012-02-23 23:09:40 +02008093}
8094
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07008095void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
8096 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008097{
Johan Hedberg90e70452012-02-23 23:09:40 +02008098 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008099
Johan Hedberg92da6092013-03-15 17:06:55 -05008100 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
8101 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
8102 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02008103
8104 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008105 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
8106 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02008107
8108 if (match.sk)
8109 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008110}
8111
Marcel Holtmann7667da32013-10-15 14:26:27 -07008112void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02008113{
Johan Hedbergb312b1612011-03-16 14:29:37 +02008114 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008115 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008116
Johan Hedberg13928972013-03-15 17:07:00 -05008117 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07008118 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008119
8120 memset(&ev, 0, sizeof(ev));
8121 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008122 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008123
Johan Hedberg333ae952015-03-17 13:48:47 +02008124 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05008125 if (!cmd) {
8126 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02008127
Johan Hedberg13928972013-03-15 17:07:00 -05008128 /* If this is a HCI command related to powering on the
8129 * HCI dev don't send any mgmt signals.
8130 */
Johan Hedberg333ae952015-03-17 13:48:47 +02008131 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07008132 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008133 }
8134
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008135 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
8136 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008137}
Szymon Jancc35938b2011-03-22 13:12:21 +01008138
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008139static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
8140{
8141 int i;
8142
8143 for (i = 0; i < uuid_count; i++) {
8144 if (!memcmp(uuid, uuids[i], 16))
8145 return true;
8146 }
8147
8148 return false;
8149}
8150
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008151static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
8152{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008153 u16 parsed = 0;
8154
8155 while (parsed < eir_len) {
8156 u8 field_len = eir[0];
8157 u8 uuid[16];
8158 int i;
8159
8160 if (field_len == 0)
8161 break;
8162
8163 if (eir_len - parsed < field_len + 1)
8164 break;
8165
8166 switch (eir[1]) {
8167 case EIR_UUID16_ALL:
8168 case EIR_UUID16_SOME:
8169 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008170 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008171 uuid[13] = eir[i + 3];
8172 uuid[12] = eir[i + 2];
8173 if (has_uuid(uuid, uuid_count, uuids))
8174 return true;
8175 }
8176 break;
8177 case EIR_UUID32_ALL:
8178 case EIR_UUID32_SOME:
8179 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008180 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008181 uuid[15] = eir[i + 5];
8182 uuid[14] = eir[i + 4];
8183 uuid[13] = eir[i + 3];
8184 uuid[12] = eir[i + 2];
8185 if (has_uuid(uuid, uuid_count, uuids))
8186 return true;
8187 }
8188 break;
8189 case EIR_UUID128_ALL:
8190 case EIR_UUID128_SOME:
8191 for (i = 0; i + 17 <= field_len; i += 16) {
8192 memcpy(uuid, eir + i + 2, 16);
8193 if (has_uuid(uuid, uuid_count, uuids))
8194 return true;
8195 }
8196 break;
8197 }
8198
8199 parsed += field_len + 1;
8200 eir += field_len + 1;
8201 }
8202
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008203 return false;
8204}
8205
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008206static void restart_le_scan(struct hci_dev *hdev)
8207{
8208 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008209 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008210 return;
8211
8212 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8213 hdev->discovery.scan_start +
8214 hdev->discovery.scan_duration))
8215 return;
8216
8217 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8218 DISCOV_LE_RESTART_DELAY);
8219}
8220
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008221static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8222 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8223{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008224 /* If a RSSI threshold has been specified, and
8225 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8226 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8227 * is set, let it through for further processing, as we might need to
8228 * restart the scan.
8229 *
8230 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8231 * the results are also dropped.
8232 */
8233 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8234 (rssi == HCI_RSSI_INVALID ||
8235 (rssi < hdev->discovery.rssi &&
8236 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8237 return false;
8238
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008239 if (hdev->discovery.uuid_count != 0) {
8240 /* If a list of UUIDs is provided in filter, results with no
8241 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008242 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008243 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8244 hdev->discovery.uuids) &&
8245 !eir_has_uuids(scan_rsp, scan_rsp_len,
8246 hdev->discovery.uuid_count,
8247 hdev->discovery.uuids))
8248 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008249 }
8250
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008251 /* If duplicate filtering does not report RSSI changes, then restart
8252 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008253 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008254 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8255 restart_le_scan(hdev);
8256
8257 /* Validate RSSI value against the RSSI threshold once more. */
8258 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8259 rssi < hdev->discovery.rssi)
8260 return false;
8261 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008262
8263 return true;
8264}
8265
Marcel Holtmann901801b2013-10-06 23:55:51 -07008266void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008267 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8268 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008269{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008270 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008271 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008272 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008273
Johan Hedberg75ce2082014-07-02 22:42:01 +03008274 /* Don't send events for a non-kernel initiated discovery. With
8275 * LE one exception is if we have pend_le_reports > 0 in which
8276 * case we're doing passive scanning and want these events.
8277 */
8278 if (!hci_discovery_active(hdev)) {
8279 if (link_type == ACL_LINK)
8280 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008281 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008282 return;
8283 }
Andre Guedes12602d02013-04-30 15:29:40 -03008284
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008285 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008286 /* We are using service discovery */
8287 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8288 scan_rsp_len))
8289 return;
8290 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008291
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008292 /* Make sure that the buffer is big enough. The 5 extra bytes
8293 * are for the potential CoD field.
8294 */
8295 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008296 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008297
Johan Hedberg1dc06092012-01-15 21:01:23 +02008298 memset(buf, 0, sizeof(buf));
8299
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008300 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8301 * RSSI value was reported as 0 when not available. This behavior
8302 * is kept when using device discovery. This is required for full
8303 * backwards compatibility with the API.
8304 *
8305 * However when using service discovery, the value 127 will be
8306 * returned when the RSSI is not available.
8307 */
Szymon Janc91200e92015-01-22 16:57:05 +01008308 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8309 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008310 rssi = 0;
8311
Johan Hedberg841c5642014-07-07 12:45:54 +03008312 bacpy(&ev->addr.bdaddr, bdaddr);
8313 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008314 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008315 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008316
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008317 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008318 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008319 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008320
Johan Hedberg1dc06092012-01-15 21:01:23 +02008321 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8322 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008323 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008324
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008325 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008326 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008327 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008328
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008329 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8330 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008331
Marcel Holtmann901801b2013-10-06 23:55:51 -07008332 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008333}
Johan Hedberga88a9652011-03-30 13:18:12 +03008334
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008335void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8336 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008337{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008338 struct mgmt_ev_device_found *ev;
8339 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8340 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008341
Johan Hedbergb644ba32012-01-17 21:48:47 +02008342 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008343
Johan Hedbergb644ba32012-01-17 21:48:47 +02008344 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008345
Johan Hedbergb644ba32012-01-17 21:48:47 +02008346 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008347 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008348 ev->rssi = rssi;
8349
8350 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008351 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008352
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008353 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008354
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008355 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008356}
Johan Hedberg314b2382011-04-27 10:29:57 -04008357
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008358void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008359{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008360 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008361
Andre Guedes343fb142011-11-22 17:14:19 -03008362 BT_DBG("%s discovering %u", hdev->name, discovering);
8363
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008364 memset(&ev, 0, sizeof(ev));
8365 ev.type = hdev->discovery.type;
8366 ev.discovering = discovering;
8367
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008368 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008369}
Antti Julku5e762442011-08-25 16:48:02 +03008370
Marcel Holtmann1904a852015-01-11 13:50:44 -08008371static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008372{
8373 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008374}
8375
8376void mgmt_reenable_advertising(struct hci_dev *hdev)
8377{
8378 struct hci_request req;
8379
Arman Uguray24b4f382015-03-23 15:57:12 -07008380 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8381 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008382 return;
8383
8384 hci_req_init(&req, hdev);
8385 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008386 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008387}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008388
8389static struct hci_mgmt_chan chan = {
8390 .channel = HCI_CHANNEL_CONTROL,
8391 .handler_count = ARRAY_SIZE(mgmt_handlers),
8392 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008393 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008394};
8395
8396int mgmt_init(void)
8397{
8398 return hci_mgmt_chan_register(&chan);
8399}
8400
8401void mgmt_exit(void)
8402{
8403 hci_mgmt_chan_unregister(&chan);
8404}